Aus der actionPerformed-Methode andere Methode aufrufen funktioniert nicht


#1

Hallo zusammen,

ich versuche gerade aus der actionPerformed-Methode eine andere Methode aufzurufen die sich in der selben Klasse befindet.
In der actionPerformed-Methode frage ich zuerst mit einer if-Anweisung ab, ob der Button gedrückt wurde oder nicht.
Wenn er gedrückt wurde soll die Methode aufgerufen werden.
Leider passiert nichts wenn ich den Button drücke.
Wenn ich darunter ein “System.out.println(“Text”);” schreibe und den Button drücke, dann wird der Text ausgegeben. Das heißt der Button funktioniert.
Wenn ich die Methode im standard Konstruktor der Klasse aufrufe, dann funktioniert die Methode auch.
Nur wenn ich sie aus der actionPerformed aufrufe geht nichts.

Bekomme beim starten aber auch keine Fehlermeldung von Eclipse.

Was mache ich falsch?

MfG


#2

Das ist ein gerne genommenes GUI-Anfängerproblem - du missachtest Regeln des Event-Dispatch-Threads. Eine davon lautet, dass du keine Methoden aufrufen kannst, die die Anzeige ändern, denn diese wird ja gerade aufgebaut. Wenn du also per ActionListener etwas sichtbar macchen willst, dann musst du in actionPerformed einen Status setzen, welchen du im nächsten Paint-Zyklus abfragst und entsprechend reagierst.


#3

Die Antwort ^ ist schon SEHR wild geraten, so ganz ohne code…


#4

Geraten ja, aber keinesfalls wild. Die Symptome hat er ja recht gut beschrieben.

Aber dennoch… Code wäre natürlich nicht schlecht und ich denke mal, der kommt auch, wenn ich unrecht habe.


#5

[quote=“Javaman1991, post:1, topic:19314, full:true”]
In der actionPerformed-Methode frage ich zuerst mit einer if-Anweisung ab, ob der Button gedrückt wurde oder nicht.

[…]

Was mache ich falsch?[/quote]

Auch wenn das nicht zu deinem Problem beiträgt, scheint es mir, als würdest du hier nicht einen einzelnen ActionListener nur am Button benutzen, wenn du abfragen musst, was den Actionlistener ausgelöst hat, und das ist nicht so gut.

Beispiel:

    JButton button = new JButton("Beenden");
    button.addActionListener(e -> quit());

Beim Druck auf den Button wird die Methode quit() aufgerufen.

Oder auch ausgeschrieben:

    JButton button = new JButton("Beenden");
    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            quit();
        }
    });

#6

Hallo Leute,

ich habe es mit “validate();” in der jeweiligen Methode realisiert.

Mit repaint(); funktioniert es interessanterweise nicht.

repaint(); -> zeichnet ja alles neu
validate(); -> berechnet nur das Layout neu

Eigentlich müsste ja beides funktionieren, oder?

Danke für die Hilfe.

MfG


#7

Dachte ich es mir doch…

repaint verwendet man bei Panels, von denen man die Paint(Component)-Methode überschreibt und dann arbeitet man mit besagten States, die man in der Paint-Methode abfragt.

bei UI-Elementen genügt ein revalidate, also invalidate und validate hintereinander - wobei ich aber nicht weiß, welchen Sinn invalidate macht (ich programmiere so selten anspruchsvolle GUIs).


#8

Was jetzt genau der unterschied zwischen:

validate();
invalidate();
revalidate();
repaint();

ist würde mich auch interessieren?

Weiß das vielleicht jemand?

Im Netz finde ich keine klare Antwort darauf.

Ein kleines Problem besteht noch immer bei meinem Programm.

Ich habe ja 3 JPanels die jeweils mit Buttons gefüllt werden.
Zum testen habe ich für die Buttons farben vergeben.
Die farben der Button unterscheiden sich von JPanel zu JPanel.

Wenn ich nun das erste JPanel anzeigen lasse am JFrame, dann haben alle Buttons des JPanel z.B. die farbe Rot.
Wenn ich nun das andere JPanel anzeigen lasse, dann haben die ganzen Buttons die Farbe blau.

Soweit alles gut.

Sobald ich aber mit dem Mauszeiger über die Buttons fahre werden diese wieder rot??
Ich fahre einfach nur drüber, ohne zu klicken.
Aber immer nur der Button über den ich gerade mit dem Mauszeiger bin ändert die Farbe.
Die anderen behalten solange die Farbe, bis der Mauszeiger über sie fährt.

