I've got two classes: Connection extends JComponent
and PostMachineView extends JPanel implements MouseListener
. What I'm trying to do is fire a method whenever the mouse button is pressed inside the Connection
component. I'm using SwingUtilities.convertPointToScreen
so that the mouse event coordinates will be relative to where I am drawing. The problem is that it returns slightly different numbers for x
and y
than it should. Code below:
public class PostMachineView extends JPanel implements MouseListener {
ArrayList<Connection> connections;
public PostMachineView() {
connections = new ArrayList<>();
setSize(new Dimension(800, 800));
setBackground(Color.white);
//here i create the points i'll need for the connection and instantiate it
Point p1 = new Point(100, 100);
Point p2 = new Point(100, 200);
Connection conn = new Connection(p1, p2);
//add the connection component to this panel
add(conn);
//set the connection mouse listener
conn.addMouseListener(this);
connections.add(conn);
}
@Override
public void paint(Graphics g) {
super.paint(g);
//this will be done in a different way, just trying to get it to work first
Point p1 = new Point(100, 100);
Point p2 = new Point(100, 200);
((Connection)getComponent(0)).paintComponent(g, p1, p2);
}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {
System.out.println("clicked in the component");
}
@Override
public void mouseReleased(MouseEvent e) {}
}
public class Connection extends JComponent {
private Rectangle2D.Double curveControl;
private GeneralPath path;
public Connection(Point p1, Point p2) {
path = new GeneralPath();
path.moveTo(p1.getX(), p1.getY());
int[] mid = getMidPointCoords(p1, p2);
curveControl = new Rectangle2D.Double(mid[0] - 5, mid[1] - 5, 10, 10);
path.curveTo(curveControl.getCenterX(), curveControl.getCenterY(),
curveControl.getCenterX(), curveControl.getCenterY(),
p2.getX(), p2.getY());
}
public int[] getMidPointCoords(Point p1, Point p2) {
int[] v = { 0, 0 };
v[0] = (int) ((p1.getX() + p2.getX()) / 2);
v[1] = (int) ((p1.getY() + p2.getY()) / 2);
return v;
}
public void paintComponent(Graphics g, Point p1, Point p2) {
path.moveTo(p1.getX(), p1.getY());
path.curveTo(curveControl.getCenterX(), curveControl.getCenterY(),
curveControl.getCenterX(), curveControl.getCenterY(),
p2.getX(), p2.getY());
Graphics2D g2d = (Graphics2D) g;
g2d.draw(path);
g2d.setColor(Color.red);
g2d.fill(curveControl);
g2d.setColor(Color.black);
}
@Override
public boolean contains(int x, int y) {
//here is where i use swingutilities to convert the coordinates
Point p = new Point(x, y);
SwingUtilities.convertPointToScreen(p, this);
return curveControl.contains(p.getX(), p.getY());
}
}
I also have a Teste class, which simply instantiates a JFrame and adds a PostMachineView
to it:
public class Teste {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(new Dimension(800,800));
f.add(new PostMachineView());
f.setResizable(false);
f.setVisible(true);
}
}
This...
public void paint(Graphics g) {
super.paint(g);
//this will be done in a different way, just trying to get it to work first
Point p1 = new Point(100, 100);
Point p2 = new Point(100, 200);
((Connection)getComponent(0)).paintComponent(g, p1, p2);
}
Is a VERY bad idea. The Connection
component is already a child of the PostMachineView
component. You should simply be updating the state of Connection
(maybe through a mouseClicked
event) and calling repaint
to update it.
In Connection
, this...
public void paintComponent(Graphics g, Point p1, Point p2) {
path.moveTo(p1.getX(), p1.getY());
path.curveTo(curveControl.getCenterX(), curveControl.getCenterY(),
curveControl.getCenterX(), curveControl.getCenterY(),
p2.getX(), p2.getY());
Graphics2D g2d = (Graphics2D) g;
g2d.draw(path);
g2d.setColor(Color.red);
g2d.fill(curveControl);
g2d.setColor(Color.black);
}
Should be slit into two methods, one that adds the new point and one that draws it...
public void add(Point p1, Point p2) {
path.moveTo(p1.getX(), p1.getY());
path.curveTo(curveControl.getCenterX(), curveControl.getCenterY(),
curveControl.getCenterX(), curveControl.getCenterY(),
p2.getX(), p2.getY());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(path);
g2d.setColor(Color.red);
g2d.fill(curveControl);
g2d.setColor(Color.black);
g2d.dispose();
}
Because the MouseListener
is attached to the Connection
component, this...
@Override
public boolean contains(int x, int y) {
//here is where i use swingutilities to convert the coordinates
Point p = new Point(x, y);
SwingUtilities.convertPointToScreen(p, this);
return curveControl.contains(p.getX(), p.getY());
}
No longer makes sense and, to be honest, I'd be VERY careful with messing around with this
At best it should be more like...
public boolean contains(int x, int y) {
return curveControl.contains(x, y);
}
But remember, the MouseListener
will no longer generate events unless the x/y coordinates are WITHIN the curveControl
, which might not really be what you want.
Oh and this ArrayList<Connection> connections;
scares me...but then, I don't have the context to your problem to really know what you're intentions are for this...
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.