使用Java Swing繪製隨鼠標拖拽可見軌跡的矩形(不會一直繪製矩形,而是類似ps中的矩形工具)
作爲學生黨,爲了完成java程序設計的實驗(自制小畫板工具),在網上找了很久相關的資料,但是結果都不太理想,。而且由於是第一次接觸java,雖然以前學c和c++,還自己看過一段c#,但對於Gui編程是一頭霧水(Api函數多到爆炸,頭皮發麻)。這一上手直接圖形界面,還是十分頭疼的。
好了,說重點吧,其實這個小程序最難搞的(我認爲)就是繪製矩形或橢圓的時候讓其顯示動態軌跡。如ps中的矩形工具那樣的效果。
爲了做到這個,我可是想了不少辦法(畢竟是小白),
首先,直接在mouseDragged 中獲取x,y值,傳到繪製矩形的函數中,但是這樣做的後果是繪製時矩形是隨着mouseDragged的觸發頻率連續繪製的,效果慘不忍睹,不說了,看圖
紅線畫出的地方就是因爲事件一直連續發生,所以繪製出的矩形的座標點也是連續的,這樣一畫就是一大片。
這種方法嘗試失敗後,我又想了另一種方法,借鑑於Ps的圖層這種模式,我想將Bufferedimage當作一個圖層,每次在上面繪製當前的圖像,然後將圖像繪製到當作底板的jpanel上,豈不美滋滋。
我以爲graphics的Drawimage方法能將Bufferedimage的有效部分疊加繪製到對象Observer上,可是現實並不樂觀,事實證明這是不可行的。Drawimage每次會將Bufferedimage覆蓋到Observer上從而使得從前次繪製的不可見。
最後就是綜合了前兩種,既然每次會覆蓋,那就手動將他們的顏色疊加,在mouseReleased方法中獲取當前bufferedimage像素信息,與底層bufferedimage的像素信息,將表層中爲0的值用底層的替代,最後將這個數組輸出到新的底層bufferedimage中,這樣再繪製一遍底層就能添加所需圖形了。
`import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class FSPaint extends JPanel {
//常量
private int PenStyle = 1;
private int a = 0, b = 0;
private int oa = 0, ob = 0;
private int LastX = 0, LastY = 0;
private boolean Drag = false;
private boolean Save = false;
private Graphics2D Pen;
//控件
private Font Tip_font;
private JLabel Position_X;
private JLabel Position_Y;
//緩衝區
private BufferedImage Temp;
private BufferedImage STemp;
public FSPaint ( ) throws IOException, FontFormatException {
setSize (786, 385);
setBackground (Color.BLACK);
//設置字體
Tip_font = Font.createFont (Font.TRUETYPE_FONT, new FileInputStream (new File ("D:\\P\\java\\T0\\src\\swfit .TTF")));
Tip_font = Tip_font.deriveFont (8.0f);
super.setVisible (true);
Temp = new BufferedImage (786, 385, BufferedImage.TYPE_4BYTE_ABGR_PRE);
setCursor (Toolkit.getDefaultToolkit ().createCustomCursor (
Toolkit.getDefaultToolkit ().getImage (this.getClass ().getResource ("arr_pen.png")), new Point (0, 0), "stick"));
//Position
Position_X = new JLabel ();
Position_X.setFont (Tip_font);
Position_X.setForeground (new Color (170, 170, 170));
Position_X.setText ("x:" + " ");
Position_Y = new JLabel ();
Position_Y.setFont (Tip_font);
Position_Y.setForeground (new Color (170, 170, 170));
Position_X.setText ("y:" + " ");
this.addMouseListener (new java.awt.event.MouseAdapter () {
public void mouseReleased ( MouseEvent e ) {
Drag = false;
//Temp = AddToBg (STemp, Temp);
switch ( PenStyle ) {
case 0:
break;
case 1:
}
}
public void mouseEntered ( MouseEvent e ) {
switch ( PenStyle ) {
case 0:
break;
case 1:
}
}
public void mouseExited ( MouseEvent e ) {
repaint ();
}
public void mousePressed ( MouseEvent e ) {
oa = a = e.getX ();
ob = b = e.getY ();
}
});
this.addMouseMotionListener (new MouseAdapter () {
@Override
public void mouseDragged ( MouseEvent e ) {
super.mouseDragged (e);
Drag = true;
switch ( PenStyle ) {
case 0:
DrawAny (Pen, e.getX (), e.getY ());
break;
case 1:
DrawRect (Pen, e.getX (), e.getY ());
break;
}
}
@Override
public void mouseMoved ( MouseEvent e ) {
SetPosition (e.getX (), e.getY ());
}
});
}
public void setPenStyle ( int mode ) {
this.PenStyle = mode;
}
@Override
protected void paintComponent ( Graphics g ) {
super.paintComponent (g);
Graphics2D G = ( Graphics2D ) g;
DrawbacBground (G);
G.drawImage (Temp, 0, 0, 786, 385, this);
// if ( Drag ) G.drawImage (STemp, 0, 0, 786, 385, this);
}
//繪製背景
private void DrawbacBground ( Graphics2D G ) {
G.setColor (new Color (42, 22, 22));
G.fillRect (1, 1, 784, 384);
G.setColor (new Color (26, 13, 13));
G.fillRect (0, 0, 1, 384);
G.setColor (new Color (49, 26, 26));
G.fillRect (1, 0, 785, 1);
G.setColor (new Color (59, 31, 31));
G.fillRect (815, 0, 1, 385);
G.setColor (new Color (32, 17, 17));
G.fillRect (0, 384, 785, 1);
}
//畫筆工具
private void DrawAny ( Graphics2D g, int x, int y ) {
g = ( Graphics2D ) Temp.getGraphics ();
g.setColor (new Color (255, 255, 255));
g.setStroke (new BasicStroke (1.0f));
g.drawLine (a, b, x, y);
a = x;
b = y;
repaint ();
g.dispose ();
}
//繪製矩形
private void DrawRect ( Graphics2D g, int x, int y ) {
// STemp = new BufferedImage (786, 385, BufferedImage.TYPE_4BYTE_ABGR_PRE);
// g = ( Graphics2D ) STemp.getGraphics ();
g = ( Graphics2D ) Temp.getGraphics ();
a = x - oa > 0 ? x - oa : oa - x;
b = y - ob > 0 ? y - ob : ob - y;
LastX = oa > x ? x : oa;
LastY = ob > y ? y : ob;
g.setColor (new Color (255, 255, 255));
g.fillRect (LastX, LastY, a, b);
repaint ();
g.dispose ();
}
//顯示座標
private void SetPosition ( int x, int y ) {
Position_X.setText ("x:" + " " + "" + x);
Position_Y.setText ("y:" + " " + "" + y);
}
//圖層疊加
private BufferedImage AddToBg ( BufferedImage up, BufferedImage down ) {
BufferedImage Combain = new BufferedImage (down.getWidth (), down.getHeight (), BufferedImage.TYPE_4BYTE_ABGR_PRE);
int[] upRgb;
int[] downRgb;
upRgb = up.getRGB (0, 0, up.getWidth (), up.getHeight (), null, 0, up.getWidth ());
downRgb = down.getRGB (0, 0, down.getWidth (), down.getHeight (), null, 0, down.getWidth ());
for ( int i = 0; i < down.getWidth () * down.getHeight (); i++ )
if ( upRgb[ i ] != 0 ) downRgb[ i ] = upRgb[ i ];
//此處可插入圖像處理
Combain.setRGB (0, 0, down.getWidth (), down.getHeight (), downRgb, 0, down.getWidth ());
return Combain;
}
//外部顯示
public void Show_Position ( JFrame F ) {
Position_X.setVisible (true);
Position_X.setBounds (913, 576, 72, 15);
Position_Y.setVisible (true);
Position_Y.setBounds (985, 576, 72, 15);
F.add (Position_X);
F.add (Position_Y);
}
}
`