Java Swing - как показать панель поверх другой панели?
Я хочу иметь внутреннее (не окно) диалоговое окно, чтобы запросить ввод элемента. Я хотел бы, чтобы диалог был размещен централизованно на существующей JPanel.
Я просмотрел layeredpanes, и они выглядят непригодными из-за того, что на всех панелях только один менеджер макета (или нет менеджера макетов). Я думаю, я мог бы попытаться переопределить JLayeredPane и предоставить настраиваемый макет, но это кажется экстремальным.
Стеклянные стекла также не подходят.
Как это можно сделать? Не существует ли пригодной концепции z-индексов в Swing?
http://i42.tinypic.com/30tkuvk.jpg
ИЗМЕНИТЬ
Причина, по которой Layered Panes не подходит, объясняется отсутствием менеджера компоновки на каждый уровень. Панель может быть изменена по размеру, панель A должна оставаться на уровне 100% площади, а панель B должна оставаться централизованной.
Ответы
Ответ 1
Я думаю, что 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.
Ответ 2
Я просто подумал, что добавлю, что в 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)
Ответ 3
Вы можете добавить неразделенный 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);
}
}
Ответ 4
Используйте 1 на 1 GridLayout в существующем JPanel, затем добавьте свою панель в этот JPanel. Единственная проблема с GridLayout, которая 1 к 1, заключается в том, что вы не сможете разместить другие элементы на JPanel. В этом случае вам нужно будет найти подходящий макет. Каждая панель, которую вы используете, может использовать свой собственный макет, поэтому это не будет проблемой.
Я правильно понимаю этот вопрос?
Ответ 5
JOptionPane.showInternalInputDialog, вероятно, делает то, что вы хотите. Если нет, было бы полезно понять, чего не хватает.
Ответ 6
Там может быть интересен другой менеджер компоновки: Макет Overlay
Вот простой учебник: OverlayLayout: для управления компоновкой компонентов, которые лежат друг над другом.
Overlay Layout позволяет размещать панели друг над другом и устанавливать макет внутри каждой панели. Вы также можете установить размер и положение каждой панели отдельно.
(Причина, по которой я отвечаю на этот вопрос много лет назад, состоит в том, что я наткнулся на ту же проблему, и я видел очень мало упоминаний о Overlay Layout на StackOverflow, хотя, похоже, это хорошо документировано. может помочь кому-то, кто продолжает его искать.)