有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java问题重新验证/重新绘制按钮面板

我已经在谷歌上搜索了好几个小时,尝试了一百万种不同的细微变化,但都无济于事,所以我想我最好的选择是挑选比我更熟练的人的大脑

我正在编写一个类,从数据库中加载一组按钮,目标是让用户能够根据自己的喜好排列按钮,但是,由于某些原因,我似乎无法使框架重新验证或重新绘制。按钮会四处移动,但不会像我编码的那样重新排列。该组织似乎工作正常,即释放鼠标按钮时进行重新排列所涉及的代码,只是组件将仅停留在拖放位置,即使它们在各自的列表中重新排序

代码很长,我不想发布整个课程,因为它可能会让一些人感到厌烦,但我不知道我在哪里犯了错误,所以我认为发布整个课程将符合我的最佳利益。主要关注的领域是mouseReleased(MouseEvent e) {...}repaint()/refresh()方法,但是,我可能在其他地方遗漏了一些东西

tl;博士: 我基本上只是尝试在用户按照他们想要的顺序拖放按钮之后执行一个setBounds(),但是按钮停留在拖放的相同位置,不会revalidate()repaint()。我甚至无法清除面板上的组件并重新加载

提前谢谢你。这是我的密码:

public class AdminButtonEditor extends javax.swing.JFrame {
    public AdminButtonEditor(OrderView parent) { ...
        ...
        Component[] components = buttonsPanel.getComponents();
        for (int i = 0; i < components.length; i++) {
            Component c = components[i];
            if (c instanceof JButton) {
                JButton jb = (JButton) c;
                jb.setFocusable(false);
                buttons.add(new MyJButton(...));
            }
        }
        for (int i = 0; i < buttons.size(); i++) {
            buttons.get(i).addTo(editPanel);
            buttons.get(i).orderIndex=modButtonList.get(i).menuModifier.getViewOrderValue();
            buttons.get(i).idx=i;
        }
        EventHandler eh = new EventHandler();
        addWindowListener(eh);
        editPanel.addMouseMotionListener(eh);
        editPanel.addMouseListener(eh);
        contentPane.add(editPanel, BorderLayout.CENTER);
    }
    protected void refresh() {
        if (!buttons.isEmpty() && buttons.get(0) != null) {
            contentPane.remove(editPanel);
            editPanel.removeAll();
            for (int i = 0; i < buttons.size(); i++) {
                MyJButton s = buttons.get(i);
                s.addTo(editPanel);
            }
            contentPane.add(editPanel, BorderLayout.CENTER);
            editPanel.repaint();
        }
    }
    public void paint(Graphics g) {
       refresh();
       super.paint(g);
    }
    private int getSelectionIndex(int x, int y) {
        int s=-1;
        for (int i=buttons.size()-1; i>=0;i--){
            if (buttons.get(i).contains(x, y)) {
                s = i;
                break;
            }
        }
        return s;
    }
private class EventHandler implements MouseInputListener,WindowListener, ActionListener {
    private int selectionIndex, startX, startY, lastX, lastY;
    private MyJButton selected;
    private boolean moving=false;
    ....
    ....
    public void mouseReleased(MouseEvent e) {
        if (moving){
            setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
            moving=false;
            int dropX=e.getX();
            int dropY=e.getY();
            int row = dropY/selected.height;
            int col = dropX/selected.width;
            int idx=(row*3+col)-1;
            int oldIdx=buttons.indexOf(selected);
            insertIntoList(idx,oldIdx);
         }
        if (selected!=null){
            selected.unHighLight();
            selected=null;
        }

        Collections.sort(buttons);
        for (int i=0;i<buttons.size();i++){
        //modButtonList.get(buttons.get(i).idx).menuModifier.setViewOrderValue(buttons.get(i).orderIndex);
        }
        editPanel.validate();
        repaint();
    }

    private void insertIntoList(int idx, int oldIdx) {
        MyJButton temp = buttons.get(idx);
        int tempid=buttons.get(idx).idx;
        buttons.set(idx, new MyJButton(selected.text,selected.x,selected.y,selected.width,selected.height,selected.idx));
        buttons.get(idx).orderIndex=temp.orderIndex;
        if (idx<oldIdx){
            int id;
            for (int i=oldIdx;i>idx+1;i--){
                id=buttons.get(i).orderIndex;
                buttons.set(i, new MyJButton(buttons.get(i-1).text,buttons.get(i-1).x,buttons.get(i-1).y,buttons.get(i-1).width,buttons.get(i-1).height,buttons.get(i-1).idx));
                buttons.get(i).orderIndex=id;
            }
            id = buttons.get(idx+1).orderIndex;
            buttons.set(idx+1,new MyJButton(temp.text,temp.x,temp.y,temp.width,temp.height,temp.idx));
            buttons.get(idx+1).orderIndex=id;
        } else if (idx>oldIdx) {
            int id;
            for (int i=oldIdx;i<idx-1;i++){
                id=buttons.get(i).orderIndex;
                buttons.set(i, new MyJButton(buttons.get(i+1).text,buttons.get(i+1).x,buttons.get(i+1).y,buttons.get(i+1).width,buttons.get(i+1).height,buttons.get(i+1).idx));
                buttons.get(i).orderIndex=id;
            }
            id = buttons.get(idx-1).orderIndex;
            buttons.set(idx-1,new MyJButton(temp.text,temp.x,temp.y,temp.width,temp.height,temp.idx));
            buttons.get(idx-1).orderIndex=id;;
        } else {
            buttons.get(idx).x=buttons.get(idx).originx;
            buttons.get(idx).y=buttons.get(idx).originy;
        }
        repaint();
    }
    public void mouseDragged(MouseEvent e) {
        if (moving) {
            Graphics g = editPanel.getGraphics();
            g.setColor(Color.black);
            g.drawLine(selected.getXPos(), 0, selected.getXPos(),editPanel.getWidth());
            g.drawLine(0, selected.getYPos(), editPanel.getHeight(), selected.getYPos());
            selected.moveBy(e.getX()-lastX, e.getY()-lastY);
            g.setXORMode(Color.black);

            g.drawLine(selected.getXPos(), 0, selected.getXPos(), editPanel.getWidth());
            g.drawLine(0, selected.getYPos(), editPanel.getHeight(), selected.getYPos());

            lastX=e.getX();
            lastY=e.getY();
            repaint();
        }
    }
    ....
}
  private class MyJButton extends JButton implements Comparable {
    private int orderIndex,idx;
    private int x, y, width, height,originx,originy;
    private String text;
    public Border DEFAULT_BORDER;// new SoftBevelBorder(BevelBorder.RAISED);
    public Border SELECT_BORDER = BorderFactory.createLineBorder(Color.RED, 3, true);

    public MyJButton(String text, int x, int y, int width, int height) {
        ....
        setFocusable(false);
    }
    public MyJButton(String text, int x, int y, int width, int height,int idx) {....}

    public void addTo(JPanel p) {
        setBounds(x, y, width, height);
        p.add(this);
    }

    @Override
    public boolean contains(int x, int y) {
        int x1 = x, y1 = y;
        if (x1 >= this.x && y1 >= this.y && x1 <= this.x + width && y1 <= this.y + height) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void setSize(int w, int h) {
        width = w;
        height = h;
    }
    ....
    public void moveBy(int dx, int dy) {
        x += dx;
        y += dy;
    }

    @Override
    public void resize(int newWidth, int newHeight) {
        this.width = newWidth;
        this.height = newHeight;
        setBounds(x, y, width, height);
    }

    public int compareTo(Object o) {
        MyJButton mjb = (MyJButton)o;
        return this.idx-mjb.idx;
    }

  }
}

共 (1) 个答案

