Pourquoi mon nouveau composant n'affiche dans un gestionnaire de mise en page null?
-
02-10-2019 - |
Question
Il y a un panneau dans un JFrame
appelé WatchPanel extends JPanel
qui utilise un GroupLayout
et contient un WatchListPanel extends JPanel
. Le WatchListPanel
utilise un null
de LayoutManager
et contient plusieurs instances de WatchItemPanel extends JPanel
. Le WatchItemPanel
expose son contenu avec un GridBagLayout
.
Quand je charge le châssis et instancier les WatchPanel
, je précharger le WatchListPanel
avec trois instances de WatchItemPanel
avec des données. Ces travaux très bien. Ma mise en œuvre permet de les réordonner par glisser-déposer (d'où la mise en page de null
), et qui fonctionne aussi bien. Sur le WatchPanel
est un bouton pour ajouter une nouvelle montre, qui fait apparaître un nouveau panneau dans son propre JFrame
où une montre peut être ajouté. Lorsque le bouton « Enregistrer » est pressé sur ce nouveau panneau, il ajoute la nouvelle montre à la WatchPanel
, qui ruisselle dans le WatchListPanel
et ferme la JFrame
pour ajouter une nouvelle montre.
Le problème est que lorsque ce nouveau WatchItemPanel
est ajouté, il ne soit pas peint à moins que je redimensionnez la JFrame
contenant le WatchPanel
. Je peux communiquer avec elle par glisser-déposer. Je peux même faire glisser ce panneau spécifique - mais il est vide. Au moment où je redimensionner la WatchPanel
, il apparaît et est peint correctement.
Maintenant, je l'ai substituée la méthode setBounds
sur WatchListPanel
à l'appel setSize
et repaint
sur chacune des instances de WatchItemPanel
dans la liste, mais je fais appel setBounds
et repaint
sur le nouveau WatchItemPanel
déjà que je l'ajoute. Je l'ai essayé d'ajouter repaint
et appels invalidate
dans toutes la pensée concevable place peut-être je raté quelque chose, mais pas de chance. Je absolument ai ajouté le WatchItemPanel
au WatchListPanel
et appelé setBounds
, setVisible(true)
et repaint
sur le nouveau panneau.
Voici les méthodes de addWatch
et updatePositions
sur le 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(); }
Et voici les méthodes de setBounds
sur 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(); } }
Un autre élément d'information ici - les quatre panneaux sont en cours de peinture. Je l'emportaient sur paintComponent
dans le WatchItemPanel
et a ajouté un System.out.println
et a obtenu ce résultat:
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=]
Qu'est-ce que la colonne supplémentaire « invalide » il dans le panneau? Quand je redimensionnez la WatchPanel
la « invalide » va. Il ressemble à une colonne supplémentaire, cependant. Il n'y a pas valeur non valide correspondante sur les autres lignes. (Ce qui est la sortie de JPanel.toString()
par défaut avec le nom du paquet supprimé.
La solution
Après avoir ajouté le composant, appel this.revalidate()
. Cela provoque le récipient à marquer à nouveau la présentation de ses composants. Une fois cette ligne de code est ajouté, il fonctionne parfaitement.