2012-12-29 185 views
4

我正在绘制绘制不同形状的绘画小程序。我想在拖动鼠标的同时画线。问题是,当线条出现时,它们如下图所示。拖动鼠标拖动时出现问题

enter image description here

我目前正使用一个点(起点) 构造类线,它有一个名为setDragPoint方法,为了画线需要拖动鼠标点的同时拖动也drawingImage让太多的闪烁同时以拖动模式绘图。为什么会发生?

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

public class PaintBrush extends Applet implements MouseListener, MouseMotionListener { 

Shape shape; 
Point startPoint; 
Point dragPoint; 
ArrayList<Shape> shapes; 
Choice shapeChoice; 
Choice colorChoice; 
Choice fillChoice; 
Image drawingImage; 
Graphics drawGraphics; 
String shapeString, colorString, fillString; 
boolean isDragMode; 

public void init() { 
    shapes = new ArrayList<Shape>(); 
    shapeChoice = new Choice(); 
    shapeChoice.addItem("Line"); 
    shapeChoice.addItem("Rectangle"); 
    shapeChoice.addItem("RoundRect"); 
    shapeChoice.addItem("Oval"); 
    shapeChoice.addItem("FreeHand"); 

    add(shapeChoice); 

    colorChoice = new Choice(); 
    colorChoice.addItem("Red"); 
    colorChoice.addItem("Green"); 
    colorChoice.addItem("Blue"); 

    add(colorChoice); 

    fillChoice = new Choice(); 
    fillChoice.addItem("Filled"); 
    fillChoice.addItem("Hollow"); 
    add(fillChoice); 

    shapeString = shapeChoice.getSelectedItem(); 
    colorString = colorChoice.getSelectedItem(); 
    fillString = fillChoice.getSelectedItem(); 

    drawingImage = createImage(getSize().width, getSize().height); 
    drawGraphics = drawingImage.getGraphics(); 
    System.out.println("set up image"); 
    drawGraphics.setColor(Color.black); 
    drawGraphics.fillRect(0, 0, getSize().width, getSize().height); 
    drawGraphics.setColor(Color.orange); 
    drawGraphics.drawRect(0, 0, getSize().width - 1, getSize().height - 1); 
    drawGraphics.drawRect(1, 1, getSize().width - 3, getSize().height - 3); 
    startPoint = new Point(0, 0); 
    dragPoint = new Point(0, 0); 
    addMouseListener(this); 
    addMouseMotionListener(this); 
} 

public void mouseEntered(MouseEvent e) { 
} 

public void mouseExited(MouseEvent e) { 
} 

public void mouseClicked(MouseEvent e) { 
} 

public void mousePressed(MouseEvent e) { 

    System.out.println("Pressed"); 

    startPoint.x = e.getX(); 
    startPoint.y = e.getY(); 
    repaint(); 

    switch (shapeString) { 
     case "Line": 
      shape = new Line(startPoint.x, startPoint.y); //step 1 here i construct a new line using the start point (the point at which the mouse is pressed) 

      break; 
     case "FreeHand": 
      shape = new FreeShape(); 
      break; 
    } 


    } 

public void mouseReleased(MouseEvent e) { 
    if (isDragMode) { 
     shapes.add(shape); 
     isDragMode = false; 
    } 
    repaint(); 

} 

public void mouseMoved(MouseEvent e) { 
} 

public void mouseDragged(MouseEvent e) { 
    System.out.println("Dragged"); 
    isDragMode = true; 
    dragPoint.x = e.getX(); 
    dragPoint.y = e.getY(); 

    switch (shapeString) { 
     case "Line": 
      shape.setDragPoint(dragPoint.x, dragPoint.y); //here i set the drag points to the already created line at step 1 
       break; 
     case "FreeHand": 
      shape = new FreeShape(); 
      break; 
    } 

    shape.drawWhileDragging(drawGraphics); // i call this method to draw while mouse is dragging 

    repaint(); 


} 

public void paint(Graphics g) { 

    update(g); 
} 
public void update(Graphics g) { 

    // create an off-screen graphics drawing environment if none 
    //existed 
    // or if the user resized the applet drawing area to a different 
// size 
    if (drawingImage == null) 
{ 

System.out.println("Image is Null"); 
    drawingImage = createImage(getSize().width,getSize().height); 
drawGraphics = drawingImage.getGraphics(); 
} 



    // erase the previous image 
    drawGraphics.setColor(Color.black); 
    drawGraphics.fillRect(0,0,getSize().width,getSize().height); 
    drawGraphics.setColor(Color.orange); 
    drawGraphics.drawRect(0,0,getSize().width-1,getSize().height-1); 
    drawGraphics.drawRect(1,1,getSize().width-3,getSize().height-3); 

    for(Shape s:shapes) 
     s.draw(drawGraphics); 

    // paint the offscreen image to the applet viewing window 
    g.drawImage(drawingImage,0,0,this); 

    } 
} 