  1. # 1 楼答案

    加甘德佩巴利斯评论+1

    好吧,所以我觉得这很酷,并决定进一步研究

    我想出了一些逻辑,可能不是最好的,但要让它发挥作用需要这些逻辑:

    1)我们需要使我们的JButton成为可拖动的(谢谢@camickr和他的DragLayout):)

    2)当一个JButton被拖放时,即在mouseReleased(..)上,我们应该检查我们拖动的按钮是否与其他按钮冲突

    3)我们通过获取JButton图像并计算正在拖动的JButton的不透明像素覆盖另一个按钮的数量来检查JButton是否与另一个发生碰撞

    4)对冲突的数量进行排序并找到最大值,这样我们就可以看到在哪里插入我们拖动的JButton。i、 e它将由碰撞最多的组件插入

    5)对保存按钮以匹配更改的ArrayList进行排序

    6)移除所有按钮并使用数组重新添加它们(因此它们将被重新排序)

    下面是一个示例(大多数代码发生在重写的ComponentMover{}方法中):

    在拖动任何内容之前:

    enter image description here

    将按钮4拖动到按钮1上并松开鼠标按钮后:

    enter image description here

    import java.awt.Component;
    import java.awt.Cursor;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.GraphicsEnvironment;
    import java.awt.GridLayout;
    import java.awt.Insets;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.Window;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.imageio.ImageIO;
    import javax.swing.JButton;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class DragButtons {
    
        ArrayList<JButton> buttons = new ArrayList<>();
    
        public DragButtons() {
            initComponents();
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new DragButtons();
                }
            });
        }
    
        private void initComponents() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            final JPanel panel = new JPanel(new GridLayout(2, 2));
    
            ComponentMover cm = new ComponentMover() {
                @Override
                public void mouseReleased(MouseEvent e) {
                    super.mouseReleased(e);
                    HashMap<Integer, JButton> collisions = new HashMap<>();
                    JButton draggedButton = (JButton) e.getSource();
    
                    for (JButton btn : buttons) {//iterate through all buttons and get the number of collsions of each
                        if (btn != draggedButton) {//dont chck button we were dragging
                            int col = checkPerPixelCollision(draggedButton, btn);
                            System.out.println("Button " + btn.getText());
                            System.out.println(col);
                            collisions.put(col, btn);
                        }
                    }
                    //lets get the button which had most collisions
                    int maxCollisions = 0;
                    JButton intersectingButton = null;
                    for (Map.Entry<Integer, JButton> entry : collisions.entrySet()) {
                        Integer collisionCount = entry.getKey();
                        JButton button = entry.getValue();
                        if (collisionCount > maxCollisions) {
                            maxCollisions = collisionCount;
                            intersectingButton = button;
                        }
                    }
    
                    boolean reLayout = false;
    
                    if (maxCollisions > 0) {//check if there was any
                        System.out.println("Button " + draggedButton.getText() + " is intersecting more of Button " + intersectingButton.getText());
                        System.out.println("Collisions: " + maxCollisions);
                        reLayout = true;
                    } else {
                        System.out.println("No change made");
                        reLayout = false;
                    }
    
                    ArrayList<JButton> tmpButtons = (ArrayList<JButton>) buttons.clone();//create clone of buttons
    
                    if (reLayout) {//a button as moved and panel needs to be layed out
                        buttons.clear();//clear old buttons
    
                        for (JButton b : tmpButtons) {//re-order jbuttons
                            if (b == intersectingButton) {
                                buttons.add(draggedButton);
                            } else if (b == draggedButton) {
                                buttons.add(intersectingButton);
                            } else {
                                buttons.add(b);
                            }
                        }
                        panel.removeAll();//remove all buttons
                        for (JButton btn : buttons) {//iterate through all buttons and get the number of collsions of each
                            panel.add(btn);//re-add buttons according to arraylist
                        }
                        panel.revalidate();
                        panel.repaint();
                        //re-order the Array of buttons to fit
                        //remove all button and re add them using sorted array
                    }
    
                }
            };
    
            for (int i = 0; i < 4; i++) {
                JButton b = new JButton(String.valueOf(i + 1));
                buttons.add(b);
                panel.add(b);
                cm.registerComponent(b);
            }
    
            frame.add(panel);
    
            frame.pack();
            frame.setVisible(true);
    
        }
    
        public HashSet<String> getMask(JButton e) {
            HashSet<String> mask = new HashSet<>();
            int pixel, a;
            BufferedImage bi = null;
            try {
                bi = componentToImage(e, e.getBounds()); //gets the current image being shown
            } catch (IOException ex) {
                Logger.getLogger(DragButtons.class.getName()).log(Level.SEVERE, null, ex);
            }
            for (int i = 0; i < bi.getWidth(); i++) { // for every (x,y) component in the given box, 
                for (int j = 0; j < bi.getHeight(); j++) {
                    pixel = bi.getRGB(i, j); // get the RGB value of the pixel
                    a = (pixel >> 24) & 0xff;
                    if (a != 0) {  // if the alpha is not 0, it must be something other than transparent
                        mask.add((e.getX() + i) + "," + (e.getY() - j)); // add the absolute x and absolute y coordinates to our set
                    }
                }
            }
            return mask;  //return our set
        }
    
        public static BufferedImage componentToImage(Component component, Rectangle region) throws IOException {
            BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);
            Graphics g = img.getGraphics();
            g.setColor(component.getForeground());
            g.setFont(component.getFont());
            component.paintAll(g);
            ImageIO.write(img, "png", new File("c:/saved.png"));
            return img;
        }
    
        // Returns true if there is a collision between object a and object b   
        public int checkPerPixelCollision(JButton b, JButton b2) {
            // This method detects to see if the images overlap at all. If they do, collision is possible
            int ax1 = (int) b2.getX();
            int ay1 = (int) b2.getY();
    
            int ax2 = ax1 + (int) b2.getWidth();
            int ay2 = ay1 + (int) b2.getHeight();
    
            int bx1 = (int) b.getX();
            int by1 = (int) b.getY();
    
            int bx2 = bx1 + (int) b.getWidth();
    
            int by2 = by1 + (int) b.getHeight();
    
            if (by2 < ay1 || ay2 < by1 || bx2 < ax1 || ax2 < bx1) {
                return 0; // Collision is impossible.
            } else { // Collision is possible.
                // get the masks for both images
                HashSet<String> maskPlayer1 = getMask(b2);
                HashSet<String> maskPlayer2 = getMask(b);
                maskPlayer1.retainAll(maskPlayer2);  // Check to see if any pixels in maskPlayer2 are the same as those in maskPlayer1
                if (maskPlayer1.size() > 0) {  // if so, than there exists at least one pixel that is the same in both images, thus
                    return maskPlayer1.size();
                }
            }
            return 0;
        }
    }
    
    class ComponentMover extends MouseAdapter {
    
        private Insets dragInsets = new Insets(0, 0, 0, 0);
        private Dimension snapSize = new Dimension(1, 1);
        private Insets edgeInsets = new Insets(0, 0, 0, 0);
        private boolean changeCursor = true;
        private boolean autoLayout = false;
        private Class destinationClass;
        private Component destinationComponent;
        private Component destination;
        private Component source;
        private Point pressed;
        private Point location;
        private Cursor originalCursor;
        private boolean autoscrolls;
        private boolean potentialDrag;
    
        /**
         * Constructor for moving individual components. The components must be
         * regisetered using the registerComponent() method.
         */
        public ComponentMover() {
        }
    
        /**
         * Constructor to specify a Class of Component that will be moved when drag
         * events are generated on a registered child component. The events will be
         * passed to the first ancestor of this specified class.
         *
         * @param destinationClass the Class of the ancestor component
         * @param component the Components to be registered for forwarding drag
         * events to the ancestor Component.
         */
        public ComponentMover(Class destinationClass, Component... components) {
            this.destinationClass = destinationClass;
            registerComponent(components);
        }
    
        /**
         * Constructor to specify a parent component that will be moved when drag
         * events are generated on a registered child component.
         *
         * @param destinationComponent the component drage events should be
         * forwareded to
         * @param components the Components to be registered for forwarding drag
         * events to the parent component to be moved
         */
        public ComponentMover(Component destinationComponent, Component... components) {
            this.destinationComponent = destinationComponent;
            registerComponent(components);
        }
    
        /**
         * Get the auto layout property
         *
         * @return the auto layout property
         */
        public boolean isAutoLayout() {
            return autoLayout;
        }
    
        /**
         * Set the auto layout property
         *
         * @param autoLayout when true layout will be invoked on the parent
         * container
         */
        public void setAutoLayout(boolean autoLayout) {
            this.autoLayout = autoLayout;
        }
    
        /**
         * Get the change cursor property
         *
         * @return the change cursor property
         */
        public boolean isChangeCursor() {
            return changeCursor;
        }
    
        /**
         * Set the change cursor property
         *
         * @param changeCursor when true the cursor will be changed to the
         * Cursor.MOVE_CURSOR while the mouse is pressed
         */
        public void setChangeCursor(boolean changeCursor) {
            this.changeCursor = changeCursor;
        }
    
        /**
         * Get the drag insets
         *
         * @return the drag insets
         */
        public Insets getDragInsets() {
            return dragInsets;
        }
    
        /**
         * Set the drag insets. The insets specify an area where mouseDragged events
         * should be ignored and therefore the component will not be moved. This
         * will prevent these events from being confused with a MouseMotionListener
         * that supports component resizing.
         *
         * @param dragInsets
         */
        public void setDragInsets(Insets dragInsets) {
            this.dragInsets = dragInsets;
        }
    
        /**
         * Get the bounds insets
         *
         * @return the bounds insets
         */
        public Insets getEdgeInsets() {
            return edgeInsets;
        }
    
        /**
         * Set the edge insets. The insets specify how close to each edge of the
         * parent component that the child component can be moved. Positive values
         * means the component must be contained within the parent. Negative values
         * means the component can be moved outside the parent.
         *
         * @param edgeInsets
         */
        public void setEdgeInsets(Insets edgeInsets) {
            this.edgeInsets = edgeInsets;
        }
    
        /**
         * Remove listeners from the specified component
         *
         * @param component the component the listeners are removed from
         */
        public void deregisterComponent(Component... components) {
            for (Component component : components) {
                component.removeMouseListener(this);
            }
        }
    
        /**
         * Add the required listeners to the specified component
         *
         * @param component the component the listeners are added to
         */
        public void registerComponent(Component... components) {
            for (Component component : components) {
                component.addMouseListener(this);
            }
        }
    
        /**
         * Get the snap size
         *
         * @return the snap size
         */
        public Dimension getSnapSize() {
            return snapSize;
        }
    
        /**
         * Set the snap size. Forces the component to be snapped to the closest grid
         * position. Snapping will occur when the mouse is dragged half way.
         */
        public void setSnapSize(Dimension snapSize) {
            if (snapSize.width < 1
                    || snapSize.height < 1) {
                throw new IllegalArgumentException("Snap sizes must be greater than 0");
            }
    
            this.snapSize = snapSize;
        }
    
        /**
         * Setup the variables used to control the moving of the component:
         *
         * source - the source component of the mouse event destination - the
         * component that will ultimately be moved pressed - the Point where the
         * mouse was pressed in the destination component coordinates.
         */
        @Override
        public void mousePressed(MouseEvent e) {
            source = e.getComponent();
            int width = source.getSize().width - dragInsets.left - dragInsets.right;
            int height = source.getSize().height - dragInsets.top - dragInsets.bottom;
            Rectangle r = new Rectangle(dragInsets.left, dragInsets.top, width, height);
    
            if (r.contains(e.getPoint())) {
                setupForDragging(e);
            }
        }
    
        private void setupForDragging(MouseEvent e) {
            source.addMouseMotionListener(this);
            potentialDrag = true;
    
            //  Determine the component that will ultimately be moved
    
            if (destinationComponent != null) {
                destination = destinationComponent;
            } else if (destinationClass == null) {
                destination = source;
            } else //  forward events to destination component
            {
                destination = SwingUtilities.getAncestorOfClass(destinationClass, source);
            }
    
            pressed = e.getLocationOnScreen();
            location = destination.getLocation();
    
            if (changeCursor) {
                originalCursor = source.getCursor();
                source.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
            }
    
            //  Making sure autoscrolls is false will allow for smoother dragging of
            //  individual components
    
            if (destination instanceof JComponent) {
                JComponent jc = (JComponent) destination;
                autoscrolls = jc.getAutoscrolls();
                jc.setAutoscrolls(false);
            }
        }
    
        /**
         * Move the component to its new location. The dragged Point must be in the
         * destination coordinates.
         */
        @Override
        public void mouseDragged(MouseEvent e) {
            Point dragged = e.getLocationOnScreen();
            int dragX = getDragDistance(dragged.x, pressed.x, snapSize.width);
            int dragY = getDragDistance(dragged.y, pressed.y, snapSize.height);
    
            int locationX = location.x + dragX;
            int locationY = location.y + dragY;
    
            //  Mouse dragged events are not generated for every pixel the mouse
            //  is moved. Adjust the location to make sure we are still on a
            //  snap value.
    
            while (locationX < edgeInsets.left) {
                locationX += snapSize.width;
            }
    
            while (locationY < edgeInsets.top) {
                locationY += snapSize.height;
            }
    
            Dimension d = getBoundingSize(destination);
    
            while (locationX + destination.getSize().width + edgeInsets.right > d.width) {
                locationX -= snapSize.width;
            }
    
            while (locationY + destination.getSize().height + edgeInsets.bottom > d.height) {
                locationY -= snapSize.height;
            }
    
            //  Adjustments are finished, move the component
    
            destination.setLocation(locationX, locationY);
        }
    
        /*
         *  Determine how far the mouse has moved from where dragging started
         *  (Assume drag direction is down and right for positive drag distance)
         */
        private int getDragDistance(int larger, int smaller, int snapSize) {
            int halfway = snapSize / 2;
            int drag = larger - smaller;
            drag += (drag < 0) ? -halfway : halfway;
            drag = (drag / snapSize) * snapSize;
    
            return drag;
        }
    
        /*
         *  Get the bounds of the parent of the dragged component.
         */
        private Dimension getBoundingSize(Component source) {
            if (source instanceof Window) {
                GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
                Rectangle bounds = env.getMaximumWindowBounds();
                return new Dimension(bounds.width, bounds.height);
            } else {
                return source.getParent().getSize();
            }
        }
    
        /**
         * Restore the original state of the Component
         */
        @Override
        public void mouseReleased(MouseEvent e) {
            super.mouseReleased(e);
            if (!potentialDrag) {
                return;
            }
    
            source.removeMouseMotionListener(this);
            potentialDrag = false;
    
            if (changeCursor) {
                source.setCursor(originalCursor);
            }
    
            if (destination instanceof JComponent) {
                ((JComponent) destination).setAutoscrolls(autoscrolls);
            }
    
            //  Layout the components on the parent container
    
            if (autoLayout) {
                if (destination instanceof JComponent) {
                    ((JComponent) destination).revalidate();
                } else {
                    destination.revalidate();
                }
                destination.repaint();
            }
        }
    }