2

此代码用于在 JPanel 上绘图。在paintComponent(Graphics)我试图通过重复绘制曲线Graphics2D#fillOval(x, y, with, height)

该应用程序运行正常,当我缓慢拖动鼠标光标时;它根据我的需要绘制一条连续曲线。但是当我加快拖动鼠标光标时,结果是分开的点而不是连续的曲线。

那么即使我加快拖动,如何让它画出一条连续的曲线呢?

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

public class Painter extends JPanel {

    int x, y;
    ArrayList<Point> points;

    public Painter() {

        setBackground(Color.white);
        points = new ArrayList<>();

        MouseHandler listener = new MouseHandler();
        this.addMouseMotionListener(listener);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(600, 600);
    }

    private class MouseHandler extends MouseAdapter implements MouseMotionListener {

        @Override
        public void mouseDragged(MouseEvent e) {
            Point point = new Point(e.getX(), e.getY());
            points.add(point);
            repaint();
        }
    }

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

        Graphics2D g2d = (Graphics2D) g;
        for (Point point : points) {
            g2d.fillOval(point.x, point.y, 15, 15);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame();
                f.setContentPane(new Painter());
                f.pack();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
            }
        });
    }
}
4

1 回答 1

3

正如在对您之前的类似问题的评论中提到的:

  • 不要在您的paintComponent 方法中绘制离散的椭圆。
  • 而是通过在相邻点之间绘制线条来连接 PaintComponent 中列表中的点。
  • 如果您需要使线条更粗,请更改 Graphics2D 对象的 Stroke 属性,使用更粗的线。
  • 但是要小心 Strokes,因为您通常不希望属性更改沿着绘制链传播。这意味着有时您会想要复制 Graphics 对象并在新的 Graphics 对象上设置 Stroke 并使用它进行绘制,然后将其丢弃。
  • 创建 Stroke 的最简单方法是使用 BasicStroke 类,例如,new BasicStroke(6f)它会为您提供一条漂亮的粗曲线。

例如:

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

import javax.swing.*;

public class Painter2 extends JPanel {

    private static final float STROKE_WIDTH = 15f;
    private static final Stroke STROKE = new BasicStroke(STROKE_WIDTH, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
    int x, y;
    ArrayList<Point> points;

    public Painter2() {

        setBackground(Color.white);
        points = new ArrayList<>();

        MouseHandler listener = new MouseHandler();
        this.addMouseMotionListener(listener);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(600, 600);
    }

    private class MouseHandler extends MouseAdapter implements MouseMotionListener {

        @Override
        public void mouseDragged(MouseEvent e) {
            Point point = new Point(e.getX(), e.getY());
            points.add(point);
            repaint();
        }
    }

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

        Graphics2D g2d = (Graphics2D) g;
        g2d.setStroke(STROKE);
        for (int i = 1; i < points.size(); i++) {
            int x1 = points.get(i - 1).x;
            int y1 = points.get(i - 1).y;
            int x2 = points.get(i).x;
            int y2 = points.get(i).y;
            g2d.drawLine(x1, y1, x2, y2);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame();
                f.setContentPane(new Painter2());
                f.pack();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
            }
        });
    }
}

或者更好:

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
public class Painter2 extends JPanel {

    private static final float STROKE_WIDTH = 15f;
    private static final Stroke STROKE = new BasicStroke(STROKE_WIDTH, BasicStroke.CAP_ROUND,
            BasicStroke.JOIN_ROUND);
    private static final Color CURVES_COLOR = Color.BLUE;
    private static final Color TEMP_CURVE_COLOR = Color.PINK;
    private List<List<Point>> curvesList = new ArrayList<>();
    private List<Point> tempCurve = null;

    public Painter2() {
        setBackground(Color.white);
        MouseHandler listener = new MouseHandler();
        addMouseListener(listener);
        addMouseMotionListener(listener);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(600, 600);
    }

    private class MouseHandler extends MouseAdapter implements MouseMotionListener {
        @Override
        public void mousePressed(MouseEvent e) {
            tempCurve = new ArrayList<>();
            tempCurve.add(e.getPoint());
            repaint();
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            tempCurve.add(e.getPoint());
            repaint();
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            tempCurve.add(e.getPoint());
            curvesList.add(tempCurve);
            tempCurve = null;
            repaint();
        }
    }

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

        Graphics2D g2 = (Graphics2D) g.create();
        g2.setStroke(STROKE);
        g2.setColor(CURVES_COLOR);
        for (List<Point> curve : curvesList) {
            drawCurve(g2, curve);
        }

        if (tempCurve != null) {
            g2.setColor(TEMP_CURVE_COLOR);
            drawCurve(g2, tempCurve);
        }

        g2.dispose();
    }

    private void drawCurve(Graphics2D g2, List<Point> ptList) {
        for (int i = 1; i < ptList.size(); i++) {
            int x1 = ptList.get(i - 1).x;
            int y1 = ptList.get(i - 1).y;
            int x2 = ptList.get(i).x;
            int y2 = ptList.get(i).y;
            g2.drawLine(x1, y1, x2, y2);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame();
                f.setContentPane(new Painter2());
                f.pack();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
            }
        });
    }
}
于 2016-03-25T05:00:11.957 回答