abstract class Shape { 

Color shapeColor; 
boolean filled; 

abstract void draw(Graphics g); 

void drawWhileDragging(Graphics g) { 
} 

void setDragPoint(int x, int y) { 
} 
} 

class Line extends Shape { 

private Point startPoint; 
private Point currentPoint; 

public Point getStartPoint() { 
    return startPoint; 
} 

public Point getCurrentPoint() { 
    return currentPoint; 
} 

public void setStartPoint(Point point) { 
    this.startPoint = point; 
} 

public void setCurrentPoint(Point point) { 
    this.currentPoint = point; 
} 

void drawWhileDragging(Graphics g) { 
    g.drawLine(startPoint.x, startPoint.y, currentPoint.x, currentPoint.y); 
} 

public void draw(Graphics g) { 
    g.drawLine(startPoint.x, startPoint.y, currentPoint.x, currentPoint.y); 
} 

Line() { 
    startPoint = new Point(0, 0); 
    currentPoint = new Point(0, 0); 
} 

Line(int x1, int y1) { 
    this(); 
    this.startPoint.x = x1; 
    this.startPoint.y = y1; 
} 

void setDragPoint(int x, int y) { 
    this.currentPoint.x = x; 
    this.currentPoint.y = y; 
    System.out.println("Current-X:" + currentPoint.x + " currentPoint-Y" + currentPoint.y); 
    System.out.println("start-X:" + startPoint.x + " startPoint-Y" + startPoint.y); 
    } 

} 

class FreeShape extends Shape { 

private ArrayList<Point> dragPoints = new ArrayList<Point>(); 

public ArrayList<Point> getDragPoints() { 
    return dragPoints; 
} 

public void setDragPoints(Point point) { 
    dragPoints.add(point); 
} 

public void draw(Graphics g) { 
} 

public FreeShape() { 
    } 
} 


class Rectangle extends Shape { 

public void draw(Graphics g) { 
    } 
} 


class Oval extends Shape { 

public void draw(Graphics g) { 
    } 
} 
+2

'public class PaintBrush extends Applet..'它应该在这个千禧年中扩展'JApplet'。 –

+0

'不能打开字符串类型的值。只有可转换的int值或枚举常量是允许的,是否显示给你? – Parth

+3

有点话题:你的Windows 7副本不是真的。 – 2012-12-29 07:45:48

回答

1

我最近写了一个类似的应用程序。这是截图。它没有完全发展,你可以看到。 enter image description here

现在,我还面临类似的问题,因为你现在面临着。你必须做的是。

  • 双缓冲所有的绘画操作
  • 请勿通过调用重绘清除屏幕。 Repaint实际上首先用背景色&填充屏幕,那就是你看到的闪烁。

您可以在Image中制作当前屏幕画布的副本。 Image将在每次绘图操作后更新。因此,通过调用repaint来清除屏幕,您所做的是在画布上绘制Image。这就像双缓冲。

在您的代码中,每次拖动鼠标时都会调用repaint。这是闪烁的原因。


UPDATE

三个我在你新更新的代码

  • 发现在drawWhileDragging方法主要问题你不改变线路图形上下文绘制颜色。所以这条线实际上是用黑色绘制的,而且你的背景也是黑色的。结果你什么也看不见。
  • 在此相同的方法中,您传递的图形上下文(即引用)为drawingImage。因此,该线实际上是在屏幕外图像上绘制的,而不是在屏幕上。
  • mouseDragged方法中,您在每次拖动之后调用repaint。因此,实际上没有任何东西被绘

我已经在我的机器上运行您的代码,并做了必要的更改。我只发布更改的方法,以保持它简短。

这里是更新mouseDragged方法

