2009-05-12 3 views
30

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

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

Glass panes также не подходят.

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

http://i42.tinypic.com/30tkuvk.jpg

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

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

+0

См. в качестве опции - как (очень просто) расширить JLayeredPane, чтобы принять любой LayouManager. http://stackoverflow.com/questions/42413590/jlayeredpane-and-gridbagconstraints – Mischa

ответ

34

Я думаю, что LayeredPane - ваш лучший выбор здесь. Вам понадобится третья панель, хотя для того, чтобы содержать A и B. Эта третья панель будет layeredPane, а затем панели A и B могут по-прежнему иметь красивые LayoutManagers. Все, что вам нужно сделать, это центр B над A, и в Swing-трейле есть довольно много примеров того, как это сделать. Tutorial for positioning without a 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.

+0

Привет, это проспект, который я изначально преследовал, но я не могу понять, как заставить A и B вести себя без использования setBounds. В документах для JLayeredPane упоминается «Все менеджеры макетов, предоставляемые платформой Java, упорядочивают компоненты так, как если бы они были на одном уровне». – Pool

+0

Да, это правильно. Для позиции A и B вам необходимо использовать setBounds. На панелях A и B все еще может быть любой LayoutManager, который вы хотите расположить в них компоненты. Отвечает ли это на ваш вопрос? – willcodejavaforfood

+1

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

1

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

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

+0

Спасибо, я добавил диаграмму выше, чтобы уточнить. В основном это закладывание компонентов поверх друг друга (индекс z), о котором я не знаю. – Pool

+0

О, я вижу, моя ошибка. Спасибо за дополнительное разъяснение. – AlbertoPL

0

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

+0

Спасибо, так как я это понимаю, он будет отображать внутренний фрейм, который будет выглядеть и выглядеть в окне. Мне действительно нужна полная настройка, которую предложила панель. – Pool

4

можно добавить неукрашенный 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); 
    } 
} 
+0

Спасибо, к сожалению, это создает новое окно +1 для незадекларированного, хотя и очень приятного эффекта. – Pool

+0

И почему это проблема? Теперь, когда я рассмотрю второй вопрос, вы можете сделать диалог немодальным и изменить его, когда размер родительского кадра будет изменен. – mavroprovato

+0

Это требование. Диалог/окно не имеет смысла для этой панели. – Pool

5

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

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

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

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

0

Там другой менеджер компоновки, которые могут быть интересны здесь: Overlay Layout Вот простой учебник: OverlayLayout: for layout management of components that lie on top of one another. Overlay Layout позволяет размещать панели друг над другом и устанавливать макет внутри каждой панели. Вы также можете установить размер и положение каждой панели отдельно.

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

Смежные вопросы