¿Por qué mi nuevo componente no aparece en un controlador de distribución nula?
-
02-10-2019 - |
Pregunta
Hay un panel en un JFrame
llamado WatchPanel extends JPanel
que utiliza un GroupLayout
y contiene una WatchListPanel extends JPanel
. El WatchListPanel
utiliza un null
LayoutManager
y contiene varios casos de WatchItemPanel extends JPanel
. El WatchItemPanel
expone su contenido con un GridBagLayout
.
Cuando cargo hasta el bastidor y una instancia de la WatchPanel
, I pre-cargar el WatchListPanel
con tres casos WatchItemPanel
con datos. Estos funcionan bien. Mi aplicación permite que éstos se vuelvan a ordenar arrastrando y soltando (de ahí el diseño null
), y que funciona tan bien. Por WatchPanel
es un botón para añadir un nuevo reloj, lo que abrirá un nuevo panel en su propia JFrame
donde se puede añadir un reloj. Cuando se pulsa el botón "Guardar" en este nuevo panel, se añade el nuevo reloj de la WatchPanel
, que se escurre hacia abajo en el WatchListPanel
y cierra la JFrame
para añadir un nuevo reloj.
El problema es que cuando se añade este nuevo WatchItemPanel
, que no consigue pintado a menos puedo cambiar el tamaño de la JFrame
que contiene el WatchPanel
. Puedo interactuar con él a través de arrastrar y soltar. Incluso puedo arrastrar ese panel específico - pero es en blanco. En el momento que cambie el tamaño del WatchPanel
, lo que parece y se pinta correctamente.
Ahora, he anulado el método setBounds
en WatchListPanel
a setSize
llamada y repaint
en cada uno de los casos WatchItemPanel
en la lista, pero estoy llamando setBounds
y repaint
en el nuevo WatchItemPanel
como ya lo añado. He intentado agregar repaint
y invalidate
llamadas en cada lugar concebible pensar que tal vez haya perdido algo, pero no hubo suerte. Absolutamente añadido el WatchItemPanel
a la llamada y WatchListPanel
setBounds
, setVisible(true)
y repaint
en el nuevo panel.
Aquí son los métodos addWatch
y updatePositions
en la 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(); }
Y aquí están los métodos setBounds
en 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(); } }
Otra pieza de información aquí - los cuatro paneles están siendo pintado. Me hizo caso omiso de paintComponent
en el WatchItemPanel
y añadí un System.out.println
y obtuve este resultado:
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é es esa columna extra "no válido" existe en el panel? Cuando cambio el tamaño de la WatchPanel
el "no válido" desaparece. Se ve como una columna adicional, sin embargo. No hay valor no válido correspondiente en las otras líneas. (Esta es la salida JPanel.toString()
defecto con el nombre del paquete eliminado.
Solución
Después de añadir el componente, this.revalidate()
llamada. Esto hace que el recipiente sea marcada para componentes re-diseño de su. Una vez que se añade esta línea de código, funciona perfectamente.