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

StackOverflow https://stackoverflow.com/questions/852631

Вопрос

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

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

Стеклянные панели это тоже кажется неуместным.

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

Редактировать

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

Это было полезно?

Решение

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

Другие советы

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

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

Обратите внимание, что вы должны переопределить javax.swing.JComponent#isOptimizedDrawingEnabled возвращать false в родительском контейнере, чтобы заставить ваши перекрывающиеся компоненты правильно перерисовываться, в противном случае их перерисовки будут мешать друг другу.(J-компоненты не предполагают перекрывающихся дочерних элементов, если только 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 в существующей JPanel, затем добавьте свою панель в эту JPanel.Единственная проблема с GridLayout размером 1 на 1 заключается в том, что вы не сможете размещать другие элементы на JPanel.В этом случае вам нужно будет определиться с подходящим макетом.Каждая панель, которую вы используете, может использовать свой собственный макет, так что это не будет проблемой.

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top