Warum wird meine neue Komponente nicht in einem Null-Layout-Manager angezeigt werden?
-
02-10-2019 - |
Frage
Es ist eine Platte in einem JFrame
ein WatchPanel extends JPanel
genannt, die eine GroupLayout
verwendet und enthält eine WatchListPanel extends JPanel
. Die WatchListPanel
verwendet eine null
LayoutManager
und enthält mehrere Instanzen von WatchItemPanel extends JPanel
. Die WatchItemPanel
legt seinen Inhalt mit einem GridBagLayout
.
Wenn ich den Rahmen einlegen und die WatchPanel
instanziiert, ich die WatchListPanel
mit drei WatchItemPanel
Instanzen mit Daten vorab laden. Diese arbeiten gut. Meine Implementierung ermöglicht diese durch Ziehen und Ablegen (daher das null
Layouts) neu geordnet werden, und das funktioniert auch. Auf der WatchPanel
ist eine Schaltfläche, um eine neue Uhr fügen, die bis eine neue Platte in ihrer eigenen JFrame
erscheint, wo eine Uhr hinzugefügt werden kann. Wenn die Schaltfläche „Speichern“ auf dieser neuen Platte gedrückt wird, fügt es die neue Uhr auf die WatchPanel
, die in den WatchListPanel
rieselt nach unten und schließt die JFrame
für eine neue Uhr hinzufügen.
Das Problem ist, dass, wenn dieser neue WatchItemPanel
hinzugefügt wird, ist es nicht gemalt bekommen, wenn ich die JFrame
die Größe des WatchPanel
enthält. Ich kann damit durch Drag-and-Drop in Wechselwirkung treten. Ich kann sogar, dass bestimmte Panel ziehen - aber es ist leer. Der Moment, als ich die WatchPanel
Größe ändern, es erscheint und korrekt gezeichnet.
Jetzt habe ich die setBounds
Methode auf WatchListPanel
zu Anruf setSize
und repaint
auf jedem der WatchItemPanel
Instanzen in der Liste außer Kraft gesetzt, aber ich rufe setBounds
und repaint
auf den neuen WatchItemPanel
schon, wie ich es hinzufügen. Ich habe repaint
und invalidate
Anrufe in jedem denkbaren Ort Denken versucht, das Hinzufügen vielleicht habe ich etwas verpasst, aber kein Glück. Ich habe absolut die WatchItemPanel
zum WatchListPanel
und rief setBounds
, setVisible(true)
und repaint
auf das neue Panel hinzugefügt.
Hier sind die addWatch
und updatePositions
Methoden auf dem WatchListPanel
:
public void addWatch(Watch watch) { WatchItemPanel watchPanel = new WatchItemPanel(watch); synchronized (this.watches) { this.watches.add(watch); } this.watchPanels.put(watch, watchPanel); this.add(watchPanel); watchPanel.setOpaque(false); watchPanel.setForeground(this.getForeground()); watchPanel.setBackground(this.getBackground()); watchPanel.setVisible(true); watchPanel.setSize(this.getWidth(), WatchItemPanel.PANEL_HEIGHT); for (MouseListener l: this.mouseListeners) watchPanel.addMouseListener(l); for (MouseMotionListener l: this.mouseMotionListeners) watchPanel.addMouseMotionListener(l); this.updatePositions(); } private void updatePositions() { int count = 0; synchronized (this.watches) { for (Watch watch: this.watches) { if ((this.selectedWatchPanel != null) && (count == this.selectedWatchPanelPosition)) count++; WatchItemPanel panel = this.watchPanels.get(watch); if (panel == this.selectedWatchPanel) continue; panel.setBounds(0, count * WatchItemPanel.PANEL_HEIGHT, this.getWidth(), WatchItemPanel.PANEL_HEIGHT); count++; } } if (this.selectedWatchPanel != null) this.selectedWatchPanel.setBounds(0, (this.selectedWatchPanelPosition * WatchItemPanel.PANEL_HEIGHT) + this.selectedWatchPanelDragOffset, this.getWidth(), WatchItemPanel.PANEL_HEIGHT); this.repaint(); }
Und hier sind die setBounds
Methoden auf WatchListPanel
:
@Override public void setBounds(Rectangle r) { super.setBounds(r); for (WatchItemPanel panel: this.watchPanels.values()) { panel.setSize(r.width, WatchItemPanel.PANEL_HEIGHT); panel.repaint(); } } @Override public void setBounds(int x, int y, int width, int height) { super.setBounds(x, y, width, height); for (WatchItemPanel panel: this.watchPanels.values()) { panel.setSize(width, WatchItemPanel.PANEL_HEIGHT); panel.repaint(); } }
Ein weiteres Stück von Informationen hier - alle vier Tafeln gemalt werden. Ich overrode paintComponent
im WatchItemPanel
und System.out.println
und bekam dieses Ergebnis hinzugefügt:
WatchItemPanel[,0,66,366x22,invalid,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=] WatchItemPanel[,0,44,366x22,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=] WatchItemPanel[,0,22,366x22,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=] WatchItemPanel[,0,0,366x22,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=]
Was ist das extra „ungültig“ Spalte in der Platte dort? Als ich die WatchPanel
die „ungültig“ die Größe weggeht. Es sieht aus wie eine zusätzliche Spalte, though. Es gibt keinen entsprechenden nicht ungültigen Wert auf den anderen Linien. (Dies ist die Standardeinstellung JPanel.toString()
Ausgang mit dem Paketnamen entfernt.
Lösung
Nach der Komponente Aufruf this.revalidate()
hinzufügen. Dies bewirkt, dass der Behälter wieder das Layout seiner Komponenten zu kennzeichnen. Sobald diese Zeile Code hinzugefügt wird, es funktioniert perfekt.