public void mouseDragged(MouseEvent e) { 
     System.out.println("Dragged"); 
     isDragMode = true; 
     dragPoint.x = e.getX(); 
     dragPoint.y = e.getY(); 

     switch (shapeString) { 
      case "Line": 
       shape.setDragPoint(dragPoint.x, dragPoint.y); //here i set the drag points to the already created line at step 1 
       break; 
      case "FreeHand": 
       shape = new FreeShape(); 
       break; 
     } 

     getGraphics().drawImage(drawingImage, 0,0,null); //Added this line 
     shape.drawWhileDragging(getGraphics()); // i call this method to draw while mouse is dragging 
    } 

这里是更新drawWhileDragging方法

void drawWhileDragging(Graphics g) { 
     g.setColor(Color.ORANGE); 
     g.drawLine(startPoint.x, startPoint.y, currentPoint.x, currentPoint.y); 
     g.setColor(Color.BLACK); 
    } 

好了,我已经设置颜色为橙色。你需要做的是根据Choice菜单设置颜色。

您也可以实施类似的绘制其他形状的类比。

+0

默认情况下,Swing组件是双缓冲区... – MadProgrammer

+0

@MadProgrammer最初发布的代码使用的是Applet而不是JApplet,这就是为什么我建议双缓冲 –

+0

@ExtremeCoders问题是,OP尝试在双缓冲造成他们的问题 - 我同意这个概念,但我相信我们可以做得更好;) – MadProgrammer

0

您遇到的问题归结为您如何“尝试”执行双缓冲。而不是在更新行位置时清除后台缓冲区,您可以简单地连续绘制它 - 有点像在黑板上绘图......

相反,您需要清除图形内容并重新应用更新 - 出人意料的是,这是部分什么paint实际上做了,但你永远不叫super.paint

很少有需要覆盖顶层容器,你也不应该很少需要重写顶层容器的paint方法。除了一切,没有双重缓冲。

取而代之,请使用类似JPanel的东西。

我已更新您的示例,不包括颜色。颜色实际上应该由形状来保持,并在涂漆时应用。

public class BadPaint06 extends JApplet { 

    public void init() { 
     setLayout(new BorderLayout()); 
    } 

    @Override 
    public void start() { 
     add(new PaintPane()); 
    } 

    public class PaintPane extends JPanel implements MouseListener, MouseMotionListener { 

     Shape shape; 
     Point startPoint; 
     Point dragPoint; 
     ArrayList<Shape> shapes; 
     Choice shapeChoice; 
     Choice colorChoice; 
     Choice fillChoice; 
     Image drawingImage; 
     Graphics drawGraphics; 
     String shapeString, colorString, fillString; 
     boolean isDragMode; 

     public PaintPane() { 
      shapes = new ArrayList<Shape>(); 
      shapeChoice = new Choice(); 
      shapeChoice.addItem("Line"); 
      shapeChoice.addItem("Rectangle"); 
      shapeChoice.addItem("RoundRect"); 
      shapeChoice.addItem("Oval"); 
      shapeChoice.addItem("FreeHand"); 

      add(shapeChoice); 

      colorChoice = new Choice(); 
      colorChoice.addItem("Red"); 
      colorChoice.addItem("Green"); 
      colorChoice.addItem("Blue"); 

      add(colorChoice); 

      fillChoice = new Choice(); 
      fillChoice.addItem("Filled"); 
      fillChoice.addItem("Hollow"); 
      add(fillChoice); 

      shapeString = shapeChoice.getSelectedItem(); 
      colorString = colorChoice.getSelectedItem(); 
      fillString = fillChoice.getSelectedItem(); 

      startPoint = new Point(0, 0); 
      dragPoint = new Point(0, 0); 
      addMouseListener(this); 
      addMouseMotionListener(this); 
     } 

     @Override 
     public void invalidate() { 

      drawingImage = null; 

      super.invalidate(); 

     } 

     public void mouseEntered(MouseEvent e) { 
     } 

     public void mouseExited(MouseEvent e) { 
     } 

     public void mouseClicked(MouseEvent e) { 
     } 

     public void mousePressed(MouseEvent e) { 

      startPoint.x = e.getX(); 
      startPoint.y = e.getY(); 
      repaint(); 

      switch (shapeString) { 
       case "Line": 
        shape = new Line(startPoint.x, startPoint.y); //step 1 here i construct a new line using the start point (the point at which the mouse is pressed) 

        break; 
       case "FreeHand": 
        shape = new FreeShape(); 
        break; 
      } 


     } 

