2016-07-24 98 views
1

我想做一个简单的绘画程序。我正在试图制作一个像铅笔这样的工具,它允许自由绘画。到目前为止,我的代码是:如何在行间填充空格?

NPaintMain

public class NPaintMain { 
    public static void main(String[] args) { 
     new NPaintWindow(); 
    } 
} 

NPaintWindow

public class NPaintWindow { 
    private JFrame windowFrame; 
    private String windowTitle; 
    private NPaintCanvas canvas; 
    private Container easel;  
    public NPaintWindow() { 
     windowTitle = "NPaint - a simple paint program."; 
     windowFrame = new JFrame(windowTitle); 
     windowFrame.setDefaultCloseOperation(windowFrame.EXIT_ON_CLOSE); 
     windowFrame.setSize(500, 500); 
     windowFrame.setLocationRelativeTo(null); 
     canvas = new NPaintCanvas(); 
     easel = windowFrame.getContentPane(); 
     easel.add(canvas); 
     windowFrame.setVisible(true); 
    } 
} 

NPaintCanvas

public class NPaintCanvas extends JPanel { 
    double x, y, px, py; 
    ArrayList<Line2D> l; 
    public NPaintCanvas() { 
     new NPaintMouseEvents(this); 
     x = y = px = py = 0; 
     l = new ArrayList<>(); 
    } 
    @Override 
    public void paintComponent(Graphics g){ 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g; 
      for(Line2D ll: l){ 
       g2d.draw(ll); 
      } 
      l.add(new Line2D.Double(px, py, x, y)); 
      g.dispose(); 
      repaint(); 
    } 
} 

NPaintMouseEvents

public class NPaintMouseEvents implements MouseListener,MouseMotionListener { 

    NPaintCanvas canvas; 

    public NPaintMouseEvents(NPaintCanvas canvas) { 
     this.canvas = canvas; 
     this.canvas.addMouseMotionListener(this); 
     this.canvas.addMouseListener(this); 
    } 

    @Override 
    public void mouseDragged(MouseEvent e) { 
     if(canvas.px == 0 && canvas.py == 0){ 
      canvas.px = e.getX(); 
      canvas.py = e.getY(); 
     } 
     canvas.x = e.getPoint().x; 
     canvas.y = e.getPoint().y; 
     canvas.px = canvas.x; 
     canvas.py = canvas.y; 
    } 
} 

我在这里的主要问题是,在拖动点绘制的,但他们有他们like this之间的空间。我想加入实线。任何帮助进一步的提示将不胜感激。

+0

有许多的方式来实现这一目标。 1)在当前点和最后点之间绘制一个'Line2D'。 2)将所有点添加到一个'GeneralPath'并且每次添加一个新的点时绘制它。顺便说一句:为了更快地提供更好的帮助,请发布[MCVE]或[简短,独立,正确的示例](http://www.sscce.org/)。为此,需要将除main(String [])'类之外的所有类都还原为默认值,并将其放在NPaintMain末尾,然后添加导入。 –

+0

@安德鲁·汤普森我不确定我是否有这个权利。 –

+0

查看编辑的评论..噢,对,我没有(从来没有)密切关注代码,直到有一个MCVE,编译在我的IDE .. –

回答

2

你的问题是你画一个单一的点到每个鼠标拖动。

对于每条画线:x1和x2是相同的,y1和y2是相同的。
你应该在两个不同的点之间画一条线。 我已经更新了您的代码,通过引入两个不同的点:prev和实际点。
为了简单解释,仅当前一个点和实际点具有值时绘制一条线。
当绘制一条线时,最后一个实际绘制点将成为下一个绘制线的上一个点。这样,你就不会在线条之间产生空洞了。

在Canvas类:

if (previousPoint != null && actualPoint != null) { 
    l.add(new Line2D.Double(previousPoint.x, previousPoint.y, actualPoint.x, actualPoint.y)); 
    previousPoint = new Point(actualPoint.x, actualPoint.y); 
} 

如果你松开鼠标按钮,前面的和实际点都设置为null。

在事件类:

@Override 
    public void mouseReleased(MouseEvent e) { 
     canvas.mouseReleased(); 
    } 

在Canvas类:

public void mouseReleased() { 
    previousPoint = null; 
    actualPoint = null; 
    } 

通过这种方式,可以绘制线条倍数以独立的方式,如果你想。

此外,我已使用Point实例(而不是双打)使用点坐标简化了代码,但您可以使用多个双打字段,它在实践中并不会改变很多事情。

package paint; 

import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.geom.Line2D; 

import java.util.ArrayList; 

import javax.swing.JPanel; 

public class NPaintCanvas extends JPanel { 
    ArrayList<Line2D> l; 
    Point actualPoint; 
    Point previousPoint; 

    public NPaintCanvas() { 
    new NPaintMouseEvents(this); 
     l = new ArrayList<>(); 
    } 



    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g; 
     for (Line2D ll : l) { 
      g2d.draw(ll); 
     } 
     if (previousPoint != null && actualPoint != null) { 
      l.add(new Line2D.Double(previousPoint.x, previousPoint.y, actualPoint.x, actualPoint.y)); 
      previousPoint = new Point(actualPoint.x, actualPoint.y); 
     } 
     g.dispose(); 
     repaint(); 
    } 

    public void mouseReleased() { 
     previousPoint = null; 
     actualPoint = null; 
    } 

    public void mousePressed(int x, int y) { 
     previousPoint = new Point(x, y); 
    } 
} 

