简体   繁体   English

拖动并调整未修饰的 JFrame 的大小

[英]Drag and Resize undecorated JFrame

Currently, I am using the following code to drag and move my undecordated JFrames.目前,我正在使用以下代码来拖动和移动我未解码的 JFrame。

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>
}

What must I write so that the user can resize it like a decorated window, by dragging the side?我必须写什么才能让用户可以像装饰窗口一样通过拖动边来调整它的大小?

You can check out mr Rob Camick's ComponentResizer class.您可以查看 Rob Camick 先生的ComponentResizer类。 Pretty simple and straight forward to use.使用起来非常简单直接。

Just instantiate the ComponentResizer and register the frame with something like:只需实例化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(...));

Here's a complete example of using the class这是使用该类的完整示例

在此处输入图片说明

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();
            }
        });
    }
}

I have recently built my own prototype for this.我最近为此构建了自己的原型。 Maybe you will find this useful.也许你会发现这很有用。

It uses 2 different components one on top of the other.它使用 2 个不同的组件,一个在另一个之上。 UnlikeRob Camick's ComponentResizer on which this is inspired, the mouse listeners set to the components in the JFrame will be functional.受此启发的Rob Camick 的 ComponentResizer不同,为 JFrame 中的组件设置的鼠标侦听器将起作用。 You will not get the JFrame to capture all the mouse events making it useless to attach listeners to the components in the JFrame.您不会让 JFrame 捕获所有鼠标事件,因此无法将侦听器附加到 JFrame 中的组件。 It captures mouse events only when and where a double headed arrow must be displayed.它仅在必须显示双头箭头的时间和地点捕获鼠标事件。

The key is this method in the top component:关键是顶部组件中的这个方法:

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

Here is the code:这是代码:

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();
    }
}

Note: This code sets a null LayoutManager and a listener to the container to resize the inner component when needed.注意:此代码为容器设置了一个 null LayoutManager 和一个侦听器,以在需要时调整内部组件的大小。 This practice is discouraged.不鼓励这种做法。 This logic should be moved to a custom layout manager.此逻辑应移至自定义布局管理器。

Add this to your frame after selecting "undecorated" option (below uses a jbutton from the main menu to open a new undecorated input form called PlumbingPRO that has a border and is draggable).选择“未装饰”选项后将其添加到您的框架中(下面使用主菜单中的 jbutton 打开一个名为 PlumbingPRO 的新的未装饰输入表单,该表单具有边框且可拖动)。 I would add this to MAIN Method or at the class that has the "initComponents();"我会将其添加到 MAIN 方法或具有“initComponents();”的类中at the beginning of the java file if using within the main form.如果在主窗体中使用,则在 java 文件的开头。 If using for a follow-on form, the below should work from the button selection.如果用于后续表单,则以下内容应从按钮选择开始。 Make sure you do your "imports" for the below actions (BorderFactory, FrameDragListener, addmouselistener, addMouseMotionListener) in the form that has the button selection and not the follow-on form.确保在具有按钮选择的表单而不是后续表单中对以下操作(Bor​​derFactory、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);

}             

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM