用Java語言編寫一個簡易畫板


 

    講了三篇概博客的概念,今天,我們來一點實際的東西。我們來探討一下如何用Java語言,編寫一塊簡易的畫圖板。

一、需求分析

    無論我們使用什么語言,去編寫一個什么樣的項目,我們的第一步,總是去分析這個項目需要滿足怎樣的需求。

    那么,畫板需要滿足怎樣的需要呢?換句話說,在畫板上,我們應該賦予它什么功能呢?從我們熟悉的畫板來看,我們需要實現諸如鉛筆、橡皮、噴槍、刷子的功能,我們可以畫出一些規則的圖形,比如直線、矩形、圓。最好我們還能調整畫筆的顏色和粗細。以上,我們希望的是,當我們點擊一個按鈕的時候,我們就能實現相對應的功能。一個簡單畫板的功能大概就這么多了,一些關於添加文本框、放大鏡等的操作在簡單畫板上就不一一實現了。

二、實現畫板

1、基本圖形的繪制

    我們先從最基本的畫一些基本圖形開始。在Java里有一個畫筆類Graphics,而我們實現畫板功能的關鍵就在這里。在Graphics這個畫筆類里面,有幾個方法,比如:畫矩形、圓、直線。了解了這一點,我們的思路就來了。接下來,我們將一步一步認識實現基本圖形繪制的全過程。

    首先,我們需要實例化一個JFrame容器,並給它設置初始值。其次,我們需要在這個容器上,添加一些按鈕。這里以直線、矩形、圓為例。這部分的實現比較簡單,需要注意的是,我們可以通過實例化一個字符串類型的數組去存儲按鈕里的內容,然后通過遍歷數組的方式去實現多個按鈕的建立,以此減少代碼行數。給出代碼如下:

 

    其次,因為涉及到關於鼠標點擊以及按鈕點擊的操作,我們需要用到事件監聽機制,MouseListener和ActionListener。因為它們都是接口,不能被實例化對象,所以我們需要建立一個事件處理類去實現這兩個接口,並重寫其中的抽象方法。具體代碼如下:

    當然,僅僅這樣是不夠的。首先,我們需要對事件源,也就是我們的按鈕和畫板界面通過addXXXListener的方式添加事件處理機制。其次,我們還需要對對應的方法,在其方法體中寫上我們需要實現的功能。畫筆類是一個抽象類,因此它是不能被實例化的,我們只能通過getGraphics這個方法從JFrame或者是JPanel里去獲取畫筆。注意,畫筆的獲取要在讓界面可見之后。之后,因為我們在事件處理類里面要用到畫筆,所以,我們還需要將畫筆從我們的畫板界面傳到我們的事件處理類當中,我們可以在事件處理類里面定義一個setGraphics的方法,同時定義一個Graphics的引用去接收這個畫筆。具體代碼如下:

 

 

 

    接下來就是調用畫筆里的方法了。舉個例子,當我們獲取的按鈕里的內容是Line的時候,那么,我們需要調用畫筆Graphics里的drawLine方法,我們需要給它起始點和終點的x,y坐標。所以,我們在mousePressed方法里,記錄下起始點的x,y坐標,在mouseReleased里記錄下釋放點的xy坐標,然后調用這個drawLine方法。那么,我們就可以在我們按下和釋放的地方連成一條直線。代碼實現如下:

 

    這樣我們就實現了三個基本圖形的繪制。其他的, 在Graphics畫筆類里面還有關於弧形、多邊形、填充矩形等繪制方法,這里就不一一列舉了。

2、畫筆顏色與粗細的變化

    Java里有一個Color類,它可以用作畫筆顏色的設置。除了固定顏色的選取,例如Color.BLACK,我們程序員自己還可以自己去調取顏色。我們知道,每一種顏色,都可以由紅、綠、藍三基色按不同程度調配而成。在Java里有一個關於Color的構造方法,傳入三個int類型、范圍在0到255之間的數,分別對應紅綠藍三種顏色的程度。我們可以通過Color 顏色名=new Color(int a,int b,int c)的方式去自行定義自己想要的顏色。之后,我們可以通過.setColor的方式,將我們新建的顏色賦給我們的畫筆。

    而關於畫筆粗細的設置方法,它並不在Graphics類里面,而是在它的子類Graphics2D里面。相較於Graphics,Graphics2D同樣是一個抽象類,但是它里面新增了不少方法,比如給畫筆設置粗細的方法setStroke。而在setStroke這個方法中,你所需要傳遞的參數是一個Stroke類型的參數,而Stroke是一個接口,所以不能夠實例化,因此我們給它傳遞的是Stroke的一個封裝類BasicStroke,它實現了Stroke這個接口。因此,我們設置粗細的方式為:(Graphics2D)g.setStroke(new BasicStroke(float width))。

    如果我們需要實現這樣的情況,在畫板界面里有紅、綠、藍等多種顏色的按鈕,當點擊后畫筆變成相應顏色,我們可以通過給按鈕設置顏色的方式去處理這樣的問題。給按鈕或者窗體設置顏色的方式是.setBackground(Color c)。

