Почему мой новый компонент не отображается в null layout manager?
-
02-10-2019 - |
Вопрос
Есть панель в JFrame
вызванный WatchPanel extends JPanel
который использует GroupLayout
и содержит WatchListPanel extends JPanel
.Тот Самый WatchListPanel
использует null
LayoutManager
и содержит несколько экземпляров WatchItemPanel extends JPanel
.Тот Самый WatchItemPanel
выкладывает его содержимое с помощью GridBagLayout
.
Когда я загружаю фрейм и создаю экземпляр WatchPanel
, я предварительно загружаю WatchListPanel
с тремя WatchItemPanel
экземпляры с данными.Они прекрасно работают.Моя реализация позволяет переупорядочивать их путем перетаскивания (отсюда null
макет), и это тоже работает.На WatchPanel
это кнопка для добавления новых часов, которая открывает новую панель в своем собственном JFrame
куда можно добавить часы.Когда на этой новой панели нажимается кнопка "Сохранить", она добавляет новые часы в WatchPanel
, который стекает в WatchListPanel
и закрывает JFrame
для добавления новых часов.
Проблема в том, что когда этот новый WatchItemPanel
добавляется, он не будет окрашен, если я не изменю размер JFrame
содержащий WatchPanel
.Я могу взаимодействовать с ним с помощью drag-n-drop.Я даже могу перетащить эту конкретную панель, но она пуста.В тот момент, когда я изменяю размер WatchPanel
, он отображается и нарисован правильно.
Теперь я переопределил setBounds
способ включения WatchListPanel
позвонить setSize
и repaint
на каждом из WatchItemPanel
экземпляров в списке, но я вызываю setBounds
и repaint
о новом WatchItemPanel
уже сейчас, когда я это добавляю.Я пробовал добавлять repaint
и invalidate
звонит во все мыслимые места, думая, что, может быть, я что-то пропустил, но безуспешно.Я абсолютно уверен, что добавил WatchItemPanel
к тому WatchListPanel
и позвал setBounds
, setVisible(true)
, и repaint
на новой панели.
Вот эти addWatch
и updatePositions
методы на 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(); }
И вот эти setBounds
методы по 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(); } }
Еще одна информация здесь - все четыре панели окрашиваются.Я перешел все границы paintComponent
в WatchItemPanel
и добавил System.out.println
и получил такой результат:
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=]
Что это за дополнительный столбец "недопустимый" там, на панели?Когда я изменяю размер WatchPanel
"инвалид" уходит.Хотя это выглядит как дополнительная колонка.В других строках нет соответствующего недопустимого значения.(это значение по умолчанию JPanel.toString()
вывод с удаленным именем пакета.
Решение
После добавления компонента вызовите this.revalidate()
.Это приводит к маркировке контейнера для изменения компоновки его компонентов.Как только эта строка кода добавлена, она работает безукоризненно.