Java Swing – как показать панель поверх другой панели?

Я хочу иметь внутреннее (не окно) диалоговое окно для запроса ввода элемента. Я хотел бы, чтобы диалог был размещен централизованно на существующей JPanel.

Я посмотрел на слоистые панели, и они кажутся непригодными из-за того, что на всех панелях имеется только один менеджер компоновки (или нет менеджера макетов). Я думаю, я мог бы попытаться переопределить JLayeredPane и предоставить пользовательский макет, но это кажется экстремальным.

Стеклянные стекла тоже не подходят.

Как это может быть сделано? Не существует ли полезной концепции z-индексов в Swing?

http://sofru.miximages.com/java/30tkuvk.png

РЕДАКТИРОВАТЬ

Причина, по которой Layered Panes была неуместной, была связана с отсутствием менеджера компоновки на каждый слой. Панель может изменяться по размеру, панель A должна оставаться на уровне 100% площади, а панель B должна оставаться централизованной.

Я думаю, что LayeredPane – ваш лучший выбор здесь. Вам понадобится третья панель, хотя для того, чтобы содержать A и B. Эта третья панель будет layeredPane, а затем панели A и B могут по-прежнему иметь красивые LayoutManagers. Все, что вам нужно сделать, это центр B над A, и в Swing-трейле есть довольно много примеров того, как это сделать. Учебное пособие для позиционирования без LayoutManager .

public class Main { private JFrame frame = new JFrame(); private JLayeredPane lpane = new JLayeredPane(); private JPanel panelBlue = new JPanel(); private JPanel panelGreen = new JPanel(); public Main() { frame.setPreferredSize(new Dimension(600, 400)); frame.setLayout(new BorderLayout()); frame.add(lpane, BorderLayout.CENTER); lpane.setBounds(0, 0, 600, 400); panelBlue.setBackground(Color.BLUE); panelBlue.setBounds(0, 0, 600, 400); panelBlue.setOpaque(true); panelGreen.setBackground(Color.GREEN); panelGreen.setBounds(200, 100, 100, 100); panelGreen.setOpaque(true); lpane.add(panelBlue, new Integer(0), 0); lpane.add(panelGreen, new Integer(1), 0); frame.pack(); frame.setVisible(true); } /** * @param args the command line arguments */ public static void main(String[] args) { new Main(); } } 

Вы используете setBounds для размещения панелей внутри слоистой панели, а также для установки их размеров.

Редактировать, чтобы отразить изменения в исходном сообщении. Вам нужно будет добавить компонентные слушатели, которые обнаруживают, когда размер родительского контейнера изменяется, а затем динамически изменяют границы панели A и B.

Я просто подумал, что добавлю, что в Swing есть понятие Z-порядка, см. [Java.awt.Component # setComponentZOrder] [1]

который влияет на позиции компонента в его составном массиве родителей, который определяет порядок окраски.

Обратите внимание, что вы должны переопределить javax.swing.JComponent # isOptimizedDrawingEnabled, чтобы возвращать false в родительском контейнере, чтобы ваши совпадающие компоненты правильно перекрашивались, в противном случае их копии будут сжиматься друг с другом. (JComponents не предполагают, что пересекающиеся дочерние элементы, если isOptimizedDrawingEnabled возвращает false)

[1]: http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Container.html#setComponentZOrder(java.awt.Component , int)

Вы можете добавить неразделенный JDialog следующим образом:

 import java.awt.event.*; import javax.swing.*; public class TestSwing { public static void main(String[] args) throws Exception { JFrame frame = new JFrame("Parent"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(800, 600); frame.setVisible(true); final JDialog dialog = new JDialog(frame, "Child", true); dialog.setSize(300, 200); dialog.setLocationRelativeTo(frame); JButton button = new JButton("Button"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { dialog.dispose(); } }); dialog.add(button); dialog.setUndecorated(true); dialog.setVisible(true); } } 

Используйте 1 на 1 GridLayout в существующем JPanel, затем добавьте свою панель в этот JPanel. Единственная проблема с GridLayout, которая составляет 1 к 1, заключается в том, что вы не сможете разместить другие элементы на JPanel. В этом случае вам нужно будет найти подходящий макет. Каждая панель, которую вы используете, может использовать свой собственный макет, чтобы это не было проблемой.

Правильно ли я понимаю этот вопрос?

JOptionPane.showInternalInputDialog, вероятно, делает то, что вы хотите. Если нет, было бы полезно понять, чего не хватает.

Здесь может быть интересен другой менеджер компоновки: Overlay Layout. Вот простой учебник: OverlayLayout: для управления компоновкой компонентов, которые лежат друг над другом . Overlay Layout позволяет размещать панели друг над другом и устанавливать макет внутри каждой панели. Вы также можете установить размер и положение каждой панели отдельно.

(Причина, по которой я отвечаю на этот вопрос много лет назад, заключается в том, что я наткнулся на ту же проблему, и я видел очень мало упоминаний о Overlay Layout на StackOverflow, хотя, похоже, это хорошо документировано. Надеюсь, это может помочь кому-то другой, кто продолжает его искать.)

  • Какие свойства CSS создают контекст стекирования?
  • Как заставить родительский элемент появиться над дочерним элементом
  • WindowsFormsHost всегда самый верхний элемент WPF
  • Давайте будем гением компьютера.