第一次寫博客 且是稍微大點(diǎn)的程序 看看就行
重新寫的在這,更加清晰明了: 用Java寫一個畫圖程序
- 設(shè)計(jì)思路
首先我直接去了Windows自帶畫圖程序去實(shí)踐模擬,看看具體方法,進(jìn)行了布局和按鈕的思考。
容器頂層放工具欄,工具欄中存放圖形按鈕、工具按鈕、顏色按鈕。對于圖形按鈕,存放在垂直的Box中,分成行列,設(shè)置邊框,設(shè)置標(biāo)簽,加入JToolbar;對于工具按鈕設(shè)置Jpanel保存,線條粗細(xì)設(shè)置垂直Box存儲,設(shè)置邊框后,最后將兩者加入水平Box中,與前面圖形按鈕設(shè)置間隔加入JToolbar中,設(shè)置標(biāo)簽;對于顏色按鈕,畫布背景顏色選擇按鈕單獨(dú)設(shè)置大按鈕,直接加入JToolbar,而顏色選擇按鈕我設(shè)置了JPanel,垂直Box進(jìn)行組裝,成行列,設(shè)置邊框,加入JToolbar中。最后的顏色選擇編輯按鈕,也是單獨(dú)大按鈕,加入JToolbar中。
最終效果如下:
這個程序,難在哪里?難在工具欄中按鈕監(jiān)聽。對于工具欄中各個按鈕,我要實(shí)時監(jiān)聽。但是對于工具欄中每一個按鈕我都進(jìn)行行為監(jiān)聽,適配器模式也招架不住程序的紊亂。于是寫一個類,繼承MouseAdapter、ActionListener,重寫部分監(jiān)聽方法。
對于行為監(jiān)聽、鼠標(biāo)抓取,進(jìn)行了一些操作,下面類的設(shè)計(jì)會詳細(xì)講解。在這個過程中我對所有圖形特征進(jìn)行了分析,順著這個我也創(chuàng)建了一個Shape類,類屬性包含了所有圖形的特征??墒枪ぞ邫诓粏螁斡袌D形構(gòu)畫,還有橡皮擦、顏色、粗細(xì),為此我對Shape里面的屬性做了調(diào)整,可以存儲當(dāng)前線條顏色、粗細(xì)。
對于菜單的設(shè)計(jì)較為簡單,因?yàn)闆]有太強(qiáng)邏輯可言,你想讓它如何展現(xiàn),展現(xiàn)什么內(nèi)容,就怎樣重寫監(jiān)聽方法。我設(shè)計(jì)了文件保存、打開以及畫圖的屬性、幫助、界面風(fēng)格。寫了一個MyMenu類,進(jìn)行相關(guān)設(shè)計(jì)組裝,下面也會具體講解。
圖畫刷新展示需要進(jìn)行repaint,我寫了MyFrame類繼承JFrame,重寫paint方法。在MyJFrame類中有參構(gòu)造的同時,我也進(jìn)行了畫圖的圖標(biāo)處理,這樣更加更美觀。
最終就是拼裝完成,設(shè)置界面,進(jìn)行顯示。
總結(jié):利用java中的現(xiàn)有類,創(chuàng)建主窗口、創(chuàng)建主窗口中內(nèi)容、設(shè)置事件響應(yīng)機(jī)制、顯示主窗口、進(jìn)入消息循環(huán)接收處理。
?
輸入java Painter conf/Painter-1.ini 展示圓、矩形
輸入java Painter conf/Painter-2.ini 展示圓、矩形、三角形、菱形、多邊形
其中功能按鈕、曲線、直線會一直展現(xiàn)。
- 類的設(shè)計(jì)
(一)
- MyMouseListener
繼承MouseAdapter適配器和MouseListner接口,進(jìn)行一些方法重寫。通過重寫actionPerformed,先行獲取按鈕內(nèi)容,設(shè)置屬性。
(1)曲線、橡皮擦、噴槍、毛筆
在mouseDragged方法中進(jìn)行行為監(jiān)聽。這個拖拽的過程是需要實(shí)時更新的,坐標(biāo)也需要實(shí)時更新。
<1>曲線:是由無數(shù)直線拼接而來,不斷創(chuàng)建shape,draw。這里我最開始也是用的實(shí)心圓,但是太曲折了,在網(wǎng)上資源也都是直線。
直線:
實(shí)心圓:
這里對比明顯直線更勝一籌。
<2>橡皮擦:我的思路是在鼠標(biāo)拖拽相應(yīng)位置同樣創(chuàng)建shape,而這些shape對象的顏色則為畫布初始顏色,draw,實(shí)現(xiàn)橡皮擦功能。
<3>噴槍、毛筆:都是范圍內(nèi)進(jìn)行噴畫,可以用循環(huán)畫無數(shù)條線的方式解決,并且這些直線是不連續(xù)的、隨機(jī)的??梢允褂肦andom循環(huán)一次次創(chuàng)建shape,draw。毛筆與噴槍不同的一點(diǎn)就是墨水會減少,需要記錄刷新,畫筆變細(xì),最后為空,當(dāng)再次pressed、released刷新“墨水”。
- 刷新、上一步
在actionPerformed中獲取按鈕內(nèi)容之后,根據(jù)if條件,對vector中的數(shù)據(jù)進(jìn)行更新。這里刷新之后,上一次vector數(shù)據(jù)要存起來,防止下次點(diǎn)擊上一步不展示任何內(nèi)容,利用兩個vector互相轉(zhuǎn)換,repaint。
- 直線、矩形、圓、三角形、菱形
重寫mousePressed和mouseReleased方法,獲取兩頂點(diǎn)坐標(biāo),算法得出左上角坐標(biāo)與右下角坐標(biāo)。
<1>直線、矩形、圓、橢圓
在庫中有相應(yīng)的draw方法,對于直線、矩形,在已知坐標(biāo)的情況,創(chuàng)建shape,draw;對于圓,我設(shè)置圓心為pressed點(diǎn),計(jì)算拖拽距離為r,創(chuàng)建shape,draw;對于橢圓,我則是借鑒Windows畫圖中的畫法,通過拖拽坐標(biāo)得寬高,創(chuàng)建shape,draw。
<2>三角形、菱形
三角形:直角三角形、等腰三角形,根據(jù)拖拽坐標(biāo),找尋第三個點(diǎn),創(chuàng)建三個type為直線的shape,draw三條線。
菱形:根據(jù)拖拽點(diǎn)計(jì)算四個點(diǎn)坐標(biāo),創(chuàng)建四個type為直線的type,draw四條直線。
- 多邊形
對于多邊形,獲取坐標(biāo),相鄰的點(diǎn)進(jìn)行聯(lián)接,創(chuàng)建多個type為直線的shape。并且存著首個坐標(biāo)點(diǎn),雙擊鼠標(biāo),可將圖形封閉為多邊形。
- 畫筆粗細(xì)、顏色編輯
畫筆粗細(xì):根據(jù)按鈕對象,創(chuàng)建stroke對象,在下次畫圖時傳入shape中。
畫布顏色:調(diào)用JColorChooser.showDialog進(jìn)行選擇,改變背景顏色,同時改變按鈕邊框顏色。
畫筆顏色:根據(jù)點(diǎn)擊的按鈕,設(shè)置畫筆相應(yīng)的顏色,存入color對象,傳入shape中。另外對點(diǎn)擊的圖形按鈕設(shè)置相應(yīng)的邊框顏色。
按鈕顏色編輯:自選顏色后可填入按鈕中,并且設(shè)置循環(huán),可反復(fù)覆蓋。
- Shape
這個類實(shí)現(xiàn)了每一個圖形的數(shù)據(jù)存儲,包含兩個坐標(biāo)點(diǎn),畫筆顏色,圖形類型,畫筆粗細(xì)。
對于直線、橢圓、圓、矩形,兩個坐標(biāo)即可畫出圖形。多邊形、三角形、噴槍、毛筆、橡皮擦,則是由若干條線段構(gòu)成的,只需創(chuàng)建多個類型為直線的shape對象。color,stroke對象記錄當(dāng)前畫筆顏色,畫筆粗細(xì)。
- MyFrame
繼承JFrame類,設(shè)置兩個vector,v和v1的目的 v和v2都有存儲圖形的功能 用于遍歷repaint。另外我可以當(dāng)刷新時,將v的所有數(shù)據(jù)送給v1?;赝藭r,我可以遍歷v1,避免空畫。
有參(title)構(gòu)造MyFrame,并且在其中進(jìn)行圖標(biāo)的設(shè)置。對paint方法進(jìn)行重寫,首先調(diào)用父類中的方法。其次將Graphics強(qiáng)制轉(zhuǎn)換為Graphics2D,為了實(shí)現(xiàn)畫筆粗細(xì)。在遍歷過程中對shape中stroke,color進(jìn)行獲取,根據(jù)type畫圖。
其中直線、曲線、三角形、多邊形的type都是直線,drawLine即可;圓、橢圓、矩形,則根據(jù)shape中兩個坐標(biāo)獲取左上角坐標(biāo),計(jì)算大小,調(diào)用draw或fill方法。
最后若存在image,則drawImage,打開文件照片之后畫布可以顯示圖片信息。
- MyMenu
構(gòu)建菜單,設(shè)置菜單條,創(chuàng)建MyMouseListener對象。在類中構(gòu)造方法,創(chuàng)建菜單條。
文件菜單下創(chuàng)建打開、保存、屬性、幫助等menuItem,并且過程中直接設(shè)置行為監(jiān)聽。
其中文件打開,JFileChooser默認(rèn)為當(dāng)前目錄,選取文件進(jìn)行獲取,repaint圖片到畫布;文件保存,可在一定的區(qū)間范圍內(nèi),畫布保存為圖片,默認(rèn)保存路徑為當(dāng)前目錄,獲取選擇文件路徑,圖片格式為jpg,如果保存了,則設(shè)置flag為真,關(guān)閉程序不會彈出窗口。
屬性和幫助則是彈出窗口顯示相關(guān)說明性信息。
格式菜單下設(shè)置了幾種風(fēng)格,可以進(jìn)行選擇刷新組件外觀,更換界面主題,并且repaint,將圖畫信息轉(zhuǎn)移到當(dāng)前畫布。
最后所有菜單裝入菜單條,組裝至容器中。
- MyJToolbar
繼承JToolbar類。創(chuàng)建一個初始化方法,對于按鈕則可以設(shè)計(jì)for循環(huán),進(jìn)行創(chuàng)建加入圖片,監(jiān)聽,裝入工具欄;對于線條粗細(xì)的按鈕,設(shè)置了一個垂直的Box拼裝,監(jiān)聽,裝入工具欄;對于顏色按鈕,則僅僅設(shè)置顏色,監(jiān)聽,裝入工具欄。
最后將工具欄裝入JFrame的頂部。
- Main
創(chuàng)建上述幾個類的對象,調(diào)用各類初始化方法,組裝,展示。
(二)
類之間的聯(lián)系
???? 我并沒有采用復(fù)雜的繼承關(guān)系和設(shè)置抽象的類與接 口,只是繼承了java中的一些原有的類和接口,便于 更好地實(shí)現(xiàn)自己寫的一些類以及繼承相應(yīng)的父類不可 少的方法。其次對于自己寫的幾個類,我的耦合度可 能高一點(diǎn),不太好可能,可能也不是,因?yàn)楦黝愔卸?有創(chuàng)建其他類的對象解決一些問題,各類中有創(chuàng)建相 應(yīng)變量進(jìn)行關(guān)聯(lián),改變窗口界面。
簡單地繼承:
類之間的一些聯(lián)系:
?代碼實(shí)現(xiàn)
1.Painter 主函數(shù)
package com.zzu;
import javax.swing.*;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
//框架:最上層Menu --->文件保存 導(dǎo)入 界面刷新(清除功能) 風(fēng)格更換
// Menu下面放工具欄 繪制各種圖形 顏色 線條粗細(xì) 橡皮擦 字體模式大小
// 關(guān)閉界面可以彈出警告窗口 設(shè)置監(jiān)聽器是否保存
// 畫布 默認(rèn)CENTER
//Content:
// 一個shape類存儲Point color type
// 矩形: press、release為兩側(cè)頂點(diǎn)坐標(biāo) 通過計(jì)算可得左上角右下角坐標(biāo)及長寬 drawRect(Math.min(x1,x2), Math.min(y1,y2), Math.abs(x2-x1),Math.abs(y2-y1));
// 直線: Mouse press release drawLine
// 圓: Mouse press release drawOval
// 菱形: Mouse press release drawLine
// 噴槍: random 的實(shí)心圓 或 坐標(biāo)點(diǎn) fillOval
// 曲線: 這就需要MouseDrag監(jiān)聽不斷更新起點(diǎn)和終點(diǎn) Point1->Point2 Point2->新Point 無限小直線 drawLine
// 多邊形:release clicked drawLine
// 橡皮擦:區(qū)域內(nèi)添加新圖形 顏色為畫布顏色 橡皮擦大小也跟畫筆粗細(xì)相關(guān)聯(lián)
// 回退:返回上一步
// 刷新:畫布刪除所有圖形
// 粗細(xì): Graphics2D Stroke
// 畫布背景顏色: JColorChooser
public class Painter {
//創(chuàng)建窗口對象
MyFrame jf = new MyFrame("畫圖");
//創(chuàng)建畫圖內(nèi)容監(jiān)聽對象
MyMouseListener myMouseListener = new MyMouseListener();
//彈出文件窗口放在JPanel 防止保存圖片時出現(xiàn)問題
JPanel jPanel = new JPanel();
//創(chuàng)建菜單對象
MyMenu myMenu = new MyMenu(jf,jPanel);
//創(chuàng)建工具欄對象
MyJToolbar myJToolbar = new MyJToolbar(jf,myMouseListener);
//空參構(gòu)造
public Painter(){
}
/**
* @param file
* @return ArrayList 文件內(nèi)容以若干個字符串傳出
* @throws IOException
*/
public static ArrayList<String> getFileContent(String file) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(file));
//這里ArrayList是為了存儲不確定個數(shù)的String
ArrayList<String> content = new ArrayList<>();
//獲取文件中字符串
String line = "";
try{
while((line=reader.readLine())!=null){
//首個屬性值
if(line.contains("[")) {
continue;
}
String str[] = line.split("=");//分割出內(nèi)容
if(str.length>1) line = str[1];
else line = str[0];
line = line.trim();//去除首尾空格
String str1[] = line.split(",");//逗號分隔開若干個
//遍歷加入list
for (String s : str1) {
content.add(s);
}
}
return content;
}finally{//始終保持文件最終關(guān)閉
reader.close();
}
}
/**
* 展示界面
* @throws Exception
*/
public void showUI() throws Exception {
//讀取圖形數(shù)據(jù)
Scanner sc = new Scanner(System.in);
String file = sc.next();
ArrayList<String> list = getFileContent(file);
myJToolbar.setList(list);
//JFrame設(shè)置監(jiān)聽 可以任意畫曲線
//添加鼠標(biāo)監(jiān)聽器
jf.addMouseListener(myMouseListener);
jf.addMouseMotionListener(myMouseListener);
//將JFrame傳過去 實(shí)現(xiàn)repaint
myMouseListener.setMyFrame(jf);
//初始化菜單加入到JFrame中
myMenu.init();
//初始化工具欄加入JFrame中
myJToolbar.init();
//設(shè)置界面大小
jf.setSize(1100,800);
//居中顯示
jf.setLocationRelativeTo(null);
//設(shè)置可見
jf.setVisible(true);
//關(guān)閉進(jìn)程
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) throws Exception {
new Painter().showUI();
}
}
2.MyMenu 菜單類
package com.zzu;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
public class MyMenu {
private MyFrame jf;
private JPanel jPanel;
//菜單項(xiàng)組件
//菜單條
public JMenuBar jMenuBar = new JMenuBar();
//兩個菜單
public JMenu fileMenu = new JMenu("文件");
public JMenu styleMenu = new JMenu("界面風(fēng)格");
//確定文件是否被保存
public boolean flag = false;
//獲取畫布圖片信息或者獲取文件中圖片信息
public BufferedImage image;
public MyMenu() {
}
public MyMenu(MyFrame jf, JPanel jPanel) {
this.jf = jf;
this.jPanel = jPanel;
}
/**
* 組裝菜單
* @throws Exception
*/
public void init() throws Exception {
//fileMenu下的條目菜單 對應(yīng)設(shè)置行為監(jiān)聽
//圖片打開
JMenuItem open = new JMenuItem(new AbstractAction("打開",new ImageIcon("打開.png")) {
@Override
public void actionPerformed(ActionEvent e) {
//顯示一個文件選擇器 當(dāng)前目錄
JFileChooser fileChooser = new JFileChooser(".");
fileChooser.showOpenDialog(jPanel);
//獲取選擇的文件
File file = fileChooser.getSelectedFile();
//如果選擇了文件 就進(jìn)行相關(guān)操作
if(file != null){
//進(jìn)行顯示
try {
image = ImageIO.read(file);
//將信息傳進(jìn)MyFrame中
jf.setImage(image);
jf.setIg(true);
jf.repaint();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
});
//圖片保存
JMenuItem save = new JMenuItem(new AbstractAction("保存",new ImageIcon("保存.png")) {
@Override
public void actionPerformed(ActionEvent e) {
//顯示一個文件選擇器 當(dāng)前目錄
JFileChooser fileChooser = new JFileChooser(".");
fileChooser.showSaveDialog(jPanel);
//獲取用戶選擇的保存文件路徑
File file = fileChooser.getSelectedFile();
//如果只是打開目錄沒有保存 則不進(jìn)行下面操作
if(file!=null){
//保存
try {
try {
//畫布保存為圖片 設(shè)置區(qū)域范圍大小
image = new Robot().createScreenCapture(new Rectangle(jf.getX(),jf.getY()+250, jf.getWidth(),jf.getHeight()-250));
} catch (AWTException ex) {
throw new RuntimeException(ex);
}
ImageIO.write(image,"jpg",file);//存入文件
flag = true;//保存成功
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
});
//關(guān)于畫圖
JMenuItem attribute = new JMenuItem(new AbstractAction("關(guān)于畫圖",new ImageIcon("關(guān)于畫圖.png")) {
//展示特性
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(jf,null,"關(guān)于畫圖",JOptionPane.DEFAULT_OPTION,new ImageIcon("屬性.png"));
}
});
//幫助
JMenuItem help = new JMenuItem(new AbstractAction("幫助",new ImageIcon("幫助.png")) {
//展示內(nèi)容
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "" + "******************\n" + "#畫圖軟件使用說明書#\r\n"
+ "******************\n"
+ "1.本軟件主要分為四個模塊:菜單、工具欄、調(diào)色板、和畫布\n"
+ "(1)菜單欄的文件子菜單包括打開、保存圖片以及幫助,關(guān)于我們\r\n"
+ "(2)工具主要包括清空畫板、撤回操作、圖形繪制\n"
+ "(3)調(diào)色板位于界面的頂側(cè)工具欄,用于改變畫布背景顏色或設(shè)置畫筆的顏色\n"
+ "(4)畫布用于圖形繪制,使用鼠標(biāo)選中要繪制的圖形即可進(jìn)行繪制\n"
+"2.具體操作:\n"
+"(1)可在畫布繪制任意曲線\n"
+"(2)矩形、三角形、菱形、箭頭:鼠標(biāo)拖拽 獲得兩頂點(diǎn)系統(tǒng)會算法確定位置大小\r\n"
+"(3)圓:鼠標(biāo)拖拽 press點(diǎn)和release點(diǎn)分別為圓心和圓上一點(diǎn)\n"
+"(4)多邊形:相鄰的兩點(diǎn)連接,雙擊則可形成封閉圖形\n"
+"(5)橡皮擦、噴槍 鼠標(biāo)點(diǎn)擊拖拽即可\n"
+"(6)畫筆粗細(xì)選擇\n"
+"(7)背景顏色、畫筆顏色可自動選擇 選擇之后點(diǎn)擊按鈕 按鈕邊框也會變色\n"
+"(8)最后的編輯顏色可以配色進(jìn)行選擇\n", "使用說明", JOptionPane.PLAIN_MESSAGE);
}
});
//styleMenu風(fēng)格單選
ButtonGroup buttonGroup = new ButtonGroup();
JRadioButtonMenuItem metalItem = new JRadioButtonMenuItem("Metal 風(fēng)格");
JRadioButtonMenuItem windowsItem = new JRadioButtonMenuItem("Windows 風(fēng)格",true);//默認(rèn)
JRadioButtonMenuItem windowsClassicItem = new JRadioButtonMenuItem("Windows 經(jīng)典風(fēng)格");
JRadioButtonMenuItem motifItem = new JRadioButtonMenuItem("Motif 風(fēng)格");
//風(fēng)格選擇監(jiān)聽 避免多次重寫
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
//獲得內(nèi)容 傳送設(shè)置風(fēng)格
changeFlavor(e.getActionCommand());
//風(fēng)格改變后需要重畫
jf.repaint();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
};
//退出若未保存則彈出提示窗口
jf.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
if (!flag) {
// 彈出對話框 提示未保存
JOptionPane.showOptionDialog(jf,"你還沒保存,確定要退出嗎?","BBQ",JOptionPane.DEFAULT_OPTION
,JOptionPane.WARNING_MESSAGE,null,new String[]{"確定","非常確定"},"確定");
}
}
});
//組裝風(fēng)格菜單
buttonGroup.add(metalItem);
buttonGroup.add(windowsItem);
buttonGroup.add(windowsClassicItem);
buttonGroup.add(motifItem);
//添加監(jiān)聽器
metalItem.addActionListener(listener);
windowsItem.addActionListener(listener);
windowsClassicItem.addActionListener(listener);
motifItem.addActionListener(listener);
//加入styleMenu
styleMenu.add(metalItem);
styleMenu.add(windowsItem);
styleMenu.add(windowsClassicItem);
styleMenu.add(motifItem);
//文件以及幫助菜單
fileMenu.add(open);
fileMenu.add(save);
fileMenu.add(attribute);
fileMenu.add(help);
//菜單欄
jMenuBar.add(fileMenu);
jMenuBar.add(styleMenu);
//將組裝好的菜單欄裝入JFrame中
jf.setJMenuBar(jMenuBar);
}
/**
*
* @param command
* @throws Exception
* 此方法用于改變界面風(fēng)格
*/
public void changeFlavor(String command) throws Exception {
switch (command) {
case "Metal 風(fēng)格":
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
break;
case "Windows 風(fēng)格":
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
break;
case "Windows 經(jīng)典風(fēng)格":
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel");
break;
case "Motif 風(fēng)格":
UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
break;
}
//刷新組件的外觀
SwingUtilities.updateComponentTreeUI(jf.getContentPane());
SwingUtilities.updateComponentTreeUI(jMenuBar);
}
public MyFrame getJf() {
return jf;
}
public void setJf(MyFrame jf) {
this.jf = jf;
}
public JPanel getjPanel() {
return jPanel;
}
public void setjPanel(JPanel jPanel) {
this.jPanel = jPanel;
}
}
3.MyJToolbar?工具欄類
package com.zzu;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class MyJToolbar extends JToolBar{
static int num = 12;//當(dāng)前第幾個顏色選擇框
private MyFrame jf;
private MyMouseListener myMouseListener;
private ArrayList<String> list;
public MyJToolbar() {
}
public MyJToolbar(MyFrame jf, MyMouseListener myMouseListener) {
//聲明工具條相關(guān)內(nèi)容
super("工具欄",SwingConstants.HORIZONTAL);
this.setBackground(new Color(0xCFFCE6));
this.jf = jf;
this.myMouseListener = myMouseListener;
}
//TODO 工具條拖動畫布內(nèi)容消失問題
@Override
public void setFloatable(boolean b) {
super.setFloatable(b);
if(b) jf.repaint();
}
/**
* 組裝工具欄
*/
public void init(){
//組裝工具欄
//工具欄內(nèi)容從最左側(cè)開始填充
this.setLayout(new FlowLayout(FlowLayout.LEFT));
for (int i = 0; i < 3; i++) {
//設(shè)置間隔 美觀清晰
this.addSeparator();
}
//第一行的這些圖形功能是剛需的 不需要判斷
//第二行的需要根據(jù)文件讀取圖形數(shù)據(jù)判斷是否加入
String[] image1 = {"直線.png", "曲線.png","空心矩形.png", "實(shí)心矩形.png", "空心圓.png","實(shí)心圓.png","空心橢圓.png","實(shí)心橢圓.png",
"直角三角形.png","等腰三角形.png","菱形.png", "多邊形.png"};
Box vBox = Box.createVerticalBox();
JLabel jLabel1 = new JLabel("圖形選擇");
JPanel jPanel1 = new JPanel();
JPanel jPanel2 = new JPanel();
//遍歷組裝圖形功能按鈕
for (int i = 0; i < image1.length; i++) {
boolean contain = false;
if(i<2) contain = true;//前幾個圖形不需要判定是否存在在文件中
else {//文件中是否存在后面圖形
for(String s:list){
if(image1[i].contains(s)) {
contain = true;
break;
}
}
}
if(contain){
//JButton圖片內(nèi)容
JButton jbt = new JButton();
ImageIcon icon = new ImageIcon(image1[i]);//實(shí)例化ImageIcon對象
icon.setImage(icon.getImage().getScaledInstance(30,30,Image.SCALE_DEFAULT));//設(shè)置圖片大小與JButton大小匹配
jbt.setIcon(icon);//加入JButton中
//按鈕大小
jbt.setPreferredSize(new Dimension(35,35));
//設(shè)置監(jiān)聽器
jbt.addActionListener(myMouseListener);
//默認(rèn)邊框藍(lán)色
jbt.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
if(i<6) jPanel1.add(jbt);
else jPanel2.add(jbt);
}
}
vBox.add(jPanel1);
vBox.add(jPanel2);
vBox.add(jLabel1);
//vBox.setSize(210,80);
vBox.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED, Color.RED, Color.GREEN));
this.add(vBox);
for (int i = 0; i < 3; i++) {
//設(shè)置間隔 美觀清晰
this.addSeparator();
}
//工具按鈕
//水平Box存取工具 線條
Box hBox = Box.createHorizontalBox();
//設(shè)置邊框
hBox.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED, Color.RED, Color.GREEN));
//存取按鈕
JPanel jPanel3 = new JPanel();
JLabel jLabel2 = new JLabel("工具");
String[] image2 = {"噴槍.png","毛筆.png", "橡皮擦.png","上一步.png","刷新.png"};
//遍歷組裝圖形功能按鈕
for (int i = 0; i < image2.length; i++) {
//JButton圖片內(nèi)容
JButton jbt = new JButton();
ImageIcon icon = new ImageIcon(image2[i]);//實(shí)例化ImageIcon對象
icon.setImage(icon.getImage().getScaledInstance(35,35,Image.SCALE_DEFAULT));//設(shè)置圖片大小與JButton大小匹配
jbt.setIcon(icon);//加入JButton中
//按鈕大小
jbt.setPreferredSize(new Dimension(40,40));
//設(shè)置監(jiān)聽器
jbt.addActionListener(myMouseListener);
//默認(rèn)邊框藍(lán)色
jbt.setBorder(BorderFactory.createLineBorder(Color.CYAN, 2));
jPanel3.add(jbt);
}
//Vbox用來處置組裝線條粗細(xì)按鈕
Box vBox2 = Box.createVerticalBox();
//線條粗細(xì)
String[] stroke = {"stroke1.png","stroke2.png","stroke3.png","stroke4.png"};
//遍歷設(shè)置監(jiān)聽和屬性
for(int i = 0;i<stroke.length;i++){
//JButton粗細(xì)內(nèi)容
JButton jbt = new JButton();
//實(shí)例化對象
ImageIcon icon = new ImageIcon(stroke[i]);
//設(shè)置圖片大小與JButton大小匹配 加入按鈕
icon.setImage(icon.getImage().getScaledInstance(50,20,Image.SCALE_DEFAULT));
jbt.setIcon(icon);
//按鈕大小
jbt.setPreferredSize(new Dimension(50,20));
//監(jiān)聽
jbt.addActionListener(myMouseListener);
vBox2.add(jbt);
}
vBox2.add(jLabel2);
//hBox.setSize(210,80);
hBox.add(jPanel3);
hBox.add(vBox2);
//加入工具條
this.add(hBox);
for (int i = 0; i < 3; i++) {
//設(shè)置間隔 美觀清晰
this.addSeparator();
}
//設(shè)置背景顏色選擇按鈕
JButton colorBack = new JButton(new ImageIcon("顏色.png"));
colorBack.setBorder(BorderFactory.createLineBorder(Color.CYAN, 3));
//設(shè)置監(jiān)聽
colorBack.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//彈出顏色選擇器
Color color = JColorChooser.showDialog(jf,"背景顏色選擇器",Color.PINK);
colorBack.setBorder(BorderFactory.createLineBorder(color, 3));
//修改背景顏色 同時需要重畫
jf.getContentPane().setBackground(color);
jf.repaint();
}
});
this.add(colorBack);
//三行顏色選擇按鈕
Box vBox3 = Box.createVerticalBox();
//vBox3.setSize(new Dimension(150,75));
//三個JPanel分別裝一行顏色按鈕
JPanel jPanel6 = new JPanel();
JPanel jPanel7 = new JPanel();
JPanel jPanel8 = new JPanel();
//創(chuàng)建畫筆顏色按鈕
Color[] color = {Color.WHITE,Color.BLACK,Color.CYAN,Color.BLUE,Color.PINK,Color.RED,
Color.ORANGE,Color.MAGENTA,Color.GREEN,Color.GRAY,Color.DARK_GRAY,Color.LIGHT_GRAY,
Color.WHITE,Color.WHITE,Color.WHITE,Color.WHITE,Color.WHITE,Color.WHITE};
//設(shè)置n個按鈕 這樣實(shí)例化為了后面改變顏色選擇按鈕顏色
JButton jbt[] = new JButton[color.length];
//遍歷組裝按鈕
for (int i = 0; i < color.length; i++) {
jbt[i] = new JButton(new ImageIcon(""));
//按鈕大小
jbt[i].setPreferredSize(new Dimension(25,25));
//按鈕添加相應(yīng)背景色
jbt[i].setBackground(color[i]);
//監(jiān)聽點(diǎn)擊的背景色
jbt[i].addActionListener(myMouseListener);
if(i<6) jPanel6.add(jbt[i]);
else if(i<12) jPanel7.add(jbt[i]);
else jPanel8.add(jbt[i]);
}
//將三個JPanel加入vBOX中
vBox3.add(jPanel6);
vBox3.add(jPanel7);
vBox3.add(jPanel8);
//設(shè)置邊框以及一些邊框?qū)傩? vBox3.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.RED, Color.GREEN, Color.BLUE, Color.GRAY));
//加入工具條
this.add(vBox3);
//設(shè)置背景顏色選擇按鈕
JButton colorEdit = new JButton(new ImageIcon("編輯顏色.png"));
colorEdit.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED, Color.RED, Color.GREEN));
//設(shè)置監(jiān)聽
colorEdit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//彈出顏色選擇器
Color color = JColorChooser.showDialog(jf,"按鈕顏色編輯器",Color.PINK);
//修改最后一行按鈕顏色
if(num==18){//都已經(jīng)修改過 從頭開始
num = 12;
jbt[num++].setBackground(color);
}
else jbt[num++].setBackground(color);
}
});
//加入工具條
this.add(colorEdit);
//TODO 界面為什么會為空 在哪repaint解決
//讓工具條可以拖動
//this.setFloatable(true);
//讓工具條不可以拖動
this.setFloatable(false);
//工具欄居上
jf.add(this,BorderLayout.NORTH);
}
public MyFrame getJf() {
return jf;
}
public void setJf(MyFrame jf) {
this.jf = jf;
}
public MyMouseListener getMyMouseListener() {
return myMouseListener;
}
public void setMyMouseListener(MyMouseListener myMouseListener) {
this.myMouseListener = myMouseListener;
}
public ArrayList<String> getList() {
return list;
}
public void setList(ArrayList<String> list) {
this.list = list;
}
}
4.MyMouseListener?監(jiān)聽器類
package com.zzu;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
class MyMouseListener extends MouseAdapter implements ActionListener {
//記錄當(dāng)前所選顏色 默認(rèn)為藍(lán)色
public Color color = Color.BLACK;
//Point1 Point2
public int x1=0,y1=0,x2=0,y2=0;
//ployX,ployY是多邊形的第一個點(diǎn)
public int ployX,ployY, ployX1, ployY1;
//按鈕名稱 默認(rèn)為null 可直接畫曲線
public String ActionCommand="";
//判斷多邊形第一條邊是否畫出
public boolean first;
//毛筆模擬計(jì)時器 控制“墨汁”
public int time,t;
// //鼠標(biāo)是否是靜態(tài)
// public int status;
//毛筆是否已經(jīng)完成上一次畫線 默認(rèn)為真
boolean last = true;
//數(shù)據(jù)存儲
public Vector<Shape> v = new Vector<>();
//最多有四個shape(菱形四條邊)
public Shape s=null;
public Shape s1=null;
public Shape s2=null;
public Shape s3=null;
//字體粗細(xì)
public Stroke stroke = new BasicStroke(1);//默認(rèn)粗細(xì)為1
//獲得容器
private MyFrame myFrame;
//實(shí)時畫圖
private Graphics2D g;
public MyMouseListener() {
}
public MyMouseListener(MyFrame myFrame, Graphics2D g) {
this.myFrame = myFrame;
this.g = g;
}
@Override
public void actionPerformed(ActionEvent e) {
g = (Graphics2D) myFrame.getGraphics();
g.setXORMode(myFrame.getBackground());
//獲取圖片名字
JButton jButton = (JButton)e.getSource();
String command = jButton.getIcon().toString();
//此處防止上次的點(diǎn)干擾此次作圖
x1=x2;
y1=y2;
if(command.equals("")){
//提取顏色
color = jButton.getBackground();
}
else if(command.equals("刷新.png")){
//這里寫if可以保證多次刷新數(shù)據(jù)也不會丟失
if(v.size()>0){
//保留刷新前的點(diǎn) 避免回退什么也不打印
Vector<Shape> v1 = new Vector<>(v);
myFrame.setV1(v1);
}
//刪除所有點(diǎn)
v.removeAllElements();
//這里將back重置為false 不然會出現(xiàn)bug
myFrame.setBack(false);
myFrame.setV(v);
myFrame.repaint();
}
else if (command.equals("上一步.png")) {
int size = v.size();
//有圖形則刪 無則不管
if(size>0){
v.remove(v.size()-1);
myFrame.setV(v);
myFrame.repaint();
}
else if(myFrame.getV1().size()>0){
myFrame.setBack(true);
myFrame.repaint();
}
}//字體粗細(xì) 并設(shè)置當(dāng)前畫筆粗細(xì)
else if(command.equals("stroke1.png")){
stroke = new BasicStroke(1);
g.setStroke(stroke);
}
else if(command.equals("stroke2.png")){
stroke = new BasicStroke(2);
g.setStroke(stroke);
}
else if(command.equals("stroke3.png")){
stroke = new BasicStroke(4);
g.setStroke(stroke);
}
else if(command.equals("stroke4.png")){
stroke = new BasicStroke(7);
g.setStroke(stroke);
}
else{//橡皮擦就不要設(shè)置邊框了
if(!command.equals("橡皮擦.png")){
JButton jbt = (JButton) e.getSource();
//設(shè)置邊框顏色 提醒畫筆顏色
//將所選按鈕框改變?yōu)楫?dāng)前已選顏色
jbt.setBorder(BorderFactory.createLineBorder(color, 2));
jbt.setBackground(color);
}
//畫筆顏色
g.setColor(color);
//獲取圖形
ActionCommand=command;
if(ActionCommand.equals("多邊形.png")){
//第一條邊未畫
first = false;
}
else if(ActionCommand.equals("毛筆.png")) {
//計(jì)時器0
time = 0;
}
}
}
//得到按壓起點(diǎn)坐標(biāo)
@Override
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
}
//得到釋放終點(diǎn)坐標(biāo)
@Override
public void mouseReleased(MouseEvent e) {
ployX1 = x2;
ployY1 = y2;
x2 = e.getX();
y2 = e.getY();
//如果released 那么毛筆墨汁刷新
//計(jì)時器都刷新
t=time=0;
last = true;
if(ActionCommand.equals("直角三角形.png")){
Shape s = new Shape(x1,y1,x2,y2,color,"直線",stroke);
v.addElement(s);
g.drawLine(x1,y1,x2,y2);
Shape s1 = new Shape(Math.min(x1,x2),Math.max(y1,y2),x1,y1,color,"直線",stroke);
v.addElement(s1);
g.drawLine(Math.min(x1,x2),Math.max(y1,y2),x1,y1);
Shape s2 = new Shape(Math.min(x1,x2),Math.max(y1,y2),x2,y2,color,"直線",stroke);
v.addElement(s2);
g.drawLine(Math.min(x1,x2),Math.max(y1,y2),x2,y2);
}
else if(ActionCommand.equals("等腰三角形.png")){
Shape s = new Shape(x1,y1,x2,y2,color,"直線",stroke);
v.addElement(s);
g.drawLine(x1,y1,x2,y2);
Shape s1 = new Shape(2*x1-x2,y2,x1,y1,color,"直線",stroke);
v.addElement(s1);
g.drawLine(2*x1-x2,y2,x1,y1);
Shape s2 = new Shape(2*x1-x2,y2,x2,y2,color,"直線",stroke);
v.addElement(s2);
g.drawLine(2*x1-x2,y2,x2,y2);
}
else if(ActionCommand.equals("菱形.png")){
int x3 = (x1+x2)/2;
int y3 = (y1+y2)/2;
Shape s = new Shape(x1,y3,x3,y1,color,"直線",stroke);
v.addElement(s);
g.drawLine(x1,y3,x3,y1);
Shape s1 = new Shape(x1,y3,x3,y2,color,"直線",stroke);
v.addElement(s1);
g.drawLine(x1,y3,x3,y2);
Shape s2 = new Shape(x2,y3,x3,y1,color,"直線",stroke);
v.addElement(s2);
g.drawLine(x2,y3,x3,y1);
Shape s3 = new Shape(x2,y3,x3,y2,color,"直線",stroke);
v.addElement(s3);
g.drawLine(x2,y3,x3,y2);
}
else if(ActionCommand.equals("空心矩形.png")){
Shape s=new Shape(x1, y1, x2, y2,color,"空心矩形",stroke);
v.addElement(s);
g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
else if(ActionCommand.equals("實(shí)心矩形.png")){
Shape s=new Shape(x1, y1, x2, y2,color,"實(shí)心矩形",stroke);
v.addElement(s);
g.fillRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
else if(ActionCommand.equals("空心圓.png")){
int r = (int)Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));//半徑
Shape s=new Shape(x1, y1, r, r,color,"空心圓",stroke);
v.addElement(s);
g.drawOval(x1,y1,r,r);
}
else if(ActionCommand.equals("實(shí)心圓.png")){
int r = (int)Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));//半徑
Shape s=new Shape(x1, y1, r, r,color,"實(shí)心圓",stroke);
v.addElement(s);
g.fillOval(x1,y1,r,r);
}
else if(ActionCommand.equals("空心橢圓.png")){
Shape s=new Shape(x1, y1, x2, y2,color,"空心橢圓",stroke);
v.addElement(s);
g.drawOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
else if(ActionCommand.equals("實(shí)心橢圓.png")){
Shape s=new Shape(x1, y1, x2, y2,color,"實(shí)心橢圓",stroke);
v.addElement(s);
g.fillOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
else if(ActionCommand.equals("直線.png")) {
Shape s=new Shape(x1, y1, x2, y2,color,"直線",stroke);
v.addElement(s);
g.drawLine(x1,y1,x2,y2);
}
else if(ActionCommand.equals("多邊形.png")&&!first){
//存起始點(diǎn)
ployX=x1;
ployY=y1;
Shape s=new Shape(x1, y1, x2, y2,color,"直線",stroke);
v.addElement(s);
//畫多邊形的第一條邊
g.drawLine(x1,y1,x2,y2);
first =true;
}
else if(ActionCommand.equals("多邊形.png")){
//雙擊形成封閉圖形
if(e.getClickCount()==2){
Shape s=new Shape(x2, y2,ployX,ployY,color,"直線",stroke);
v.addElement(s);
//首尾點(diǎn)相連
g.drawLine(x2, y2,ployX,ployY);
first =false;
}//否則繼續(xù)循序連接
else {
Shape s=new Shape(x1, y1, ployX1, ployY1,color,"直線",stroke);
v.addElement(s);
g.drawLine(x1, y1, ployX1, ployY1);
}
}
myFrame.setV(v);
}
//監(jiān)視曲線 畫布 橡皮擦 噴槍
//這里都是Point1->Point2 Point2更新 若干個Shape
@Override
public void mouseDragged(MouseEvent e) {
g = (Graphics2D) myFrame.getGraphics();
g.setColor(color);//畫筆顏色
g.setStroke(stroke);//畫筆粗細(xì)
ployX1 = x2;
ployY1 = y2;
x2 = e.getX();
y2 = e.getY();
if( ActionCommand.equals("曲線.png")||ActionCommand.equals("")){
//添加若干條直線
s=new Shape(x1, y1,x2, y2,color,"直線",stroke);
v.addElement(s);
g.drawLine(x1,y1,x2,y2);
x1=x2;
y1=y2;
}
else if( ActionCommand.equals("橡皮擦.png")){
//區(qū)域添加背景色的圖形
s=new Shape(x1, y1,x2, y2,UIManager.getColor("control"),"實(shí)心圓",stroke);
g.setColor(UIManager.getColor("control"));
v.addElement(s);
g.drawLine(x1,y1,x2,y2);
x1=x2;
y1=y2;
}
else if( ActionCommand.equals("噴槍.png")){
//隨機(jī)在區(qū)域內(nèi)畫線
Random r=new Random();
//遍歷隨機(jī)畫線
for(int i=0;i<30;i++){
int a=r.nextInt(20);
int b=r.nextInt(20);
s=new Shape(x1+a, y1+b,x2+a, y2+b,color,"直線",stroke);
v.addElement(s);
g.drawLine(x1+a,y1+b,x2+a,y2+b);
x1=x2;
y1=y2;
}
}
else if( ActionCommand.equals("毛筆.png")){
//隨機(jī)在區(qū)域內(nèi)畫線
Random r=new Random();
for(int i=0;i<60;i++){
if(t<=15&&last){
int a=r.nextInt(20-t);//ab就當(dāng)成墨汁了
int b=r.nextInt(20-t);
s=new Shape(x1+a, y1+b,x2+a, y2+b,color,"直線",stroke);
v.addElement(s);
g.drawLine(x1+a,y1+b,x2+a,y2+b);
x1=x2;
y1=y2;
time++;//計(jì)時器++
}else; //啥也不畫 沒墨汁了 再次press重畫獲得墨汁
}
//刷新t 墨汁變少
t = time/1000;
}
myFrame.setV(v);
}
public MyFrame getMyFrame() {
return myFrame;
}
public void setMyFrame(MyFrame myFrame) {
this.myFrame = myFrame;
}
public Graphics2D getG() {
return g;
}
public void setG(Graphics2D g) {
this.g = g;
}
}
5.MyFrame?類
package com.zzu;
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class MyFrame extends JFrame {
//所有數(shù)據(jù)存放至此 進(jìn)行repaint
private Vector<Shape> v = new Vector<>(); //設(shè)置v和v1的目的 v和v1都有存儲圖形的功能 用于遍歷repaint
private Vector<Shape> v1 = new Vector<>(); //另外我可以當(dāng)刷新時 將v的所有數(shù)據(jù)送給v1 回退時 我可以遍歷v1 不然會什么也不畫
private boolean back = false; //是否滿足回退且v1不為空的條件
private Image image;//文件中圖片
private boolean ig;//保證圖片也能被刪除
public MyFrame(){
}
public MyFrame(String title){
//窗體名稱
super(title);
this.getContentPane().setBackground(new Color(204,255,204));
//TODO 設(shè)置窗體圖標(biāo)
try {
ImageIcon icon = new ImageIcon("畫圖.png");
Image image = icon.getImage();
this.setIconImage(image);
} catch (Exception e) {//跳出對話框提示
JOptionPane.showMessageDialog(null, "圖標(biāo)異常");
}
}
/**
*
* @param g the specified Graphics window
* 重寫repaint方法
*/
@Override
public void paint(Graphics g) {
//父類中的方法
super.paint(g);
//如果此時v1中有Shape 則說明已經(jīng)刷新了
//判斷是否回退 回退則將這倆換一下 并且判定是否有圖片回退打印
if(v1.size()>0) {
ig = false;
if(back){
v.addAll(v1);
v1.removeAllElements();
//ig = true;
}
}
Graphics2D g1 = (Graphics2D) g;
//遍歷畫出內(nèi)容
for (Shape type: v) {
g1.setStroke(type.getStroke());//當(dāng)前圖形粗細(xì)
g1.setColor(type.getColor());//當(dāng)前顏色
int x1 = type.getX1();
int y1 = type.getY1();
int x2 = type.getX2();
int y2 = type.getY2();
//根據(jù)image選擇draw
if(type.getImage().equals("空心圓")){//圓
g1.drawOval(x1,y1,x2,y2);//這里x2=y2=r
}
else if(type.getImage().equals("實(shí)心圓")){//實(shí)心圓
g1.fillOval(x1,y1,x2,y2);//這里x2=y2=r
}
else if(type.getImage().equals("空心橢圓")){//橢圓
g1.drawOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
else if(type.getImage().equals("實(shí)心橢圓")){//實(shí)心橢圓
g1.fillOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
else if (type.getImage().equals("空心矩形")) {//矩形
//左上角坐標(biāo) 長寬
g1.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
else if (type.getImage().equals("實(shí)心矩形")){//實(shí)心矩形
//左上角坐標(biāo) 長寬
g1.fillRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
else{//線(其他多邊形 曲線都是由若干條線組成的)
g1.drawLine(x1,y1,x2,y2); //連接兩端點(diǎn)
}
}
if(ig) g1.drawImage(image,this.getX()+200,this.getY()+200,this);
}
public Vector<Shape> getV() {
return v;
}
public void setV(Vector<Shape> v) {
this.v = v;
}
public Vector<Shape> getV1() {
return v1;
}
public void setV1(Vector<Shape> v1) {
this.v1 = v1;
}
public boolean isBack() {
return back;
}
public void setBack(boolean back) {
this.back = back;
}
public Image getImage() {
return image;
}
public void setImage(Image image) {
this.image = image;
}
public boolean isIg() {
return ig;
}
public void setIg(boolean ig) {
this.ig = ig;
}
}
最終效果
程序所需圖片如下:
?這里要實(shí)現(xiàn)拉伸功能,大家可以去學(xué)一下GUI中的異或操作。
- 面向?qū)ο?
設(shè)計(jì)
- 在問題領(lǐng)域中根據(jù)需求識別對象
- 將識別出的對象抽象為類
- 找出對象與對象之間的聯(lián)系
- 進(jìn)行類的設(shè)計(jì),屬性、方法、繼承等,建立類層次結(jié)構(gòu)
- 創(chuàng)建各類對象,傳遞參數(shù),調(diào)用類中方法,根據(jù)對象間的聯(lián)系,在主函數(shù)中展示組裝。
優(yōu)秀的面向?qū)ο缶幊?,合理的進(jìn)行類的設(shè)計(jì),各種抽象的類、接口,那是必不可少的。
優(yōu)勢
在此次程序,通過面向?qū)ο缶幊?,對于窗口的處理,我可以抽象出類來解決。我可以獨(dú)立的分成幾個類,分解若干個對象,描述事物在整個解決問題的步驟中的行為。我根據(jù)程序的目的,抽象出了菜單、工具欄、監(jiān)聽器、圖形、頂級容器類,通過創(chuàng)建他們的對象,關(guān)聯(lián)組裝,就可以完成這個程序設(shè)計(jì),并且層次較為清晰。
我目前沒有用面向過程的編程進(jìn)行過此類圖形化界面程序的實(shí)現(xiàn),但是也有寫過一次千行的大作業(yè),其中全是邏輯算法問題,單純各種函數(shù)的書寫,解決某一步的問題,與此程序書寫風(fēng)格大相徑庭。
因此通過此程序,也可以感受到面向?qū)ο蟮囊恍﹥?yōu)勢。也多少能體會到兩種編程的一些差別。用面向過程的語言書寫代碼,更偏向于順序完成,調(diào)用函數(shù)。面向?qū)ο缶团c此有大的差別,思路不同、解決方法的實(shí)現(xiàn)可能現(xiàn)在對我而言是差不多,但是解決方法的路徑與過程差距很大。
面向過程中的解決問題的方法主要是函數(shù),而面向?qū)ο笾饕穷悾ㄟ@是面向過程編程所不具備的),抽象成類,構(gòu)造類屬性、方法,創(chuàng)建對象,解決問題,且?guī)в嗅槍π浴?mark hidden color="red">文章來源:http://www.zghlxwxcb.cn/news/detail-475674.html
另外面向過程是一種以過程為中心的編程思想,缺點(diǎn)就是重用率低,擴(kuò)展能力差。而面向?qū)ο缶幊虅t更容易設(shè)計(jì)出清晰、耦合度低的系統(tǒng),并且便于程序修改更新。對我這個程序而言最關(guān)鍵的是易復(fù)用,可繼承,能更好的聯(lián)系,這同時也是面向?qū)ο缶幊痰囊恍﹥?yōu)勢。文章來源地址http://www.zghlxwxcb.cn/news/detail-475674.html
到了這里,關(guān)于用JAVA寫一個畫圖小程序(JAVA 大作業(yè))的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!