【问题标题】:Drag and Resize undecorated JFrame拖动和调整未修饰的 JFrame
【发布时间】:2014-08-20 00:28:57
【问题描述】:

目前,我正在使用以下代码来拖动和移动未修饰的 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>
}

我必须写什么,以便用户可以像装饰窗口一样通过拖动边来调整它的大小?

【问题讨论】:

    标签: java swing jframe mouseevent mouse-listeners


    【解决方案1】:

    您可以查看 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();
                }
            });
        }
    }
    

    【讨论】:

    • 非常感谢。在时间允许的情况下,我会尝试并在测试后标记为 ans(现在正在开发 prog 的其他部分)。
    • 太棒了,awt & swing 比我想象的要好得多。
    • 非常感谢您的帮助,我已经测试过了,效果很好。
    【解决方案2】:

    我最近为此构建了自己的原型。也许你会发现这很有用。

    它使用 2 个不同的组件,一个在另一个之上。与受此启发的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 和一个容器监听器,以便在需要时调整内部组件的大小。不鼓励这种做法。此逻辑应移至自定义布局管理器。

    【讨论】:

      【解决方案3】:

      在选择“未装饰”选项后将其添加到您的框架中(下面使用主菜单中的 j 按钮打开一个名为 PlumbingPRO 的新未装饰输入表单,该表单具有边框且可拖动)。我会将其添加到 MAIN 方法或具有“initComponents();”的类中如果在主窗体中使用,则在 java 文件的开头。如果用于后续表单,则以下内容应通过按钮选择起作用。确保在具有按钮选择而非后续表单的表单中为以下操作(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);
      
      }             
      

      【讨论】:

        猜你喜欢
        • 2013-03-29
        • 1970-01-01
        • 1970-01-01
        • 2014-11-30
        • 2021-06-29
        • 1970-01-01
        • 1970-01-01
        • 2018-03-29
        • 1970-01-01
        相关资源
        最近更新 更多