簡體   English   中英

如何使用 BorderLayout 創建可移動的 JPanel?

[英]How to create moveable JPanel using BorderLayout?

我想創建一個帶有滑動菜單的 GUI。 該菜單是組織到帶有 BorderLayout 的 JFrame 上的三個 JPanel 之一。 有問題的菜單位於西側。 我怎樣才能使菜單可以容納文本字段、JLabels、圖像等,同時能夠滑入和滑出?

這可以完成,但它需要自定義布局或 null 布局。 在后一種情況下,您需要自己管理子組件的大小和位置。

由於一旦按下按鈕,組件就會“捕獲”鼠標,並且所有鼠標事件都會發送到同一個組件,直到鼠標被釋放,所以您只需要在用作拖動句柄的一個組件上監聽鼠標拖動事件。

我稱之為抽屜的可滑動區域可以位於 BorderLayout 的中心,拖動手柄位於東部(或 LINE_END)position。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;

import java.awt.event.ComponentEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

public class Drawer {
    private final JLayeredPane container;

    private final JComponent main;

    private final JComponent contentAndHandle;

    private int dragStartX;

    private int drawerPositionOnPress;

    public Drawer(JComponent drawerContent,
                  JComponent main) {

        this.main = main;

        container = new JLayeredPane();
        container.add(main, JLayeredPane.DEFAULT_LAYER);

        // Do the work normally done by a LayoutManager.
        main.addHierarchyListener(e -> {
            EventQueue.invokeLater(
                () -> container.setPreferredSize(main.getPreferredSize()));
        });
        container.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent event) {
                EventQueue.invokeLater(() -> updateChildrenSizes());
            }
        });

        JComponent handle = new JPanel() {
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);

                int width = getWidth();
                int height = getHeight();
                for (int x = 0; x < width; x += 4) {
                    for (int y = 0; y < height; y += 4) {
                        g.setColor(Color.WHITE);
                        g.fillRect(x, y, 1, 1);
                        g.fillRect(x + 2, y + 2, 1, 1);
                        g.setColor(Color.BLACK);
                        g.fillRect(x + 1, y + 1, 1, 1);
                        g.fillRect(x + 3, y + 3, 1, 1);
                    }
                }
            }
        };
        handle.setPreferredSize(new Dimension(12, 1));
        handle.setOpaque(true);
        handle.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent event) {
                if (event.getButton() == MouseEvent.BUTTON1) {
                    dragStartX = event.getXOnScreen();
                    drawerPositionOnPress =
                        contentAndHandle.getLocationOnScreen().x;
                }
            }
        });
        handle.addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent event) {
                int modifiers = event.getModifiersEx();
                if ((modifiers & MouseEvent.BUTTON1_DOWN_MASK) != 0) {
                    int newX = drawerPositionOnPress + 
                        event.getXOnScreen() - dragStartX;

                    newX = Math.min(0, newX);
                    newX = Math.max(-drawerContent.getWidth(), newX);

                    Point newPosition = new Point(newX, 0);
                    EventQueue.invokeLater(
                        () -> contentAndHandle.setLocation(newPosition));
                }
            }
        });

        contentAndHandle = new JPanel(new BorderLayout());
        contentAndHandle.add(drawerContent, BorderLayout.CENTER);
        contentAndHandle.add(handle, BorderLayout.LINE_END);

        container.add(contentAndHandle, JLayeredPane.DRAG_LAYER);

        // Do the work normally done by a LayoutManager.
        container.setPreferredSize(main.getPreferredSize());
        updateChildrenSizes();
    }

    public JComponent getComponent() {
        return container;
    }

    private void updateChildrenSizes() {
        Dimension size = container.getSize();
        main.setSize(size);
        size.width = contentAndHandle.getPreferredSize().width;
        contentAndHandle.setSize(size);
        container.validate();
    }
}

我選擇根據舊的Java 外觀設計指南中描述的“拖動紋理”在拖動手柄中繪制圖案。 您當然可以使用任何您想要的外觀,包括圖像。

下面是 class 的使用示例:

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTable;

public class DrawerTest {
    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            JPanel exampleMenu = new JPanel(new GridBagLayout());
            exampleMenu.setBorder(
                BorderFactory.createEmptyBorder(12, 12, 12, 12));

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.anchor = GridBagConstraints.BASELINE_LEADING;
            exampleMenu.add(new JLabel("First name: "), gbc);
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            exampleMenu.add(new JTextField(10), gbc);

            gbc.insets.top = 3;
            gbc.gridwidth = 1;
            exampleMenu.add(new JLabel("Last name: "), gbc);
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            exampleMenu.add(new JTextField(10), gbc);

            gbc.gridwidth = 1;
            exampleMenu.add(new JLabel("Credit card: "), gbc);
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            exampleMenu.add(new JTextField(19), gbc);

            gbc.gridwidth = 1;
            exampleMenu.add(new JLabel("Address: "), gbc);
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            exampleMenu.add(new JTextField(19), gbc);

            JComponent mainContent;
            mainContent = new JScrollPane(new JTable(
                new Object[][] {
                    { "Stack Overflow", "https://stackoverflow.com" },
                    { "Software Engineering",
                            "https://softwareengineering.stackexchange.com" },
                    { "Code Review", "https://codereview.stackexchange.com" },
                    { "Super User", "https://superuser.com" },
                    { "Server Fault", "https://serverfault.com" },
                },
                new Object[] { "Name", "URL" }));

            Drawer drawer = new Drawer(exampleMenu, mainContent);

            JFrame frame = new JFrame("Drawer Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(drawer.getComponent());
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        });
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM