Почему мой новый компонент не отображается в null layout manager?

#java #swing #null-layout-manager

#java #swing #null-layout-manager

Вопрос:

В a есть панель, JFrame называемая a WatchPanel extends JPanel , которая использует a GroupLayout и содержит a 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 метод on WatchListPanel для вызова setSize и repaint для каждого из WatchItemPanel экземпляров в списке, но я вызываю setBounds and repaint для нового WatchItemPanel уже при его добавлении. Я пробовал добавлять вызовы repaint и invalidate во всех мыслимых местах, думая, может быть, я что-то пропустил, но безуспешно. Я абсолютно точно добавил WatchItemPanel в WatchListPanel и вызвал setBounds , setVisible(true) и repaint на новой панели.

Вот методы addWatch и updatePositions в WatchListPanel :

public void addWatch (Смотреть просмотр) {
 WatchItemPanel watchPanel = новая WatchItemPanel(смотреть);
 синхронизировано (это.наблюдает) { 
 это.watches.add(смотреть);
 } 
 это.watchPanels.put(смотреть, watchPanel);
 this.add(watchPanel);
 watchPanel.setOpaque(false);
 watchPanel.setForeground(this.getForeground());
 watchPanel.setBackground(this.getBackground());
 watchPanel.setVisible(истина);
 watchPanel.setSize(this.getWidth(), WatchItemPanel.PANEL_HEIGHT);
 для (MouseListener l: this.MouseListeners)
 watchPanel.addMouseListener(l);
 для (MouseMotionListener l: this.mouseMotionListeners)
 watchPanel.addMouseMotionListener(l);
 this.updatePositions();
}

private void updatePositions() { 
 количество входных данных = 0;
 синхронизировано (это.наблюдает) { 
 для (Смотрите watch: this.наблюдает) {
 if ((this.selectedWatchPanel != null) amp;amp; (count == this.selectedWatchPanelPosition))
 количество   ;
 WatchItemPanel панель = это.watchPanels.get(смотреть);
 if (panel == this.selectedWatchPanel) 
 продолжить;
 panel.setBounds(0, count * WatchItemPanel.PANEL_HEIGHT, this.getWidth(), WatchItemPanel.PANEL_HEIGHT);
 количество   ;
 }
 } 
 если (this.selectedWatchPanel != null)
 this.selectedWatchPanel.setBounds(0, (this.selectedWatchPanelPosition * WatchItemPanel.PANEL_HEIGHT)   this.selectedWatchPanelDragOffset, this.getWidth(), WatchItemPanel.PANEL_HEIGHT);
 this.repaint(); 
}

И вот setBounds методы на WatchListPanel :

@Override 
общедоступные пустые заданные границы (прямоугольник r) { 
 super.setBounds(r);
 для (панель WatchItemPanel: this.watchPanels.values()) { 
 panel.setSize(r.width, WatchItemPanel.PANEL_HEIGHT);
 panel.repaint();
 }
}

@Override 
общедоступные пустые заданные границы (int x, int y, int width, int height) { 
 super.setBounds(x, y, width, height);
 для (панель WatchItemPanel: this.watchPanels.values()) { 
 panel.setSize(ширина, 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() с удаленным именем пакета.

Ответ №1:

После добавления компонента вызовите this.revalidate() . Это приводит к тому, что контейнер помечается для изменения компоновки его компонентов. Как только эта строка кода добавлена, она работает отлично.