简体   繁体   中英

How to change the color of a panel when I pass over it with another one?

I'm creating a code where I need to change a Panel color with the one I'm still pressed on when I pass over it. For instance if let's say I pressed on a green panel and drag it over another one, this one should get the green color. However it doesn't work everytime, like sometimes it does change the color but sometimes it doesn't.

import java.awt.Color;
import java.awt.Font;
import java.awt.event.MouseEvent;
import java.util.Random;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.*;
import javax.swing.event.MouseInputListener;

public class Etabli extends JFrame {
    
    JPanel paneprinci;
    CarrePanel selected;
    public Etabli() {
        this.setVisible(true);
        setTitle("Cadre");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        paneprinci=new JPanel(null);
        setSize(600,600);
        selected=new CarrePanel();
        for (int i=0;i<10;i++) {
            paneprinci.add(new CarrePanel(new Carre()));
        }
    
        this.getContentPane().add(paneprinci);
    }
    
    

    public static void main (String[]args) {
        javax.swing.SwingUtilities.invokeLater(
                new Runnable() {
                    public void run() { 
                        Etabli e=new Etabli();
                    }
                });
    }
    
    public class CarrePanel extends JPanel implements MouseInputListener{
        
        private Carre carre;
        private boolean etat;
        private int xprev;
        private int yprev;

        
        public CarrePanel(Carre c) {
            setBounds(new Random().nextInt(500),new Random().nextInt(500), 50, 50);
            addMouseListener(this);
            addMouseMotionListener(this);
            this.setBackground(c.getColor());
            this.carre=c;
        }
        
        public CarrePanel() {
            setBounds(new Random().nextInt(500),new Random().nextInt(500), 50, 50);
            addMouseListener(this);
            addMouseMotionListener(this);
        }
        
        public void setCarre(Carre c) {
            carre=c;
        }
        
        public Carre getCarre() {
            return carre;
        }

        @Override
        public void mouseClicked(MouseEvent e) {
            
            
            System.out.println(this.carre.getColor());
        }

        @Override
        public void mouseEntered(MouseEvent e) {
            if (selected.getCarre()!=null) {
                this.carre.setColor(selected.getCarre().getColor());
                this.setBackground(selected.getCarre().getColor());
            }
        }
        
        @Override
        public void mousePressed(MouseEvent e) {
            etat=true;
            selected.setCarre(this.carre);
            xprev=e.getXOnScreen();
            yprev=e.getYOnScreen();
    
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            etat=false;
            if(selected.getCarre()==this.carre) {
                
                selected.setCarre(null);;
            }
            
        }


        @Override
        public void mouseExited(MouseEvent e) {

        }

        @Override
        public void mouseDragged(MouseEvent e) {
            
            if(etat) {
                int x=this.getX()+e.getXOnScreen()-xprev;
                int y=this.getY()+e.getYOnScreen()-yprev;
                this.setLocation(x,y);
                xprev=e.getXOnScreen();
                yprev=e.getYOnScreen();
                
            }
        }

        @Override
        public void mouseMoved(MouseEvent e) {
            
        }
        
    }

}

Here's the code for Carre ( which is square in French )

import java.awt.Color;
import java.util.Arrays;
import java.util.Random;
import java.awt.Color;



public class Carre {

        
        private Color color;
        public Carre() {
            color=new Color(new Random().nextInt(255),new Random().nextInt(255),new Random().nextInt(255));
        }
        
        public Color getColor() {
            return color;
        }
        
        public void setColor(Color c) {
            color=c;
        }
    }

What I don't understand is why does it works sometimes, I don't know if the problem comes from how I did my drag event or if there's something wrong elsewhere.

Thank you for your awnser.

What I don't understand is why does it works sometimes,

When you drag a square to another square you will notice that sometimes the dragged square is painted:

  1. below the other square
  2. above the other square

When the square is painted above the other square a mouseEntered event is not generated because the default logic will only generate the event for the top component.

When the square is painted below the other square, then your mouseEntered event is generated and your logic works as expected.

The order of painting of a component is determined by its ZOrder. So you can adjust the ZOrder of the dragged component to be the last component painted.

In the mousePressed logic you can add:

JPanel parent = (JPanel)getParent();
parent.setComponentZOrder(this, parent.getComponentCount() - 1);

This will make sure that the dragged component is always painted below the other components.

Also note that your etat variable is not needed. The mouseDragged event is only generated while the mouse is pressed.

I created the following GUI.

干部

I added a java.awt.Rectangle to the Carre class to holds the bounds of each rectangle. The Carre class now holds all of the information to draw a Carre instance.

I created a CarreModel class to hold a java.util.List of Carre instances. I create all of the Carre instances in the constructor of the CarreModel class.

