[英]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.