[英]How to use drawOval() method correctly?
好的,所以我正在尝试一个绘画项目,到目前为止我已经成功了。 我有一个“画布”可以绘制,并且有一个带有颜色选择的工具栏菜单。 我已经使用drawLine()
制作了一个按钮和方法,该方法通过鼠标运动侦听器获取我的当前坐标和结束坐标,基本上可以在任意位置绘制线条,但是我喜欢在画布上绘制。 现在,我想添加一个按钮,当单击该按钮时,它将在我的画布上绘制一个椭圆形/圆形。 问题来了。
第一个问题-我可以用它在鼠标坐标上绘制椭圆形,但是在释放鼠标按钮并对其进行实际绘制之前,无法拖动它来更改其大小(就像在Microsoft Paint中一样)。
第二个问题-选择调用“绘制线条”方法的“线条”按钮时,我可以绘制线条及其精细样式,但是当我单击“椭圆”按钮时,它会绘制椭圆形,但是当我单击时也会放置一条线条鼠标(假设我在选择椭圆时需要禁用Line上的鼠标运动侦听器。)相反,如果我选择了“ Oval”按钮并绘制了椭圆形,则单击“ Line”按钮,它会画一条线,但是每次单击开始画一条线时,也会画一个椭圆。
这是我的简单程序的样子: 图片
这是有关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();
}
}
});
}
第一个问题-我可以用它在鼠标坐标上绘制椭圆形,但是在释放鼠标按钮并对其进行实际绘制之前,无法拖动它来更改其大小(就像在Microsoft Paint中一样)。
您可以在每次移动鼠标时重新绘制整个画布,但是您可能不想这样做。 相反,您可能想使用第二个画布在拖动鼠标时在其上绘制临时椭圆(或线条,框等)并重新绘制。 这并不是那么昂贵,因为您只需要一个或几个绘制调用即可。
释放鼠标时,您可以在更持久的画布上绘制当前选择的形状。 一种实现方法是将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() );
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.