[英]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.