Using Swing, I want to draw a couple of points

2020-07-26 11:52发布

问题:

... in an image and do some calculation on their [x y] coordinates.

My first idea was to use an image as the background of a JPanel and then register the points, but I'm not sure there will be a way to mark these on the JPanel. There is also the Drawing library, which I'm unfamiliar with, but I'm not sure if I can combine these with Swing.

Can you name me the packages/classes I can use in order to do the task? References of code that already does it are also welcome.

Thank you!

回答1:

The issue here is three-fold:

  1. There needs to be a way to display a background image.
  2. One must be able to find the point at which the mouse was clicked.
  3. There must be a way to draw the point on the panel.

One way to accomplish the above points would be to subclass a JPanel and provide those functionalities.

1. Display a background image in a panel.

Firstly, as a JPanel does not have a way of displaying a background image by default, there must be a way to hold an image in the JPanel, and then draw that on the panel itself, which can be performed via the paintComponent method.

One way to accomplish this is to have a field in the class which holds on to an Image to draw:

class MyPanel extends JPanel {
    // Background image. Initialize appropriately.
    Image backgroundImage;

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        // Draw background image each time the panel is repainted.
        g.drawImage(backgroundImage, 0, 0, null);
    }
}

The Graphics object in paintComponent is associated with the MyPanel and can be used to perform graphics operations.

2. Finding the point at which the mouse was clicked.

Secondly, in order to retrieve the point at which the mouse was clicked, one could assign a MouseListener to the MyPanel. In the following example, an anonymous inner class extending the MouseAdapter is used to minimize writing extra code:

class MyPanel extends JPanel {
    // Background image. Initialize appropriately.
    Image backgroundImage;

    public MyPanel() {
         // Add a MouseListener which processes mouse clicks.
         this.addMouseListener(new MouseAdapter() {
             public void mouseClicked(MouseEvent e) {
                 // Process mouse-click.
             }
         })
    }

    // paintComponents method here.
}

Processing that needs to be performed when the mouse is clicked can be included in the mouseClicked method.

3. How to draw a point on the panel.

Thirdly, in order to find one point at which the mouse was clicked, one can obtain it from the MouseEvent object that was passed in from the mouseClicked method:

class MyPanel extends JPanel {
    // Background image. Initialize appropriately.
    Image backgroundImage;
    Point pointClicked;

    public MyPanel() {
         // Add a MouseListener which processes mouse clicks.
         this.addMouseListener(new MouseAdapter() {
             public void mouseClicked(MouseEvent e) {
                 // Retrieve the point at which the mouse was clicked.
                 pointClicked = e.getPoint();

                 // Repaint the panel.
                 this.repaint();
             }
         })
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        // Draw background image each time the panel is repainted.
        g.drawImage(backgroundImage, 0, 0, null);

        // Draw a little square at where the mouse was clicked.
        g.fillRect(pointClicked.x, pointClicked.y, 1, 1);
    }
}

Although the above code is not tested, it should be a starting point.

For example, if multiple points needs to be drawing, perhaps having a List<Point> to hold the points, and drawing each Point in the paintComponents method could be done.

If additional processing needs to be performed when the mouse is clicked, additional code can be added to the mouseClicked method.

Additional resources:

  • Lesson: Performing Custom Painting
  • Painting in AWT and Swing
  • How to Write a Mouse Listener

Thank you to zedoo for pointing out in the comments that making a call to super.paintComponent should be performed when overriding the paintComponent method.



回答2:

Subclass a JPanel and override the method paintComponent:

public void paintComponent(Graphics g) {
    super.paintComponent(g);

}

In the method you can use methods of the Graphics object passed to it. This method will be invoked every time there is a need to redraw the panel, so you need to store your points in an array and then read and draw each of them in your paintComponent.



回答3:

You may also find this useful, in case you want a heavyweight component (AWT), this tutorial explains how to extend the Canvas class to draw stuff.



回答4:

The Background Panel gives a couple of suggestion on how to display a background image depending on your requirements.

Custom Painting Approaches then gives some ideas of how to do custom painting if you need to add custom points to the image.