Накладная панель (над другой) - PullRequest
14 голосов
/ 09 января 2012

Я учусь пользоваться Swing и обнаружил, что это довольно сложная задача.

Что я пытаюсь сделать: я хочу, чтобы панель (называлась панелью меню) находилась слева (скажем, шириной 100 пикселей) и вторая панель (называлась панелью содержимого), которая занимает оставшееся свободное место.

На панели меню есть 3 кнопки. Когда я нажимаю на них, справа от панели меню (над панелью содержимого) должна появиться вторая панель меню (подменю) (и она должна начинаться в середине нажатой кнопки).

Это может быть трудно понять, поэтому я создал простой черновик:

enter image description here

Я пробовал JLayeredPane, но были проблемы с изменением размера окна (элементы в Layered Pane не меняли размер).

Ответы [ 4 ]

4 голосов
/ 09 января 2012

JLayeredPane пропустить реализации для LayoutManager, вам нужно setPreferredSize или setBounds вручную для определения размера / места JComponents,

есть один возможный обходной путь, который вы можете добавить ComponentListener кJFrame, затем на componentResized(ComponentEvent e) вы можете изменить размер / заменить JComponent(s) на желаемый Bounds

например

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class LayeredPaneWithOverlap {

    private JTextArea textArea = new JTextArea(2, 10);
    private JPanel textPanel = new JPanel(new BorderLayout());
    private JTable table = new JTable(30, 5);
    private JScrollPane scroll = new JScrollPane(table);
    private JLayeredPane layer = new JLayeredPane();
    private JFrame frame = new JFrame("Frame with resiziable JLayeredPane");

    public void makeUI() {
        textArea.setBorder(new LineBorder(Color.DARK_GRAY));
        textArea.setText("Frame with resiziable JLayeredPane");
        textPanel.setOpaque(false);
        textPanel.add(textArea, BorderLayout.NORTH);
        Font font = textArea.getFont();
        FontMetrics fontMetrics = textArea.getFontMetrics(font);
        int h = fontMetrics.getHeight() + frame.getInsets().top + 
                textPanel.getInsets().top + textArea.getInsets().top
                + textArea.getInsets().bottom;
        scroll.setBounds(0, h, 400, 300);
        layer.add(textPanel, new Integer(2));
        layer.add(scroll, new Integer(1));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 400);
        frame.addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {

                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        resizeAll();
                    }
                });
            }
        });
        frame.setLocationRelativeTo(null);
        frame.add(layer);
        resizeAll();
        frame.setVisible(true);
    }

    void resizeAll() {
        Insets insets = frame.getInsets();
        int w = frame.getWidth() - insets.left - insets.right;
        int h = frame.getHeight() - insets.top - insets.bottom;
        textPanel.setSize(w, h);
        scroll.setSize(w, h - scroll.getY());
        layer.revalidate();
        layer.repaint();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new LayeredPaneWithOverlap().makeUI();
            }
        });
    }
}
2 голосов
/ 09 января 2012

Вы можете установить макет менеджера для многоуровневой панели, javax.swing.OverlayLayout использует все доступное пространство и позволяет изменять размеры.

JLayeredPane layer = new JLayeredPane();
layer.setLayout(new OverlayLayout(layer));

Вы, вероятно, не хотите, чтобы подменю занимало весь пробел. Чтобы избежать этого, вы можете переопределить его get ... size-method. Или вы можете добавить второй LayeredPane (для его прозрачности и его компоновщика), установить обычный BoxLayout и использовать прокладку.

JPanel normalContents = new JPanel();
layer.add(normalContents, JLayeredPane.DEFAULT_LAYER);
JLayeredPane subMenuAuxiliaryLayer = new JLayeredPane()
subMenuAuxiliaryLayer.setLayout(new BoxLayout(subMenuAuxiliaryLayer, BoxLayout.LINE_AXIS));
layer.add(subMenuAuxiliaryLayer, JLayeredPane.PALETTE_LAYER);
JPanel submenuContents = new JPanel();
subMenuAuliliaryLayer.add(submenuContents);
subMenuAuxiliaryLayer.add(Box.createHorizontalGlue());
1 голос
/ 09 января 2012
contentPanel.setLayout(null); // Absolute positioning of children.

@Override
public void actionPerformed(ActionEvent evt) {
    final JButton btn = (JButton) evt.getSource();
    final int buttonY = btn.getY(); // Must be final for usage in new Runnable object.

    SwingUtilities.invokeLater(new Runnable() { // Return fast from event handling.

        @Override
        public void run() {
            JPanel child = new JPanel();
            child.setBackground(Color.RED); // So we'll see it.
            child.setBounds(0, buttonY, 100, 300);
            contentPanel.removeAll(); // Clear content panel of prior additions.
            contentPanel.add(child); // Add a new panel.
            contentPanel.repaint(10L);
        }
    });
 }
0 голосов
/ 09 октября 2015

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

Если вы не хотите делать это из кода, вам понадобится менеджер раскладки, ничего особенного, просто что-то, чтобы заполнить контейнер при его изменении размера. Но вот в чем дело ... если вы добавите менеджер макетов, он будет размещать компоненты так, как будто они все находятся в одном слое, но большинство менеджеров макетов не перекрывают свои дочерние элементы, поэтому они бесполезны. Вы можете использовать только OverlayLayout - он также может изменять размер дочерних элементов. Но использование OverlayLayout с JLayeredPane излишне. Вы можете просто использовать OverlayLayout с JPanel. Так что да, JLayeredPane бесполезен. Вместо этого я рекомендую использовать JPanel с OverlayLayout.

Вот как настроить все, чтобы вы могли иметь большой контроль над практически любым сценарием с перекрывающимся пользовательским интерфейсом: используя JPanel с OverlayLayout, создайте отдельную прозрачную JPanel для каждого слоя. Таким образом, вы можете комбинировать различные LayoutManager на разных слоях, устанавливая разные менеджеры компоновки для каждой панели, включая абсолютное позиционирование при необходимости. Затем добавьте видимые компоненты внутри панелей, представляющих слои. Не добавляйте их непосредственно на панель OverlayLayout. Просто убедитесь, что все JPanels, которые вы используете в качестве слоев, имеют setAlignmentX и Y по центру (0.5f), чтобы они заполняли всю панель OverlayLayout по мере ее изменения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...