Warum??

Ich komme einfach nicht dahinter.


#9

Das ist der Punkt, an dem auch ich ohne Code nicht weiterkomme.

Die Unterschiede zwischen den Methoden sind, dass bei Validation geprüft wird, ob und was in einem Container neugezeichnet werden muss und bei repaint wird definitiv neugezeichnet.

Um validiert werden zu können, müssen Componenten invalidiert sein. Wie das Ganze genau funktioniert, ist von der Codeanalyse der API recht undurchsichtig. Vllt. bringts ja was, wenn du statt validate revalidate aufrufst - diesmal tatsächlich nur ins Blaue geraten.


#10

Ich habe einiges schon probiert.

Ich habe alle drei Varianten durchprobiert.
Ich habe es auch mit setVisible(); versucht.
Zuerst auf false und danach auf true gesetzt, damit alles neu gezeichnet wird.

Funktioniert auch nicht.

Es ist so, als würde er über das erste JPanel das zweite drüber setzen aber nur auf das erste reagieren.

Irgendwie müsste ich das alte entfernen, wenn das neue JPanel erzeugt wird.

Gibt es eine Methode, das ich das alte JPanel entfernen kann?

Ich habe es auch mit: SwingUtilities.updateComponentTreeUI(frame); probiert.

Auch kein Erfolg.

MfG


#11

Die Methoden sorgen tatsächlich immer wieder für Verwirrung, und ich muss zugeben, dass es gelegentlich mal Corner-Cases gibt, wo das Verhalten etwas unerwartet ist. Aber zur groben Einordnung:

  • repaint Bewirkt nur, dass die Component “so bald wie möglich” neu gezeichnet wird. Das hat nichts mit dem Layout o.ä. zu tun. Insbesondere reicht ein repaint demnach nicht aus, wenn man das Layout geändert hat
  • invalidate braucht man praktisch nie (das wird bei einigen Sachen intern aufgerufen)
  • validate ist das, was man üblicherweise macht, wenn man das Layout verändert hat. Wenn man also z.B. durch einen Buttonklick ein JLabel auf einem JPanel hinzufügt, muss man danach panel.validate() aufrufen, damit das Layout aktualisiert wird. Wichtig: “Oft” braucht man noch ein panel.repaint() dazu. Das sollte eigentlich nicht nötig sein, aber … es gibt immer mal wieder Glitches, wenn man es wegläßt, und es schadet schlicht nicht.
  • Methoden mit update...UI (also auch updateUI selbst) braucht man auch praktisch nie - außer, wenn man zur Laufzeit am Look&Feel rumpfuscht…

Dem letzten Beitrag nach (mit “altes Panel entfernen, neues hinzufügen”) klingt, als könnte https://docs.oracle.com/javase/tutorial/uiswing/layout/card.html eine Lösung sein. Es kann aber auch OK sein, sowas zu machen wie

container.remove(oldPanel);
container.add(newPanel);
container.validate();
container.repaint();

#12

[quote=“Marco13, post:11, topic:19314”]container.remove(oldPanel);
container.add(newPanel);
container.validate();
container.repaint();
[/quote]

Mit

container.remove(oldPanel); container.add(newPanel); container.revalidate(); container.repaint();
sorgt man auch noch dafür, dass tatsächlich alles validiert wird, also auch das, was zwar verändert aber dadurch nicht invalidiert wurde. Ist wie bei repaint - es gibt immer mal wieder Glitches…

Es kann weder sichergestellt werden, ob beim Aufruf von doLayout (über validate) repaint noch invalidate beim Ändern einer Component aufgerufen wird. Es gibt afaik auch keine Konvention, die das klar regelt.


#13

Habe das Problem gelöst.

Ich habe jetzt nur ein JPanel, auf dem ich nur die jeweiligen Buttons erstelle.
Wenn ich nun die anderen Buttons haben möchte, wo ich ursprünglich das JPanel gewechselt habe, dann werden die alten Buttons einfach gelöscht und die neuen gezeichnet.

Ich lösche alle Buttons einfach mit JPanel.removeAll();

Funktioniert einwandfrei.

Danke!

MfG


#14

Möglich wären auch zwei Cards, so dass du einfach zwischen diesen umschaltest.