如何正确使用drawOval()方法?

时间:2016-06-13 11:39:49

标签: java swing paint

好的,所以我想做一个油漆项目,到目前为止我都很成功。我有一个“画布”可以画画,我有一个带有颜色选择的工具栏菜单。我用drawLine()创建了一个按钮和方法,它通过鼠标运动监听器和我的结束坐标获取当前坐标,基本上绘制线条,无论我喜欢什么样的画布。现在我要添加一个按钮,单击该按钮将在我的画布上绘制一个椭圆/圆。这里出现了问题。

第一个问题 - 我可以让它在我的鼠标坐标上绘制椭圆形,但是在我释放鼠标按钮并实际绘制它之前我无法拖动以改变它的大小(就像你在微软绘画中那样)。 / p>

第二个问题 - 当我选择了我的“Line”按钮调用我的绘制线方法时,我可以绘制线条并且很好,但是当我点击“椭圆形”按钮时,它会绘制椭圆形但是也会放一条线当我单击鼠标时(我假设我需要在选择椭圆时在线上禁用鼠标移动侦听器。)相反也是如此,如果我之前选择了“椭圆”按钮并绘制了椭圆,则单击在“线”按钮上,每次点击开始绘制一条线时,它都会绘制一条线,但也会放一条椭圆。

这就是我的简单程序的样子: Image

以下是关于drawLine,drawOval和我的坐标收集方法的代码的一部分,因为其他一切都按预期工作:

    // Image in which we're drawing.
    private Image image;
    // Graphics2D object which we used to draw on.
    private Graphics2D g2;
    // Mouse coordinates
    private int currentX, currentY, oldX, oldY;

    public DrawArea(){
        setDoubleBuffered(false);
        addMouseListener(new MouseAdapter(){

            public void mousePressed(MouseEvent e){
                //save coordinates x,y when mouse is pressed.
                oldX=e.getX();
                oldY=e.getY();
            }});

    }

protected void paintComponent(Graphics g){
    if (image==null){
        //image to draw null ==> we create
        image = createImage(getSize().width, getSize().height);
        g2 = (Graphics2D) image.getGraphics();
        //enable antialiasing.
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                RenderingHints.VALUE_ANTIALIAS_ON);
        //clear draw area
        clear();
    }

    g.drawImage(image, 0, 0, null);
}

public void clear(){
    g2.setPaint(Color.white);
    //draw white on entire draw are to clear it.
    g2.fillRect(0, 0, getSize().width, getSize().height);
    g2.setPaint(Color.black);
    repaint();
}

public void Line(){
    addMouseMotionListener(new MouseMotionAdapter(){
        public void mouseDragged(MouseEvent e){
            //coordinates x,y when dragging mouse.
            currentX=e.getX();
            currentY=e.getY();
            if (g2 != null){
                g2.drawLine(oldX, oldY, currentX, currentY);
                repaint();
                oldX = currentX;
                oldY = currentY;
            }   
        }
    }); 
}

public void Oval(){
    addMouseListener(new MouseAdapter(){
        public void mousePressed(MouseEvent e){
            currentX=e.getX();
            currentY=e.getY();
            if (g2 != null){
                g2.drawOval(oldX, oldY, currentX, currentY);
                repaint();
            }   
        }
    }); 
}

1 个答案:

答案 0 :(得分:0)

  

第一个问题 - 我可以让它在我的鼠标坐标上绘制椭圆形,但是在我释放鼠标按钮并实际绘制它之前我无法拖动以改变它的大小(就像你在微软绘画中那样)。 / p>

每次移动鼠标时都可以重绘整个画布,但是你可能不希望这样做。相反,您可能希望使用第二个画布将临时椭圆(或线条,方框等)绘制到每个拖动鼠标时重新绘制。这并不贵,因为你只需要一个或几个绘制调用。

释放鼠标时,然后将当前选中的形状绘制到更持久的画布上。实现此目的的一种方法是使用BufferedImage作为持久性画布,并使用面板(或任何您正在使用的画布)作为临时画布。然后,在拖动鼠标时,首先将图像绘制到面板,然后添加形状。释放鼠标时,将图形绘制到图像上,然后将图像绘制到面板上并完成。

这样你就可以拥有一个可以根据需要写入文件的图像对象。

编辑:查看您的代码,您似乎已经有了图像。因此,只需将绘图临时形状的图形对象更改为:只要拖动鼠标,就可以直接使用要绘制的组件。

  

第二个问题 - 当我选择了我的“Line”按钮调用我的绘制线方法时,我可以绘制线条并且很好,但是当我点击“椭圆形”按钮时,它会绘制椭圆形但是也会放一条线当我单击鼠标时(我假设我需要在选择椭圆时禁用线上的鼠标移动侦听器。)

是的,你应该只有一个用于绘图的监听器(虽然监听器绘图本身似乎是有问题的设计,但我现在将跳过它)。当您按下按钮时,该监听器会记录鼠标位置,以及在拖动按钮或再次释放按钮后鼠标位置。

释放按钮时,您将检查位置是否在画布内,如果不是,则忘记其余部分。因此,单击按钮时不会绘制任何形状。

此外,单击按钮可能只是更改您要绘制的形状(通过设置某个变量或替换处理实际绘图的对象)。然后,鼠标监听器将使用该信息绘制当前选定的形状(如果有的话) - 理想情况下通过向“抽屉”通知任何相关事件。

编辑:仅使用一个侦听器的示例(简化,即没有任何检查,颜色等)。

interface Renderer {
  void draw( Graphics2D g, Point start, Point end );
}

class OvalRenderer implements Renderer {
  public void draw( Graphics2D g, Point start, Point end ) {
    g.drawOval(start.getX(), start.getY(), end.getY(), end.getY() );
  }
}

class CanvasListener extends MouseAdapter {
  Point start;
  public void mousePressed(MouseEvent e){
    start = e.getPoint(); 
  }

  public void mouseDragged(MouseEvent e){  
    //currentRenderer is defined elsewhere and just made accessible to the listener
    currentRenderer.draw( component.getGraphics(), start, e.getPoint() );
  }

  public void mouseReleased(MouseEvent e){  
    currentRenderer.draw( image.getGraphics(), start, e.getPoint() );
  }
}