拖拽和调整无装饰的JFrame窗口大小

13

目前,我正在使用以下代码来拖动和移动我的未装饰JFrames。

private void initialiseGUI(Component component){
    //<editor-fold defaultstate="collapsed" desc="code">
    component.addMouseListener(new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
            posX = e.getX();
            posY = e.getY();
        }
    });

    component.addMouseMotionListener(new MouseAdapter() {
        public void mouseDragged(MouseEvent evt) {
            //sets frame position when mouse dragged            
            Rectangle rectangle = getBounds();
            getGUI().setBounds(evt.getXOnScreen() - posX, evt.getYOnScreen() - posY, rectangle.width, rectangle.height);
        }
    });
    //</editor-fold>
}

我应该写什么代码,才能让用户通过拖动边框来调整大小,就像一个装饰窗口一样?

4个回答

43

你可以查看Rob Camick先生的ComponentResizer类。这个类非常简单和直接易用。

只需实例化ComponentResizer并像以下方式向该框架注册:

JFrame frame = new JFrame();
ComponentResizer cr = new ComponentResizer();
cr.registerComponent(frame);
cr.setSnapSize(new Dimension(10, 10));
cr.setMaximumSize(new Dimension(...));
cr.setMinimumSize(new Dimension(...));

以下是使用该类的完整示例

输入图像描述

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

public class UndecoratedExample {

    private JFrame frame = new JFrame();

    class MainPanel extends JPanel {

        public MainPanel() {
            setBackground(Color.gray);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }
    }

    class BorderPanel extends JPanel {

        private JLabel label;
        int pX, pY;

        public BorderPanel() {
            label = new JLabel(" X ");
            label.setOpaque(true);
            label.setBackground(Color.RED);
            label.setForeground(Color.WHITE);

            setBackground(Color.black);
            setLayout(new FlowLayout(FlowLayout.RIGHT));

            add(label);

            label.addMouseListener(new MouseAdapter() {
                public void mouseReleased(MouseEvent e) {
                    System.exit(0);
                }
            });
            addMouseListener(new MouseAdapter() {
                public void mousePressed(MouseEvent me) {
                    // Get x,y and store them
                    pX = me.getX();
                    pY = me.getY();

                }

                 public void mouseDragged(MouseEvent me) {

                    frame.setLocation(frame.getLocation().x + me.getX() - pX,
                            frame.getLocation().y + me.getY() - pY);
                }
            });

            addMouseMotionListener(new MouseMotionAdapter() {
                public void mouseDragged(MouseEvent me) {

                    frame.setLocation(frame.getLocation().x + me.getX() - pX,
                            frame.getLocation().y + me.getY() - pY);
                }
            });
        }
    }

    class OutsidePanel extends JPanel {

        public OutsidePanel() {
            setLayout(new BorderLayout());
            add(new MainPanel(), BorderLayout.CENTER);
            add(new BorderPanel(), BorderLayout.PAGE_START);
            setBorder(new LineBorder(Color.BLACK, 5));
        }
    }

    private void createAnsShowGui() {
        ComponentResizer cr = new ComponentResizer();
        cr.setMinimumSize(new Dimension(300, 300));
        cr.setMaximumSize(new Dimension(800, 600));
        cr.registerComponent(frame);
        cr.setSnapSize(new Dimension(10, 10));
        frame.setUndecorated(true);
        frame.add(new OutsidePanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new UndecoratedExample().createAnsShowGui();
            }
        });
    }
}

非常感谢。我会在有时间测试后尝试并标记为答案(现在正在开发程序的其他部分)。 - theAnonymous
太棒了,awt和swing远比我想象的要强大得多。 - Eugene
非常感谢您的帮助,我已经测试过了,它运行得非常好。 - theAnonymous

1
我最近建立了自己的原型。也许您会发现这很有用。
它使用两个不同的组件,一个在另一个之上。与Rob Camick's ComponentResizer不同,该组件受到启发,JFrame中设置的鼠标监听器将是功能性的。您将无法使JFrame捕获所有鼠标事件,从而使将监听器附加到JFrame中的组件变得无用。它仅在必须显示双头箭头的位置和时间捕获鼠标事件。
关键是顶部组件中的此方法:
@Override
public boolean contains(int x, int y) {
    return x < insets.left || y < insets.top
            || getHeight() - y < insets.bottom
            || getWidth() - x < insets.right;
}

