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:
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.