NPaintMouseEvent

package paint; 

import java.awt.Point; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.event.MouseMotionListener; 

public class NPaintMouseEvents implements MouseListener, MouseMotionListener { 

    NPaintCanvas canvas; 

    public NPaintMouseEvents(NPaintCanvas canvas) { 
     this.canvas = canvas; 
     this.canvas.addMouseMotionListener(this); 
     this.canvas.addMouseListener(this); 
    } 

    @Override 
    public void mouseDragged(MouseEvent e) { 
     if (canvas.actualPoint == null) { 
     canvas.actualPoint = new Point(); 
     } 
     canvas.actualPoint.x = e.getPoint().x; 
     canvas.actualPoint.y = e.getPoint().y; 
    } 

    @Override 
    public void mouseMoved(MouseEvent e) { 
    } 

    @Override 
    public void mouseClicked(MouseEvent e) { 
    } 

    @Override 
    public void mousePressed(MouseEvent e) { 
     canvas.mousePressed((int) e.getX(), (int) e.getY()); 
    } 

    @Override 
    public void mouseReleased(MouseEvent e) { 
     canvas.mouseReleased(); 
    } 

    @Override 
    public void mouseEntered(MouseEvent e) { 
    } 

    @Override 
    public void mouseExited(MouseEvent e) { 
    } 
} 
+0

谢谢:)。我知道在这个问题中没有问你这个问题,但是你能帮助我解决这个问题 - >即使在释放鼠标并从面板的某个角落开始后,最后一点和新点也会加入。是因为我在使用ArrayList吗?你能帮我一下吗? –

+0

不客气:) 不,不应该。它与你的名单没有关系。我的示例代码调用canvas.mouseReleased();在事件类中避免它。你可能忘了从我的例子中复制一些东西。我在我的答案中解释它。 – davidxxx

+0

对不起我的坏! :) –

2

您正在修改您的对象状态paintXXX - 这是错误的。 paint方法仅用于绘制当前状态。

你应该在MouseListener添加鼠标点到列表中,并调用rapaint标记您的canvas类在EDT被粉刷一新。

paintComponent应该始终只绘制当前列表。

所以,你应该这样来做:

public class NPaintCanvas extends JPanel { 
    ArrayList<Line2D> l; 
    public NPaintCanvas() { 
     new NPaintMouseEvents(this); 
     l = new ArrayList<>(); 
    } 
    @Override 
    public void paintComponent(Graphics g){ 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g; 
      for(Line2D ll: l){ 
       g2d.draw(ll); 
      } 
    } 
} 


public class NPaintMouseEvents implements MouseListener,MouseMotionListener { 

    NPaintCanvas canvas; 
    Point2D prev; 
    public NPaintMouseEvents(NPaintCanvas canvas) { 
     this.canvas = canvas; 
     this.canvas.addMouseMotionListener(this); 
     this.canvas.addMouseListener(this); 
    } 

    @Override 
    public void mouseDragged(MouseEvent e) { 
     if (prev==null) { 
      prev=e.getPoint(); 
      return; 
     } 
     Point2D p = new Line2D.Double(e.getPoint().x,e.getPoint().y); 
     if (p.equals(prev)) return ; //not really moved 
     canvas.l.add(prev, p); 
     p=prev; 
     canvas.repaint(); 
    } 
} 

注:最佳解决方案,你应该保持点,并采用GeneralPath

+0

谢谢:)会牢记这一点! –