PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Java Swing] Problem mit Repaints


Monger
2005-10-22, 22:04:36
Servus,

ich bastel gerade mehr schlecht als recht an einer Swing Oberfläche rum. Ich habe ein JFrame, dass verschiedene JPanels enthält. Die JPanels werden bei bestimmten Ereignissen gegen andere ausgetauscht, die enthaltenen Elemente wie Buttons o.ä. ergänzt oder gelöscht usw.


Mein Problem ist, dass in bestimmten Situationen der Fensterinhalt nicht erneut gemalt wird. Ich muss dann erst z.B. die Fenstergröße ändern, damit er wieder alles zeichnet. In anderen Fällen funktioniert es aber tadellos, aber ich kann keinen Grund dafür erkennen.

Kann mir jemand irgendwelche Tipps geben? repaint() habe ich schon ausprobiert, aber egal wie spät ich es aufrufe - es scheint keinen Unterschied zu machen.

Gast
2005-10-22, 22:24:27
Das Problem ist, wenn Du neue JComponents hinzufügst, Swing noch nicht deren Dimension kennt und sie auch nicht zeichnen kann.
Du solltest die pack()-Methode aufrufen, dann erst wird das Layout aller Komponenten komplett berechnet.

lg
Michl

HellHorse
2005-10-23, 09:41:27
ich bastel gerade mehr schlecht als recht an einer Swing Oberfläche rum. Ich habe ein JFrame, dass verschiedene JPanels enthält. Die JPanels werden bei bestimmten Ereignissen gegen andere ausgetauscht, die enthaltenen Elemente wie Buttons o.ä. ergänzt oder gelöscht usw.
Das tönt recht kompliziert. Geht es nicht auf einfacher mittels CardLayout und #setVisible(true/false)?

Kann mir jemand irgendwelche Tipps geben? repaint() habe ich schon ausprobiert, aber egal wie spät ich es aufrufe - es scheint keinen Unterschied zu machen.
#repaint() funktioniert garantiert nicht. Es müsste entweder #revalidate(), #invalidate(), #validate() oder #validateTree() sein (auf dem Komponenten, dem Komponenten hinzugefügt oder entfernt wurden). Weiss gerade nicht mehr welches. Musst halt ausprobieren oder FM lesen.

Das Problem ist, wenn Du neue JComponents hinzufügst, Swing noch nicht deren Dimension kennt und sie auch nicht zeichnen kann.
Du solltest die pack()-Methode aufrufen, dann erst wird das Layout aller Komponenten komplett berechnet.
#pack() von Frame, welches die Fenstergrösse anpasst? Das glaub ich nicht Tim.

Gast
2005-10-23, 16:34:03
In der javadoc zu Component.add() steht folgendes:

/**
* Appends the specified component to the end of this container.
* This is a convenience method for {@link #addImpl}.
* <p>
* Note: If a component has been added to a container that
* has been displayed, <code>validate</code> must be
* called on that container to display the new component.

oder auch Container.validate():

* The <code>validate</code> method is used to cause a container
* to lay out its subcomponents again. It should be invoked when
* this container's subcomponents are modified (added to or
* removed from the container, or layout-related information
* changed) after the container has been displayed.

Folgendes Beispiel-Programm verdeutlicht es:


import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

/**
* RepaintProblem from forum.3dcenter
* http://www.forum-3dcenter.org/vbulletin/showthread.php?t=255541
*
*
* @author michl
*
*/
public class RepaintProblem implements ActionListener {

private JFrame frame;
private JPanel[] panel = new JPanel[2];
private JButton[] button = new JButton[2];
private JButton switchButton1, switchButton2;
private int panelIdx = 0;
/**
* Konstruktor
*
*/
public RepaintProblem() {
frame = new JFrame("RepaintProblem");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());

for (int i=0; i<2; i++) {
button[i] = new JButton("panel "+i);
panel[i] = new JPanel();
panel[i].add(button[i]);
}

switchButton1 = new JButton("Switch with pack");
switchButton1.addActionListener(this);
switchButton2 = new JButton("Switch w/o pack");
switchButton2.addActionListener(this);

frame.add(panel[0]);
frame.add(switchButton1, BorderLayout.SOUTH);
frame.add(switchButton2, BorderLayout.NORTH);
frame.pack();
frame.setVisible(true);
}

/**
* Ein Button wurde gedrückt.
* @param e der Event
*/
public void actionPerformed(ActionEvent e) {

frame.remove(panel[panelIdx]);
frame.add(panel[(panelIdx+1) % 2]);

if (e.getSource() == switchButton1) {
frame.pack();
}
frame.repaint();

panelIdx = (panelIdx+1) % 2;
}

/**
* die main-Methode
* @param args CommandLine-Argumente
*/
public static void main(String[] args) {
new RepaintProblem();
}
}


Wenn man zuerst "Switch w/o pack" drückt, verwschwindet Panel0, aber
panel1 wird nicht angezeigt. Bei "Switch with pack" funktioniert es.

michl

michl
2005-10-23, 16:55:04
Liebe Leute!

Habe mich jetzt registriert, somit bin ich kein Gast mehr. :smile:

Und das Forum finde ich echt spitze.

michl

Monger
2005-10-23, 16:59:29
OK, da war ich auf dem völlig falschen Dampfer. Thx für die Info.

Zu Thema #pack() vom JFrame: Das wird von Window geerbt, und enthält folgende Beschreibung:

Causes this Window to be sized to fit the preferred size and layouts of its subcomponents. If the window and/or its owner are not yet displayable, both are made displayable before calculating the preferred size. The Window will be validated after the preferredSize is calculated.


#pack() ist also ein bißchen mit Kanonen auf Spatzen geschossen, wenn man nur einzelne Bereiche im Fenster neu zeichnen will. Ich kanns aber trotzdem gebrauchen, weil ich auch JDialog Elemente habe.

@Hellhorse: In meinem Fall wäre ein CardLayout ein bißchen übertrieben, weil ich derzeit nur ein einziges Mal einen Wechsel durchführe. Aber trotzdem ist dieses CardLayout ziemlich interessant. Bis jetzt kannte ich das gar nicht, also wieder was für die Zukunft gelernt! :D

Senior Sanchez
2005-10-24, 10:53:56
OK, da war ich auf dem völlig falschen Dampfer. Thx für die Info.

Zu Thema #pack() vom JFrame: Das wird von Window geerbt, und enthält folgende Beschreibung:


#pack() ist also ein bißchen mit Kanonen auf Spatzen geschossen, wenn man nur einzelne Bereiche im Fenster neu zeichnen will. Ich kanns aber trotzdem gebrauchen, weil ich auch JDialog Elemente habe.

@Hellhorse: In meinem Fall wäre ein CardLayout ein bißchen übertrieben, weil ich derzeit nur ein einziges Mal einen Wechsel durchführe. Aber trotzdem ist dieses CardLayout ziemlich interessant. Bis jetzt kannte ich das gar nicht, also wieder was für die Zukunft gelernt! :D


Also bei mir funzt validateTree() ;)
Ich hatte auch mal mit nem CardLayout rumgebastelt und nach ner langen Qual hats dann geklappt, aber es war wie in deinem Fall unnötig. Daraufhin habe ich es dann so geändert, dass einfach das Panel ausgetauscht wird.