3、鉛筆、刷子、橡皮以及噴槍的實現

    現在,我們知道了如何畫一個圓,畫一條直線。在實現鉛筆等功能錢,我想先問個問題,如何去畫一個點?我有兩個想法,一個是,你可以通過畫實心圓的方式來畫一個點,給它半徑指定為一個像素,那么所畫出的實心圓就成了一個點。第二種,可以通過畫直線的方式,指定起始位置和釋放位置相同,那么畫出的也是一個點。

    接下來,我們要講講如何實現鉛筆的功能。這里需要介紹一個新的事件監聽方法,MouseMotionListener。在這個接口里,有一個鼠標拖動的監聽方法。我們可以用它來實現鉛筆的實現。它的工作機制是每隔一段時間,就獲取一次你鼠標所在的位置。當然,這個時間非常短。事實上,我們可以觀察在畫圖板上的直線。我們會發現每一條不規則曲線,都是由若干條直線構造而成的。那么,在這個拖動過程當中,我們可以在開始的地方記錄下它的xy坐標,然后每運行一次拖動獲取,就改變一次起始的xy坐標,那么,我們就實現了所謂的鉛筆繪圖功能。因為我們的事件處理類同時也繼承了MouseListener,在拖動進行的開始,事實上我們已經進行了一次點擊操作,所以,最開始的坐標我們不需要記錄。注意,因為是不同的監聽方法,所以一定要記得給畫板界面添加MouseMotionListener的監聽方法。鉛筆的具體代碼實現如下:

 

    實現了鉛筆,刷子其實也就那么回事,我們只需要將鉛筆實現這部分的代碼復制下來,並在之前添加一行給畫筆加粗的代碼即可,加粗了的鉛筆,不就是我們的刷子嗎?至於橡皮,我們也可以這么理解,只要找到與畫板界面底色相類似的顏色,給畫筆賦這樣的顏色,不就能覆蓋掉原有的部分了嗎?

    接下來是關於噴槍的實現。我們可以將噴槍理解成,在鉛筆的基礎上(去掉鉛筆所繪的軌跡),對於一個點,在一定范圍內,隨機畫若干個點。類似的變換,我們可以對一個點的xy坐標加減一定范圍內不等的值,畫出來的效果,就類似於噴槍效果了。生成隨機數的方法在Random這個類里面,所以我們首先需要實例化一個Random類,然后通過nextInt(int a)的方式去獲取一個0到a-1的隨機數。這樣,我們就能實現噴槍了。具體代碼如下:

4、重繪

    在這個實驗過程當中,我們很容易發現一個問題,當我們最小化或者說調整窗體大小的時候,我們所繪制的圖形消失了,然而按鈕還在。這是為什么呢?事實上,每當我們進行一次最小化或者調整窗體大小的時候,我們原先的那個窗體都被關閉了,接着計算機又重新繪制了一個全新的窗體。所以,我們自行繪制的圖形都沒有了。那么,為什么我們的按鈕還在?事實上,不僅僅是按鈕,swing包內其他我們熟悉的組件,賬號輸入框、密碼輸入框等元素,也還是存在。事實上,每一個元素、每一個窗體,它都有一個重繪方法。當窗體改變大小的時候,生成新窗體后,計算機會調用這個重繪方法,所以你看到按鈕等元素在改變界面后仍然在界面上。那么,如何讓我們自行繪制的圖形也像按鈕一樣,不會隨着改變窗體而消失呢?

    事實上,我們只需要重寫一下畫圖界面上的重繪方法。這也就是為什么我要繼承JFrame這個類的原因。因為繼承了JFrame,所以,我們可以重寫它繼承的paint方法,在其中加上我們所繪制的內容,那么在窗體重繪的過程當中,我們所繪制的內容也就重新繪制上去了。

    這只不過是重繪的第一步。因為我們繪制的內容有可能過於復雜,那么我們在主類里面如何去得知我們繪制了什么呢?我們可以定義一個shape類,然后在事件處理類里面定義一個shape類型的數組,每畫一個圖,那么,我們就用數組將它存儲下來,然后讓index++。為了簡化paint方法里的內容,我們可以定義一個shape抽象類,里面定義一個抽象方法draw,然后申明不同圖形,讓它們都繼承shape類,並且重寫draw方法。這樣,在paint方法里,我們就可以直接調用draw方法,而不用去寫各種判斷語句。這樣做簡化了我們的代碼。

代碼具體實現如下:

 

 

 

這里只給出shapeLine這個類的定義,關於其他類型的圖案的定義就沒有一一給出了,讓看客自行發散。

5、進行界面的美化

    假設我們把所有的按鈕都如此加上,那么,我們會發現,畫圖界面會非常的不美觀。為了增強界面的美觀程度,我們可以通過引進panel的方法。我們可以將畫基本圖形的按鈕放在一塊面板內,顏色按鈕放在一塊面板里,而鉛筆等功能又放到一塊面板里。同時為了區分每個界面,我們還可以在重繪方法里,編寫這樣的語句g.drawLine來給界面加上邊框。

    完成程序,具備想要的功能只是第一步。之后我們需要做的就是去盡量讓我們的界面美觀,並且,一些能進行縮減的代碼盡量縮減,使我們的代碼看起來更加的精簡干練。

 

三、總結

    一個畫板,說簡單也簡單,說復雜也復雜。以后我們打的程序肯定會越來越復雜,我們需要更加嚴謹,最好是加上一定的注釋(當然我個人寫代碼是不喜歡寫注釋的,可能也是因為寫的少的原因)。畫板談的比較粗糙,歡迎各位大神指正。

 

 

 

    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM