【问题标题】:Drawing a line from 2 mouse clicks通过 2 次鼠标单击绘制一条线
【发布时间】:2012-08-28 18:51:06
【问题描述】:

我正在尝试从一系列鼠标点击中画一条线。

例如,当我从屏幕上的一个点单击到下一个点时,它会连接线,然后我可以继续单击下一个点,它会继续绘制一条连续的绘图线。

这里有一个例子:http://oneslime.net/java/Tutorial_2练习 2

我认为我的逻辑有一些错误(没有画线,只是一个点),但我似乎找不到它!

谁能帮帮我?

这是我的代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class RoadCreator extends JPanel {

    private MouseHandler mouseHandler = new MouseHandler();

    private Point previousPoint = new Point();
    private Point nextPoint = new Point();
    private boolean drawing;

    public RoadCreator() {
        this.setPreferredSize(new Dimension(640, 480));
        this.addMouseListener(mouseHandler);
       this.addMouseMotionListener(mouseHandler);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.blue);
        g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setStroke(new BasicStroke(8,
            BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
        g.drawLine(previousPoint.x, previousPoint.y, nextPoint.x, nextPoint.y);
    }

    private class MouseHandler extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            drawing = true;
            nextPoint = e.getPoint();
            repaint();
            previousPoint = e.getPoint();

        }
    }

    public void display() {
        JFrame f = new JFrame("Road Creator");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setVisible(true);
    }

    }

任何帮助将不胜感激,谢谢!

【问题讨论】:

  • 也许在 nextPoint = e.getPoint();previousPoint = e.getPoint(); 每次调用 e.getPoint() 时都会得到相同的结果。你试过previousPoint = nextPoint;然后nextPoint = e.getPoint();吗?

标签: java awt graphics2d java-2d mouselistener


【解决方案1】:

这行不通。

public void mousePressed(MouseEvent e) {
    drawing = true;
    nextPoint = e.getPoint();
    repaint();
    previousPoint = e.getPoint();
}

您假设repaint 是一个内联调用(即它在返回之前绘制)。不会,repaint 会将一个请求排队到重绘管理器,该请求将在未来某个时间更新。

public void mousePressed(MouseEvent e) {
    drawing = true;
    previousPoint = nextPoint
    nextPoint = e.getPoint();
    repaint();
}

应该可以工作,请注意,previousPoint 在用户第二次点击之前将为空。

【讨论】:

  • previousPoint 不会是 null,因为它已被初始化:private Point previousPoint = new Point();,但它不会有任何可靠的坐标。确实应该检查是否是第一次鼠标点击。
  • 是的,这就是我所追求的,但是否可以继续添加到现有行,而不是每次都添加新行?
【解决方案2】:

请改用GeneralPathPath2D

GeneralPath 类表示由直线、二次和三次 (Bézier) 曲线构成的几何路径。 它可以包含多个子路径。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.GeneralPath;

public class RoadCreator extends JPanel {

    private MouseHandler mouseHandler = new MouseHandler();

    GeneralPath path = null;
    private boolean drawing = false;

    public RoadCreator() {
        this.setPreferredSize(new Dimension(320, 200));
        this.addMouseListener(mouseHandler);
        this.addMouseMotionListener(mouseHandler);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.blue);
        g2d.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setStroke(new BasicStroke(8,
                BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
        if (path!=null) {
            g2d.draw(path);
        }
    }

    private class MouseHandler extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            Point p = e.getPoint(); 
            if (!drawing) {
                path = new GeneralPath();
                path.moveTo(p.x, p.y);
                drawing = true;
            } else {
                path.lineTo(p.x, p.y);
            }

            repaint();
        }
    }

    public void display() {
        JFrame f = new JFrame("Road Creator");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setVisible(true);
    }

    public static void main(String[] args) {
        RoadCreator rc = new RoadCreator();
        rc.display();
    }
}

【讨论】:

    【解决方案3】:

    我找到了一种以尽可能少的努力完成这项任务的方法。然而,这并不等同于创建应用程序的“好”方式。您需要考虑未来的可扩展性,例如绘制其他对象的能力......等等。因此,让我们开始了解如何使其发挥作用。

    1) 让我们省略paintComponent方法...我相信这应该是paint()。

        //@Override
        /*protected void paintComponent(Graphics g) {
             //Do Something...
          }*/
    

    2) 让我们添加这个方法:

        public void drawLineHelper(Point prev, Point next){
            Graphics g = getGraphics();
            g.setColor(Color.blue);
            g.drawLine(previousPoint.x, previousPoint.y, nextPoint.x, nextPoint.y);
        }
    

    3) 最后,我们需要对 mouseHandler 类进行一些更改:

       private class MouseHandler extends MouseAdapter {
            //twoPoints make sure we have two points.
            boolean twoPoints=false;
    
            @Override
            public void mousePressed(MouseEvent e) {
                if(twoPoints==false){
                    nextPoint = e.getPoint();
                    twoPoints = true;
                }
                else{
                    //Set previous to next from now on.
                    previousPoint = nextPoint;
    
                    //Get a new next point.
                    nextPoint = e.getPoint();
    
                    //Helper method will draw the line each time.
                    drawLineHelper(previousPoint,nextPoint);
                    //repaint() no longer necessary.
    
                }
            }
        }
    

    这里是另一个具有相同问题的示例的快速参考。页面上的最后一篇文章解释了同样的方法:http://www.ozzu.com/programming-forum/java-repainting-problem-t49362.html

    【讨论】:

      猜你喜欢
      • 2023-03-31
      • 1970-01-01
      • 2018-10-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-30
      • 1970-01-01
      • 2013-04-14
      • 1970-01-01
      相关资源
      最近更新 更多