这里是代码:

import java.awt.Component;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

public class BackgroundComponentDragger implements MouseMotionListener {

    private Component controlledComponent;

    /*
     * Point where cursor was last clicked.
     */
    private Point originPoint;

    public BackgroundComponentDragger(Component component) {
        this.controlledComponent = component;
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        Point currentFramePosition = controlledComponent.getLocation();
        Point newFramePosition = new Point(currentFramePosition.x + e.getX()
                - originPoint.x, currentFramePosition.y + e.getY() - originPoint.y);
        controlledComponent.setLocation(newFramePosition);
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        originPoint = e.getPoint();
    }
}



import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.HashMap;
import java.util.Map;

public class ComponentBorderDragger implements MouseMotionListener {

    private Component controlledComponent;

    private byte direction;
    protected static final byte NORTH = 1;
    protected static final byte WEST = 2;
    protected static final byte SOUTH = 4;
    protected static final byte EAST = 8;

    private Cursor sourceCursor;

    private static Map<Byte, Integer> cursors = new HashMap<Byte, Integer>();
    {
        cursors.put((byte) 1, Cursor.N_RESIZE_CURSOR);
        cursors.put((byte) 2, Cursor.W_RESIZE_CURSOR);
        cursors.put((byte) 4, Cursor.S_RESIZE_CURSOR);
        cursors.put((byte) 8, Cursor.E_RESIZE_CURSOR);
        cursors.put((byte) 3, Cursor.NW_RESIZE_CURSOR);
        cursors.put((byte) 9, Cursor.NE_RESIZE_CURSOR);
        cursors.put((byte) 6, Cursor.SW_RESIZE_CURSOR);
        cursors.put((byte) 12, Cursor.SE_RESIZE_CURSOR);
    }

    private Insets dragInsets;
    private Dimension minSize;

    private Point basePoint;

    public ComponentBorderDragger(Component controlledComponent, Insets dragInsets,
            Dimension minSize) {
        super();
        this.controlledComponent = controlledComponent;
        this.dragInsets = dragInsets;
        this.minSize = minSize;
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (direction == 0) {
            return;
        }

        Point newPoint = e.getPoint();
        int x, y, width, height, newBasePointX, newBasePointY;
        x = controlledComponent.getX();
        y = controlledComponent.getY();
        width = controlledComponent.getWidth();
        height = controlledComponent.getHeight();
        newBasePointX = newPoint.x;
        newBasePointY = newPoint.y;

        if ((direction & EAST) == EAST) {
            int newWidth;
            newWidth = Math.max(minSize.width, width + newPoint.x
                    - basePoint.x);
            width = newWidth;
        }
        if ((direction & SOUTH) == SOUTH) {
            int novoAlto;
            novoAlto = Math.max(minSize.height, height + newPoint.y
                    - basePoint.y);
            height = novoAlto;
        }
        if ((direction & WEST) == WEST) {
            int newWidth, newX;
            newWidth = Math.max(minSize.width, width - newPoint.x
                    + basePoint.x);
            newX = Math.min(x + width - minSize.width, x + newPoint.x
                    - basePoint.x);

            // Changing coordenates of new base point to refer to the new component position
            newBasePointX -= newX - x;
            x = newX;
            width = newWidth;
        }
        if ((direction & NORTH) == NORTH) {
            int newHeigth, newY;
            newHeigth = Math.max(minSize.height, height - newPoint.y
                    + basePoint.y);
            newY = Math.min(y + height - minSize.height, y + newPoint.y
                    - basePoint.y);
            // Changing coordenates of new base point to refer to the new component position
            newBasePointY -= newY - y;
            y = newY;
            height = newHeigth;
        }
        controlledComponent.setBounds(x, y, width, height);
        basePoint = new Point(newBasePointX, newBasePointY);
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        Component originator = e.getComponent();
        if (direction == 0) {
            sourceCursor = originator.getCursor();
        }
        calculateDirection(e.getPoint(), e.getComponent().getSize());
        setCursor(e.getComponent());
        basePoint = e.getPoint();
    }