I created one JFrame and one drawing JPanel . I left your JFrame extend, but generally, you should use Swing components. You only extend a Swing component, like JPanel in CarrePanel , when you want to override one of the class methods.

I separated the MouseListener and MouseMotionListener from the CarrePanel JPanel class. I find it helps to keep separate functions in separate methods and classes. It makes it much easier to focus on one part of the application at a time.

The MouseListener mousePressed method has a function at the bottom to move the selected carre to the top of the Z-order. This makes the carre move more visually appealing.

The MouseListener updateCarreColor method checks for carre intersections and changes the color of any carre that intersects the selected carre.

Here's the complete runnable code. I made all the classes inner classes so I can post the code as one block.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.event.MouseInputListener;

public class Etabli extends JFrame {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Etabli();
            }
        });
    }

    private CarreModel model;
    
    private CarrePanel paneprinci;

    public Etabli() {
        this.model = new CarreModel();
        
        this.setTitle("Cadre");
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        
        paneprinci = new CarrePanel();
        this.add(paneprinci, BorderLayout.CENTER);
        
        this.pack();
        this.setLocationByPlatform(true);
        this.setVisible(true);
    }

    public class CarrePanel extends JPanel {

        private static final long serialVersionUID = 1L;

        public CarrePanel() {
            this.setPreferredSize(new Dimension(550, 550));
            ColorListener listener = new ColorListener();
            this.addMouseListener(listener);
            this.addMouseMotionListener(listener);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                    RenderingHints.VALUE_ANTIALIAS_ON);

            for (Carre carre : model.getCarres()) {
                g2d.setColor(carre.getColor());
                Rectangle r = carre.getBounds();
                g2d.fillRect(r.x, r.y, r.width, r.height);
            }
        }
        
    }
    
    public class ColorListener implements MouseInputListener {
        
        private Carre selectedCarre;
        
        private Point pressedPoint;
        
        @Override
        public void mouseClicked(MouseEvent event) {
        }

        @Override
        public void mouseEntered(MouseEvent event) {
        }

        @Override
        public void mousePressed(MouseEvent event) {
            pressedPoint = event.getPoint();
            selectedCarre = null;

            for (Carre carre : model.getCarres()) {
                if (carre.getBounds().contains(pressedPoint)) {
                    selectedCarre = carre;
                    break;
                }
            }
            
            if (selectedCarre != null) {
                List<Carre> carres = model.getCarres();
                carres.remove(selectedCarre);
                carres.add(selectedCarre);
            }
        }

        @Override
        public void mouseReleased(MouseEvent event) {
            updateCarrePosition(event.getPoint());
            updateCarreColor();
        }

        @Override
        public void mouseExited(MouseEvent event) {
        }

        @Override
        public void mouseDragged(MouseEvent event) {
            updateCarrePosition(event.getPoint());
            updateCarreColor();
        }

        @Override
        public void mouseMoved(MouseEvent event) {
        }

        private void updateCarrePosition(Point point) {
            int x = point.x - pressedPoint.x;
            int y = point.y - pressedPoint.y;
            
            if (selectedCarre != null) {
                selectedCarre.incrementBounds(x, y);
                paneprinci.repaint();
                pressedPoint.x = point.x;
                pressedPoint.y = point.y;
            }
        }
        
        private void updateCarreColor() {
            if (selectedCarre != null) {
                for (Carre carre : model.getCarres()) {
                    if (!carre.equals(selectedCarre) && 
                            carre.getBounds().intersects(selectedCarre.getBounds())) {
                        carre.setColor(selectedCarre.getColor());
                        paneprinci.repaint();
                    }
                }
            }
        }
        
    }
    
    public class CarreModel {
        
        private final List<Carre> carres;
        
        public CarreModel() {
            this.carres = new ArrayList<>();
            
            for (int i = 0; i < 10; i++) {
                this.carres.add(new Carre());
            }
        }

        public List<Carre> getCarres() {
            return carres;
        }
        
    }

    public class Carre {

        private Color color;
        
        private final Random random;
        
        private Rectangle bounds;

        public Carre() {
            random = new Random();
            
            int red = random.nextInt(128);
            int green = random.nextInt(128);
            int blue = random.nextInt(128);
            color = new Color(red, green, blue);
            
            int x = random.nextInt(500);
            int y = random.nextInt(500);
            bounds = new Rectangle(x, y, 50, 50);
        }
        
        public void incrementBounds(int x, int y) {
            bounds.x += x;
            bounds.y += y;
        }

        public Color getColor() {
            return color;
        }

        public void setColor(Color c) {
            color = c;
        }

        public Rectangle getBounds() {
            return bounds;
        }
        
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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