     public void mouseReleased(MouseEvent e) { 
      if (isDragMode) { 
       shapes.add(shape); 
       isDragMode = false; 
      } 
      repaint(); 

     } 

     public void mouseMoved(MouseEvent e) { 
     } 

     public void mouseDragged(MouseEvent e) { 
      System.out.println("Dragged"); 
      isDragMode = true; 
      dragPoint.x = e.getX(); 
      dragPoint.y = e.getY(); 

      switch (shapeString) { 
       case "Line": 
        shape.setDragPoint(dragPoint.x, dragPoint.y); //here i set the drag points to the already created line at step 1 
        break; 
       case "FreeHand": 
        shape = new FreeShape(); 
        break; 
      } 

      repaint(); 


     } 

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

      System.out.println("In Paint"); 
      if (drawingImage == null) { 
       drawingImage = createImage(getSize().width, getSize().height); 
       drawGraphics = drawingImage.getGraphics(); 
       System.out.println("set up image"); 
       drawGraphics.setColor(Color.black); 
       drawGraphics.fillRect(0, 0, getSize().width, getSize().height); 
       drawGraphics.setColor(Color.orange); 
       drawGraphics.drawRect(0, 0, getSize().width - 1, getSize().height - 1); 
       drawGraphics.drawRect(1, 1, getSize().width - 3, getSize().height - 3); 
       drawGraphics.dispose(); 
      } 

      g.drawImage(drawingImage, 0, 0, this); 

      for (Shape shape : shapes) { 
       shape.draw(g); 
      } 


      if (shape != null) { 
       shape.drawWhileDragging(g); // i call this method to draw while mouse is dragging 
      } 

     } 
    } 

    abstract class Shape { 

     Color shapeColor; 
     boolean filled; 

     abstract void draw(Graphics g); 

     void drawWhileDragging(Graphics g) { 
     } 

     void setDragPoint(int x, int y) { 
     } 
    } 

    class Line extends Shape { 

     private Point startPoint; 
     private Point currentPoint; 

     public Point getStartPoint() { 
      return startPoint; 
     } 

     public Point getCurrentPoint() { 
      return currentPoint; 
     } 

     public void setStartPoint(Point point) { 
      this.startPoint = point; 
     } 

     public void setCurrentPoint(Point point) { 
      this.currentPoint = point; 
     } 

     void drawWhileDragging(Graphics g) { 
      if (currentPoint != null) { 
       g.drawLine(startPoint.x, startPoint.y, currentPoint.x, currentPoint.y); 
      } 
     } 

     public void draw(Graphics g) { 
      if (currentPoint != null) { 
       g.drawLine(startPoint.x, startPoint.y, currentPoint.x, currentPoint.y); 
      } 
     } 

     Line() { 
      startPoint = new Point(0, 0); 
//   currentPoint = new Point(0, 0); 
     } 

     Line(int x1, int y1) { 
      this(); 
      this.startPoint.x = x1; 
      this.startPoint.y = y1; 
     } 

     void setDragPoint(int x, int y) { 
      currentPoint = new Point(x, y); 
//   this.currentPoint.x = x; 
//   this.currentPoint.y = y; 
      System.out.println("Current-X:" + currentPoint.x + " currentPoint-Y" + currentPoint.y); 
      System.out.println("start-X:" + startPoint.x + " startPoint-Y" + startPoint.y); 
     } 
    } 

    class FreeShape extends Shape { 

     private ArrayList<Point> dragPoints = new ArrayList<Point>(); 

     public ArrayList<Point> getDragPoints() { 
      return dragPoints; 
     } 

     public void setDragPoints(Point point) { 
      dragPoints.add(point); 
     } 

     public void draw(Graphics g) { 
     } 

     public FreeShape() { 
     } 
    } 

    class Rectangle extends Shape { 

     public void draw(Graphics g) { 
     } 
    } 

    class Oval extends Shape { 

     public void draw(Graphics g) { 
     } 
    } 
} 
+0

我更新了我的paint&update方法,让它们擦除之前的图像并绘制新的图像,但这次drawWhileDragging方法完全没有效果图片!!请参阅我的更新方法 –

+0

@Eslam您的'drawWhileDragging'和'draw'方法是相同的,我不确定它们有什么区别。 – MadProgrammer

+0

只有在鼠标被释放后才会调用draw方法,所以我使drawWhileDragging在鼠标拖动时绘制,我测试了它,它被调用但图像没有更新,但由于我上次更新,闪烁被删除 –