#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()
. Это приводит к тому, что контейнер помечается для изменения компоновки его компонентов. Как только эта строка кода добавлена, она работает отлично.