    private void setCursor(Component component) {
        if (direction == 0) {
            component.setCursor(sourceCursor);
        } else {
            int cursorType = cursors.get(direction);
            Cursor cursor = Cursor.getPredefinedCursor(cursorType);
            component.setCursor(cursor);
        }
    }

    private void calculateDirection(Point point, Dimension componentSize) {
        direction = 0;
        if (point.x < dragInsets.left) {
            direction |= WEST;
        }
        if (point.y < dragInsets.top) {
            direction |= NORTH;
        }
        if (point.x > componentSize.width - dragInsets.right) {
            direction |= EAST;
        }
        if (point.y > componentSize.height - dragInsets.bottom) {
            direction |= SOUTH;
        }
    }
}


import java.awt.Insets;

import javax.swing.JComponent;

public class FrameComponent extends JComponent {

    private static final long serialVersionUID = 3383070502274306213L;

    private Insets insets;

    @Override
    public boolean contains(int x, int y) {
        return x < insets.left || y < insets.top || getHeight() - y < insets.bottom || getWidth() - x < insets.right;
    }

    public FrameComponent(Insets insets) {
        this.insets = insets;
    }
}


import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class GUI {

    private JFrame compoundFrame;
    private JPanel backgroundPanel;

    Dimension gUISize = new Dimension(400, 400);

    public GUI() {
        buildResizeableFrame();
    }

    public void activate() {
        compoundFrame.setVisible(true);
    }

    private void buildResizeableFrame() {
        compoundFrame = new JFrame();
        FrameComponent frame = new FrameComponent(new Insets(5, 5, 5, 5));
        backgroundPanel = new JPanel();
        compoundFrame.setLayout(null);
        compoundFrame.add(frame);
        compoundFrame.add(backgroundPanel);
        setFrameSizeController(frame, backgroundPanel);
        setFrameController(frame);
        setBackgroundPanelController(backgroundPanel);
        Dimension dimPant = Toolkit.getDefaultToolkit().getScreenSize();
        compoundFrame.setBounds(dimPant.width / 4, dimPant.height / 4, dimPant.width / 2, dimPant.height / 2);
        compoundFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        compoundFrame.setUndecorated(true);
    }

    private void setFrameSizeController(FrameComponent frame, JPanel panel) {
        compoundFrame.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                Dimension sizeIn = ((JFrame) e.getComponent()).getContentPane().getSize();
                frame.setSize(sizeIn);
                panel.setSize(sizeIn);
            }
        });
    }

    private void setFrameController(FrameComponent frame) {
        ComponentBorderDragger controller = new ComponentBorderDragger(compoundFrame,
                new Insets(5, 5, 5, 5), new Dimension(10, 10));
        frame.addMouseMotionListener(controller);
    }

    private void setBackgroundPanelController(JPanel panel) {
        panel.addMouseMotionListener(new BackgroundComponentDragger(compoundFrame));
    }

    public static void main(String[] args) {
        new GUI().activate();
    }
}

注意:此代码设置了一个空的LayoutManager和一个监听器到容器中,以在需要时调整内部组件的大小。这种做法是不被鼓励的。这个逻辑应该移动到一个自定义的LayoutManager中。

0
你可能想要尝试这个,但是你需要添加一个关闭窗口的功能。
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.Map.Entry;
import javax.swing.*;

public class AppWindow extends JFrame {
    Map<Boolean, String> mousePoint;
    private String direction;

