使用Gridbag布局管理器

时间:2016-03-06 18:06:42

标签: java swing drag gridbaglayout

我正在尝试在JPanel中实现J组件的拖动。 JPanel必须使用Gridbag布局管理器。 我查看了许多拖动代码,包括Moving Windows。它们都使用component.setLocation(x, y);,这在使用Gridbag布局管理器时无效。 我需要替代方法的帮助。

1 个答案:

答案 0 :(得分:1)

如果JComponent是JPanel中唯一的组件,则任务并不复杂。这是一个小型的演示程序(为响应鼠标滚轮事件而重新调整组件大小):

    public class GridbagDragDemo extends JPanel {

        /**
         * Pixel width and height of positioned component.
         */
        private float  width, height;

        /**
         * Layout manger for this.
         */
        private GridBagLayout gbl;

        /**
         * Layout horizontal weights for left and right gap, and component.
         */
        private float leftWeight,xCompWeight, rightWeight;

        /**
         * Layout vertical weights for top and right gap, and component.
         */
        private float topWeight,yCompWeight, bottomWeight;

        /**
         * Min and max weight values.
         * These values can be changed to change the sensitivity of dragging.
         * For better responsiveness W_MAX can be changed in respect to the JPanl's size.
         * (also a different W_MAX can be set to horizontal and vertical axis.
         */
        private float W_MIN = 0, W_MAX = 2;

        /**
         * Keep sum an even number for calculating (int) W_SUM/2
         */
        private float W_SUM = W_MIN + W_MAX;

        /**
         * Represents the change in ratio between left / right weights
         * and top/bottom weights for every pixel of mouse drag.
         * The higher the factor the faster / more sensitive the
         * component move is.
         * Try different values to get the responsiveness you need.
         */
        private float WEIGHT_DELTA = 0.01f;

        /**
         * Represents the change (in pixels) in component width and height
         * and top/bottom weights for every mouse wheel notch.
         * The higher the factor the faster / more sensitive the
         * component resize.
         * Try different values to get the responsiveness you need.
         */
        private static final int ZOOM_FACTOR = 4;

        /**
         * Store mouse pressed position.
         */
        private float pX, pY;

        /**
         * The dragged component
         */
        private JComponent component;

        public GridbagDragDemo() {

            //set initial position to center
            leftWeight = W_SUM/2 ; xCompWeight = 0;  rightWeight = W_SUM/2;
            topWeight = W_SUM/2 ; yCompWeight = 0;  bottomWeight = W_SUM/2;

            gbl = new GridBagLayout();
            gbl.columnWidths = new int[] {0, 0, 0};
            gbl.rowHeights = new int[] {0, 0, 0};
            gbl.columnWeights = new double[]{leftWeight , xCompWeight, rightWeight };
            gbl.rowWeights = new double[]{topWeight,yCompWeight, bottomWeight};
            setLayout(gbl);
            setBackground(Color.YELLOW);

            component = new JPanel();
            component.setPreferredSize(new Dimension(75,75));
            component.setMinimumSize(new Dimension(15,15));
            component.setMaximumSize(new Dimension(225,225));
            component.setBackground(Color.ORANGE);
            component.setBorder(new LineBorder(Color.black, 3));

            //add drag listeners
            component.addMouseMotionListener(new MouseMotionAdapter(){
                @Override
                public void mouseDragged(MouseEvent me) {

                    int mouseX = me.getXOnScreen();
                    int mouseY = me.getYOnScreen();

                    float moveX  =  mouseX - pX;
                    float moveY  =  mouseY - pY;

                    pX = mouseX;
                    pY = mouseY;

                    moveComp(moveX , moveY);

                }
            });
            component.addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent me) {

                    //store pressed position
                    pX = me.getXOnScreen();
                    pY = me.getYOnScreen();
                }
            });

            //add resize listener
            component.addMouseWheelListener(new MouseWheelListener() {

                @Override
                public void mouseWheelMoved(MouseWheelEvent me) {

                    //change sign so rolling "up" will be positive
                    reSizeComp(- me.getWheelRotation());
                }
            });

            GridBagConstraints gbc_panel = new GridBagConstraints();
            gbc_panel.fill = GridBagConstraints.BOTH;
            gbc_panel.gridx = 1;
            gbc_panel.gridy = 1;
            add(component, gbc_panel);

            width  = component.getPreferredSize().width;
            height = component.getPreferredSize().height;
        }

        private void moveComp(float moveX, float moveY) {

            if(Math.abs(moveX)>0) {

                leftWeight += WEIGHT_DELTA * moveX;
                leftWeight = (float) setValueInRange(leftWeight,  W_MIN, W_MAX);
                rightWeight = W_SUM - leftWeight;
            }

            if(Math.abs(moveY)>0) {

                topWeight += WEIGHT_DELTA * moveY;
                topWeight = (float) setValueInRange(topWeight, W_MIN, W_MAX );
                bottomWeight = W_SUM - topWeight;
            }

            gbl.columnWeights = new double[]{leftWeight,xCompWeight, rightWeight};
            gbl.rowWeights    = new double[]{topWeight, yCompWeight, bottomWeight};

            refresh();
        }

        /**
         *
         */
        private void refresh() {

            revalidate();
            getParent().repaint();
        }

        private void reSizeComp(int notches) {

            width += notches*ZOOM_FACTOR  ; height += notches *ZOOM_FACTOR  ;

            //respect min / max component size
            width  = (float) setValueInRange(width, component.getMinimumSize().getWidth(),
                                                        component.getMaximumSize().getWidth() );
            height = (float) setValueInRange(height, component.getMinimumSize().getHeight(),
                                                        component.getMaximumSize().getHeight() );
            component.setPreferredSize(new Dimension((int)width,(int)height));

            refresh();
        }

        private double setValueInRange(double value, double min, double max) {

            value = (value < min ) ? min : value;
            value = (value > max ) ? max : value;

            return value;
        }

        public static void main(String args[]) {

            java.awt.EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {

                    JFrame frame = new JFrame("Test Gridbag drag");
                    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                    frame.setPreferredSize(new Dimension(400, 300));
                    frame.getContentPane().setLayout(new BorderLayout());

                    frame.getContentPane().add(new GridbagDragDemo(), BorderLayout.CENTER);

                    frame.setVisible(true);
                    frame.pack();
                }
            });
        }
    }

enter image description here

如果JPanel拥有多个组件,它将成为一个完全不同的球赛。使用多个组件,其功能类似于使用GUI构建器(如Eclipse&#39; IDE Windowbuilder,您可以在其中以交互方式移动组件。

相关问题