简体   繁体   中英

Why doesn't this Java paint program paint more than one oval?

I have a Java paint program that uses a custom JPanel to paint on. While when clicking on the JPanel paints a small oval (or circle, if you will), the oval disappears each time you click on another place. The coordinates also get updated, but the oval does not stay, it moves to wherever the user clicks next... Here's the code for the custom JPanel:

int xCord, yCord;

    public class PaintPanel extends JPanel implements MouseListener {
        // default serial whatever...
        private static final long serialVersionUID = -6514297510194472060L;

        // initial values
        int xCord = -10;
        int yCord = -10;

        public PaintPanel() {
            addMouseListener(this);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(ProgramUI.currentColor);
            g.fillOval(xCord, yCord, 8, 8);
            repaint();
        }

        @Override
        public void mouseClicked(MouseEvent m) {
        }

        @Override
        public void mouseEntered(MouseEvent m) {
        }

        @Override
        public void mouseExited(MouseEvent m) {
        }

        @Override
        public void mousePressed(MouseEvent m) {
            if (paintPanel.contains(m.getPoint())) {
                xCord = m.getX();
                yCord = m.getY();
                System.out.println("x: " + xCord + " y: " + yCord);
            }
        }

        @Override
        public void mouseReleased(MouseEvent m) {
        }

    }

I need the holding of a mouse to continuously paint an oval until the mouse button is let go. The only problem here is that the mouse oval updates, but does not save it's original position. How do I fix this?

Only one oval is drawn as there is only one fillOval statement drawing a single oval in the paintComponent method so the statement

super.paintComponent(g);

causes any previous painting to be cleared once repaint is called.

To paint multiple ovals, you can paint components from a List<Point> as outlined in Custom Painting Approaches

Don't call repaint from within paintComponent . This creates an infinite loop and degrades performance. If periodic updates are required invoke repaint from the ActionListener of a Swing Timer instead.

这是因为组件会重新绘制自身,以使更改永久生效,因此,每次完成绘制后,都应该拍摄jpanel的图像并将其设置为背景...

You are only painting the last place the user clicked each time. Instead, you need to collect the past clicks and paint them all each time.

This code will do what you want:

package com.sandbox;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

public class SwingSandbox {


    public static void main(String[] args) {

        JFrame frame = buildFrame();
        frame.add(new PaintPanel());
    }

    public static class PaintPanel extends JPanel implements MouseListener {
        // default serial whatever...
        private static final long serialVersionUID = -6514297510194472060L;

        ArrayList<Point> points = new ArrayList<Point>();

        public PaintPanel() {
            addMouseListener(this);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(new Color(250));
            for (Point point : points) {
                g.fillOval(point.x, point.y, 8, 8);
            }
            repaint();
        }

        @Override
        public void mouseClicked(MouseEvent m) {
        }

        @Override
        public void mouseEntered(MouseEvent m) {
        }

        @Override
        public void mouseExited(MouseEvent m) {
        }

        @Override
        public void mousePressed(MouseEvent m) {
            if (this.contains(m.getPoint())) {
                points.add(m.getPoint());
            }
        }

        @Override
        public void mouseReleased(MouseEvent m) {
        }

    }


    private static JFrame buildFrame() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(200, 200);
        frame.setVisible(true);
        return frame;
    }


}

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