    public AppWindow() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 570, 337);
        setUndecorated(true);
        getContentPane().setBackground(new Color(33, 115, 70));
        getContentPane().setLayout(null);
        setLocationRelativeTo(null);
        setVisible(true);
        setMinimumSize(new Dimension(100, 100));
        getContentPane().addMouseMotionListener(new MouseMotionAdapter() {

            @Override
            public void mouseMoved(MouseEvent e) {

                mousePoint = new HashMap<Boolean, String>();
                mousePoint.put(e.getY() < 5, "N");
                mousePoint.put(e.getX() > (getWidth() - 5), "E");
                mousePoint.put(e.getY() > (getHeight() - 5), "S");
                mousePoint.put(e.getX() < 5, "W");
                mousePoint.put(e.getY() < 5 && e.getX() > (getWidth() - 5), "NE");
                mousePoint.put(e.getY() > (getHeight() - 5) && e.getX() > (getWidth() - 5), "SE");
                mousePoint.put(e.getY() > (getHeight() - 5) && e.getX() <= 5, "SW");
                mousePoint.put(e.getY() < 5 && e.getX() < 5, "NW");

                for (Entry<Boolean, String> item : mousePoint.entrySet()) {
                    if (item.getKey()) {
                        direction = item.getValue();
                        switch (item.getValue()) {
                        case "N":
                            setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
                            break;
                        case "E":
                            setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
                            break;
                        case "S":
                            setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
                            break;
                        case "W":
                            setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
                            break;
                        case "NE":
                            setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
                            break;
                        case "SE":
                            setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
                            break;
                        case "SW":
                            setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
                            break;
                        case "NW":
                            setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
                            break;
                        }
                    } else {
                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    }
                }
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                if (!getCursor().equals(Cursor.getDefaultCursor())) {

                    switch (direction) {
                    case "N":
                        if (e.getYOnScreen() > getY()) {
                            setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() - (e.getYOnScreen() - getY()));
                        } else {
                            setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() + (getY() - e.getYOnScreen()));
                        }
                        break;
                    case "E":
                        setBounds(getX(), getY(), e.getX(), getHeight());
                        break;
                    case "S":
                        setBounds(getX(), getY(), getWidth(), e.getY());
                        break;
                    case "W":
                        if (e.getXOnScreen() > getX()) {
                            setBounds(e.getXOnScreen(), getY(), getWidth() - (e.getXOnScreen() - getX()), getHeight());
                        } else {
                            setBounds(e.getXOnScreen(), getY(), getWidth() + (getX() - e.getXOnScreen()), getHeight());
                        }
                        break;
                    case "NE":
                        setBounds(getX(), getY(), e.getX(), getHeight());

                        if (e.getYOnScreen() > getY()) {
                            setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() - (e.getYOnScreen() - getY()));
                        } else {
                            setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() + (getY() - e.getYOnScreen()));
                        }
                        break;
                    case "SE":

                        setBounds(getX(), getY(), e.getX(), e.getY());
                        break;
                    case "SW":
                        setBounds(getX(), getY(), getWidth(), e.getY());
                        if (e.getXOnScreen() > getX()) {
                            setBounds(e.getXOnScreen(), getY(), getWidth() - (e.getXOnScreen() - getX()), getHeight());
                        } else {
                            setBounds(e.getXOnScreen(), getY(), getWidth() + (getX() - e.getXOnScreen()), getHeight());
                        }
                        break;
                    case "NW":
                        if (e.getYOnScreen() > getY()) {
                            setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() - (e.getYOnScreen() - getY()));
                        } else {
                            setBounds(getX(), e.getYOnScreen(), getWidth(), getHeight() + (getY() - e.getYOnScreen()));
                        }
                        if (e.getXOnScreen() > getX()) {
                            setBounds(e.getXOnScreen(), getY(), getWidth() - (e.getXOnScreen() - getX()), getHeight());
                        } else {
                            setBounds(e.getXOnScreen(), getY(), getWidth() + (getX() - e.getXOnScreen()), getHeight());
                        }
                        break;
                    }
                }
            }
        });
    }
}

0
在选择“无装饰”选项后,将此代码添加到您的框架中(以下示例使用主菜单中的JButton打开一个名为PlumbingPRO的新的无装饰输入表单,该表单具有边框并且可拖动)。如果在主表单中使用,请将其添加到MAIN方法或在java文件开头具有“initComponents();”的类中。如果用于后续表单,则下面的代码应该从按钮选择中起作用。请确保在具有按钮选择而不是后续表单的表单中进行以下操作的“导入”(BorderFactory、FrameDragListener、addmouselistener、addMouseMotionListener)。
private void jbtn_PLUMBINGActionPerformed(java.awt.event.ActionEvent evt) {                                              
      PlumbingPRO frame = new PlumbingPRO();
      frame.getRootPane().setBorder(BorderFactory.createMatteBorder(3, 3, 3, 3, 
           Color.DARK_GRAY));
     FrameDragListener frameDragListener = new FrameDragListener(frame );
     frame.addMouseListener(frameDragListener);
     frame.addMouseMotionListener(frameDragListener);
     frame.setLocationRelativeTo(null);
     frame.setVisible(true);

}             

什么是FrameDragListener? - Victor Grazi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接