Ich arbeite an einem Skript, das JDialogs nacheinander auftaucht, um den Benutzer zu bitten, Informationen auf dem Bildschirm (z. B. Felder um ein Menü) zu erfassen usw.), so dass das Programm danach automatisch an die Stelle klickt, an der ich es angegeben habe.Java - Benutzerdefinierte JDialog dispose-Methode mehr als einmal aufgerufen - das ist nicht beabsichtigt
Das Problem, auf dem ich derzeit feststecke, ist, dass, wenn ich meinen benutzerdefinierten JDialog schließe, die dispose-Methode anscheinend mehrmals aufgerufen wird, obwohl ich keine Ahnung habe, warum.
Hier ist ein komplettes Arbeitsbeispiel der Ausgabe:
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Main {
// Creates the main frame (MainForm extends JFrame)
private static MainForm mainForm = new MainForm();
public static void main(String[] args) {
mainForm.setVisible(true);
}
static class BaseDialog extends JDialog {
BaseDialog() {
super();
setModal(true);
}
// Overrides and calls (super)dispose method of JDialog - Nothing unusual
@Override
public void dispose() {
Exception e = new Exception();
e.printStackTrace();
System.out.println("disposing");
super.dispose();
}
}
static class CaptureDialog extends BaseDialog implements ActionListener {
CaptureDialog() {
super();
JButton btnInventory = new JButton("Close Me");
btnInventory.addActionListener(this);
add(btnInventory);
setTitle("Recapture");
setModalityType(ModalityType.APPLICATION_MODAL);
setLocationRelativeTo(null);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setResizable(false);
setSize(200, 80);
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked the button!");
dispose();
}
}
static class MainForm extends JFrame implements ActionListener {
MainForm() {
super("Example");
JButton btnCapture = new JButton();
btnCapture.setText("Capture");
btnCapture.addActionListener(this);
add(btnCapture);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setSize(200, 80);
}
// Only one button is added to action listener ('if' not necessary)
@Override
public void actionPerformed(ActionEvent e){
new CaptureDialog();
}
}
}
Das Problem ist offensichtlich, wenn ich die Anwendung ausführen und dann öffnen und schließen/den Dialog entsorgen. Mit der Platzierung des Exception e unter BaseDialog ‚s‚entsorgen‘Methode, die ich folgende Ausgabe beim Schließen durch das Fenster‚X‘Taste (Weglassen interne Anrufe):
java.lang.Exception
at Main$BaseDialog.dispose(Main.java:24)
at javax.swing.JDialog.processWindowEvent(JDialog.java:691)
at java.awt.Window.processEvent(Window.java:2017)
at java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:184)
at java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:229)
at java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:227)
at java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:227)
at java.awt.Dialog.show(Dialog.java:1084)
at java.awt.Component.show(Component.java:1673)
at java.awt.Component.setVisible(Component.java:1625)
at java.awt.Window.setVisible(Window.java:1014)
at java.awt.Dialog.setVisible(Dialog.java:1005)
at Main$CaptureDialog.<init>(Main.java:46)
at Main$MainForm.actionPerformed(Main.java:71)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
disposing
disposing
java.lang.Exception
at Main$BaseDialog.dispose(Main.java:24)
at java.awt.Window.disposeImpl(Window.java:1161)
at java.awt.Window$1DisposeAction.run(Window.java:1189)
at java.awt.Window.doDispose(Window.java:1210)
at java.awt.Window.dispose(Window.java:1151)
at javax.swing.SwingUtilities$SharedOwnerFrame.dispose(SwingUtilities.java:1814)
at javax.swing.SwingUtilities$SharedOwnerFrame.windowClosed(SwingUtilities.java:1792)
at java.awt.Window.processWindowEvent(Window.java:2061)
at javax.swing.JDialog.processWindowEvent(JDialog.java:683)
at java.awt.Window.processEvent(Window.java:2017)
Beachten Sie auch, dass, wenn Wenn Sie die Anwendung ausführen und das Dialogfeld wiederholt öffnen, wird die Methode um 1 inkrementiert (am besten sichtbar, wenn Sie die ersten beiden Zeilen unter der überschriebenen Methode "dispose" in Bezug auf die Ausnahme stacktrace drucken auskommentieren und die Ausgabe beobachten).
Hier ist eine hard-stripped-Version, wenn Sie im Voraus verwenden/sehen und danken möchten!
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Main {
public static void main(String[] args) {
new MainForm();
}
static class BaseDialog extends JDialog {
BaseDialog() {
super();
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setVisible(true);
}
@Override
public void dispose() {
new Exception().printStackTrace();
System.out.println("disposing");
super.dispose();
}
}
static class MainForm extends JFrame implements ActionListener {
MainForm() {
super();
JButton btnCapture = new JButton();
btnCapture.setText("Capture");
btnCapture.addActionListener(this);
add(btnCapture);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(200, 80);
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e){
new BaseDialog();
}
}
}
Möglicherweise nützliche Informationen:
- Weglassen ‚super.dispose()‘ Ursachen ‚verfügen‘ nur einmal aufgerufen werden - der Anwendungscode nicht das Problem sein sollte.
- Wenn ich JFrame anstelle von JDialog (in Bezug auf BaseDialog-Klasse) erweitern, wird die dispose-Methode ordnungsgemäß (mit super.dispose()) aufgerufen.
- Sortieren von irrelevanten, aber ein 'Hack' ist ein privates Feld unter der BaseDialog Klasse zu machen:
-> Privater boolean angeordnet = false;
Und dann einen Scheck, wenn die Dispose-Methode aufrufen:
@Override
public void dispose() {
if (!disposed) {
disposed = true;
super.dispose();
}
}
Während es das Problem lösen kann aber weit von einer guten Antwort ist und zukünftige Probleme existieren können leicht, da der Kern nicht richtig festgelegt ist.
Ich konnte nicht antworten, aber jetzt bin ich hier. Ich habe den Code neu formatiert (was ich gestern nicht schnell genug machen konnte, da ich aufstehen musste und es satt hatte, das Problem zu beheben) und ein kurzes, funktionierendes Beispiel hochgeladen. Jetzt sollte es nicht mehr so verwirrend sein wie zuvor. – Smokesick
Drucken Sie den 'hashCode()' aus der Dispose-Methode aus, um zu sehen, welche Instanzen aufgerufen werden. Jedes Mal, wenn die neue Instanz zweimal aufgerufen wird und jede ältere Instanz einmal aufgerufen wird. –
Möglicherweise müssen Sie in den Quellcode eintauchen, um dies zu lösen, da ich noch keinen Grund für sein Auftreten sehe. –