简体   繁体   English

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

[英]How to use drawOval() method correctly?

Ok, so I am trying to make a paint project and I am successful so far. 好的,所以我正在尝试一个绘画项目,到目前为止我已经成功了。 I have a "canvas" to draw on and I have a toolbar menu with the color choices. 我有一个“画布”可以绘制,并且有一个带有颜色选择的工具栏菜单。 I have made a button and method with drawLine() which takes my current coordinates via the mouse motion listener and my end coordinates, basically drawing the line wherever and however I like on the canvas. 我已经使用drawLine()制作了一个按钮和方法,该方法通过鼠标运动侦听器获取我的当前坐标和结束坐标,基本上可以在任意位置绘制线条,但是我喜欢在画布上绘制。 Now I want to add a button that when clicked, will draw an oval/circle on my canvas. 现在,我想添加一个按钮,当单击该按钮时,它将在我的画布上绘制一个椭圆形/圆形。 Here come the problems tho. 问题来了。

First problem - I can get it to draw the oval on my mouse coordinates, but I cannot drag in order to change its size before I release the mouse button and actually paint it (just like you would in Microsoft paint). 第一个问题-我可以用它在鼠标坐标上绘制椭圆形,但是在释放鼠标按钮并对其进行实际绘制之前,无法拖动它来更改其大小(就像在Microsoft Paint中一样)。

Second problem - When I have selected my "Line" button which invokes my draw line method, I can draw lines and its fine, but then when I click the "Oval" button, it draws the Oval but also puts a line when I click the mouse (I am assuming that I need to disable the mouse motion listener on the Line when I select the Oval.) The Opposite is also true, If I have selected the "Oval" button and drawn ovals before, then click the "Line" button, it will draw a line but also put an oval each time I click to start drawing a line. 第二个问题-选择调用“绘制线条”方法的“线条”按钮时,我可以绘制线条及其精细样式,但是当我单击“椭圆”按钮时,它会绘制椭圆形,但是当我单击时也会放置一条线条鼠标(假设我在选择椭圆时需要禁用Line上的鼠标运动侦听器。)相反,如果我选择了“ Oval”按钮并绘制了椭圆形,则单击“ Line”按钮,它会画一条线,但是每次单击开始画一条线时,也会画一个椭圆。

This is how my simple program looks like: Image 这是我的简单程序的样子: 图片

Here is part of the code concerning the drawLine, drawOval and my coordinate gathering methods, since everything else is working as intended: 这是有关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();
            }   
        }
    }); 
}

First problem - I can get it to draw the oval on my mouse coordinates, but I cannot drag in order to change its size before I release the mouse button and actually paint it (just like you would in Microsoft paint). 第一个问题-我可以用它在鼠标坐标上绘制椭圆形,但是在释放鼠标按钮并对其进行实际绘制之前,无法拖动它来更改其大小(就像在Microsoft Paint中一样)。

You'd could repaint the entire canvas every time you move the mouse but you probably don't want to do that. 您可以在每次移动鼠标时重新绘制整个画布,但是您可能不想这样做。 Instead you might want to use a second canvas to draw the temporary oval (or lines, boxes etc.) onto and repaint that whenever you drag the mouse. 相反,您可能想使用第二个画布在拖动鼠标时在其上绘制临时椭圆(或线条,框等)并重新绘制。 That's not that expensive since you'll only need one or a few of draw calls. 这并不是那么昂贵,因为您只需要一个或几个绘制调用即可。

When releasing the mouse you then draw the shape you currently selected onto the more persistent canvases. 释放鼠标时,您可以在更持久的画布上绘制当前选择的形状。 One way to achieve this would be to use a BufferedImage as your persistent canvas and your panel (or whatever canvas you're using) as the temporary one. 一种实现方法是将BufferedImage用作持久画布,将面板(或您正在使用的任何画布)用作临时画布。 Then when dragging the mouse you paint the image to the panel first then add the shape. 然后,当拖动鼠标时,首先将图像绘制到面板上,然后添加形状。 When releasing the mouse you draw the shape onto the image and then just draw the image to the panel and be done. 释放鼠标时,您可以在图像上绘制形状,然后只需将图像绘制到面板上即可。

That way you'd already have an image object you could write to a file if needed. 这样,您已经有了一个图像对象,可以根据需要将其写入文件。

Edit : looking at your code you seem to already have the image in place. 编辑 :查看您的代码,您似乎已经有了适当的图像。 So just change the graphics object your drawing temporary shapes to: as long as the mouse is being dragged, you could directly use the component you're drawing to. 因此,只需将图形对象的绘图临时形状更改为:只要拖动鼠标,您就可以直接使用绘图对象。

Second problem - When I have selected my "Line" button which invokes my draw line method, I can draw lines and its fine, but then when I click the "Oval" button, it draws the Oval but also puts a line when I click the mouse (I am assuming that I need to disable the mouse motion listener on the Line when I select the Oval.) 第二个问题-选择调用“绘制线条”方法的“线条”按钮时,我可以绘制线条及其精细样式,但是当我单击“椭圆”按钮时,它会绘制椭圆形,但是当我单击时也会放置一条线条鼠标(我假设选择椭圆形时需要禁用Line上的鼠标运动侦听器。)

Yes, you should probably only have one listener used for drawing (although the listener drawing itself seems to be questionable design, but I'll skip that for now). 是的,您可能应该只使用一个侦听器进行绘制(尽管该侦听器绘制本身似乎是有问题的设计,但我现在将略过)。 That listener records the mouse position when you pressed the button as well as the mouse position after dragging it or releasing the button again. 该监听器会记录您按下按钮时的鼠标位置以及拖动或再次释放按钮后的鼠标位置。

When releasing the button you'd check whether the position is inside the canvas or not and if not just forget the rest. 释放按钮时,您将检查该位置是否在画布内,如果不是,则只需忘记其余位置。 Thus you won't get any shapes drawn when clicking a button. 因此,单击按钮时不会绘制任何形状。

Additionally, clicking a button should probably just change the shape you're about to draw (either by setting some variable or by replacing the object that handles the actual drawing). 此外,单击按钮可能应该仅更改您要绘制的形状(通过设置一些变量或替换处理实际图形的对象)。 The mouse listener would then just use that information to draw the currently selected shape (if there is any) - ideally by informing the "drawer" about any relevant events. 然后,鼠标侦听器将仅使用该信息绘制当前选定的形状(如果有的话)-理想情况下是通过将任何相关事件告知“抽屉”。

Edit : example on using only one listener (simplified, ie without any checks, color etc.). 编辑 :仅使用一个侦听器的示例(简化,即,无需任何检查,颜色等)。

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() );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM