實作一個簡易記事本
效果:記事本界面,實作使用者編輯内容,文本字型設定,檔案儲存,檔案打開,記事本退出
先來看看最後運作的一個結果界面:(代碼在最後)
分析上圖,第一個觀察簡易記事本的主要構成
1.菜單欄
2.文本域
3.給文本域添加的滾動條
第二個考慮窗體布局,明顯的使用方位布局–BorderLayout。菜單欄添加到窗體的上方,文本域添加到窗體的中間。
第三個考慮使用到的元件:面闆JPanel,菜單欄JMenuBar,菜單JMenu,文本域JTextArea,文本域的滾動條JScrollPane,
還有三個菜單JMenu:file 、edit 、view
第四個,代碼的實作思路
1.定義要用到的變量
2.建立主要方法分别實作:變量初始化、元件往窗體上添加、元件事件監聽,儲存檔案,打開檔案,記事本退出等功能
代碼有一些細節要注意,菜單有哪些都可以自己定義,如下,每倆功能之間都有一條下劃線,當然這個不添加也可以。
代碼實作
package test2;
//簡易記事本,裡面的this是調用成員變量,解決局部變量名稱沖突問題
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
//繼承JFrame的這個父類,實作監聽器的接口
public class EasyTXT extends JFrame implements ActionListener {
//觀察布局,有菜單欄和文本域兩個上下組成,是以用方位布局
//先定義要用到的變量
JPanel jp;//窗體主面闆
JTextArea jta;//文本域
JScrollPane jsp;//文本域的滾動條
JMenuBar jmb;//菜單欄元件
JMenu file,edit,view;//菜單内容
File currentFile=null;//目前打開的檔案
boolean wasSaved=true;//目前檔案是否儲存
public void TextEditor(){ //該方法實作對元件的初始化
jp=new JPanel();//初始化面闆
jmb=new JMenuBar();//初始化菜單欄元件
jta=new JTextArea(50,50);//初始化文本域
jta.getDocument().addDocumentListener(
//給文本域注冊監聽器,用來監聽文檔是否發生更改,DocumentListener()接口中有三個方法
new DocumentListener() {
@Override//表示繼承,以下三個方法是對父類方法的一個重寫
public void insertUpdate(DocumentEvent e) {
wasSaved=false;//表示編輯框有修改操作
//當監聽到有這三種操作時就代表着文本将重新儲存,這時文本狀态是未儲存的,是以用false,true是檔案已儲存
}
@Override
public void removeUpdate(DocumentEvent e) {
wasSaved=false;//表示對編輯框有插入操作
}
@Override
public void changedUpdate(DocumentEvent e) {
wasSaved=false;//表示對編輯框内容有删除的操作
}
}
);
jsp=new JScrollPane(jta);// 給文本域添加滾動條
//下面對三個菜單按鈕進行定義
file=new JMenu("File");//第一個,file菜單
JMenuItem item;//定義菜單項
file.add(item=new JMenuItem("New"));//給file添加以下功能
item.addActionListener(this);
file.add(item=new JMenuItem("Open..."));
item.addActionListener(this);
file.addSeparator();//調用該方法,在這兩個功能下添加一條下劃線
file.add(item=new JMenuItem("Save"));
item.addActionListener(this);
file.add(item=new JMenuItem("Save As..."));
item.addActionListener( this);
file.addSeparator();//調用該方法,添加一條下劃線
file.add(item=new JMenuItem("Quit"));
item.addActionListener( this);
//給edit菜單添加以下功能
edit=new JMenu("Edit");
edit.add(item=new JMenuItem("Find..."));
item.addActionListener( this);
edit.add(item=new JMenuItem("Replace..."));
item.addActionListener(this);
//給view菜單添加以下功能
view=new JMenu("View");
view.add(item=new JMenuItem("Font..."));
item.addActionListener(this);
view.add(item=new JMenuItem("Color..."));
item.addActionListener(this);
}
public void init(){ //菜單欄和窗體的添加
jmb.add(file);//把三個菜單都添加到菜單欄元件上去
jmb.add(edit);
jmb.add(view);
this.setJMenuBar(jmb);//再設定jmb 為窗體的菜單欄,這個this指的是jp
this.add(jsp, BorderLayout.CENTER);//把帶有滾動條的文本域添加到面闆中間,這個this也是指jp
setSize(800,600);//窗體大小設定
jta.setFont(new Font("宋體",Font.PLAIN,18));//字型設定
setVisible(true);//視窗可見
}
public void actionPerformed(ActionEvent e){//該方法是對每個菜單事件的監聽
String command=e.getActionCommand();//獲得點選按鈕的字元串
//getSource得到的元件的名稱,而getActionCommand得到的是标簽。
if(command.equals("Open...")){
File f=null;
openFile(f);
currentFile=f;
return;
}
if(command.equals("Color...")){
//Color菜單處理
Color c=JColorChooser.showDialog(this,"選擇文字顔色",Color.BLACK);
jta.setForeground(c);//對文字進行顔色設定
return;
}
if(command.equals("Quit")){
this.dispose(); //關閉gui頁面,關閉窗體并釋放一部分窗體所占資源
}
if(command.equals("Save As...")){
File f = null;
saveFileAs(f);
currentFile=f;
return;
}
if(command.equals("Save")){
File f=null;
saveFile(f);
currentFile = f;
return;
}
}
//檔案儲存~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public void saveFile(File f){
// 從标題欄取得檔案名稱
File file = new File(getTitle());
// 若指定的檔案不存在
if(!file.exists()) {
// 執行另存為
saveFileAs(file);
}
else {
try {
// 開啟指定的檔案,建立一個字元輸出緩沖流,讓使用者輸入資料
BufferedWriter buf = new BufferedWriter(new FileWriter(file));
// 将文字編輯區的文字寫入檔案,
buf.write(jta.getText());
buf.close();//關閉緩沖流
}
catch(IOException e) {
JOptionPane.showMessageDialog(null, e.toString(),
"寫入檔案失敗", JOptionPane.ERROR_MESSAGE);
}
}
}
private void saveFileAs(File f) {
// 顯示檔案對話框
JFileChooser fileChooser = new JFileChooser();//建立檔案選擇器
int option = fileChooser.showSaveDialog(null);//show‘’儲存‘’
//showSaveDialog(null);----show‘’儲存‘’
//showOpenDialog(null);----show“打開”
// 如果确認選取檔案
if(option == JFileChooser.APPROVE_OPTION) {
//JFileChooser.APPROVE_OPTION是個整型常量,代表0。就是說當傳回0的值我們才執行相關操作,否則什麼也不做。
// 取得選擇的檔案
File file = fileChooser.getSelectedFile();
// 在标題欄上設定檔案名稱
setTitle(file.toString());
try {
// 建立檔案
file.createNewFile();
// 進行檔案儲存
saveFile(file);
}
catch(IOException e) {
JOptionPane.showMessageDialog(null, e.toString(),
"無法建立新檔案", JOptionPane.ERROR_MESSAGE);
}
}
}
//檔案打開~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public void openFile(File f){
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Open file");
int option=fileChooser.showDialog(null, null);
// 使用者按下确認鍵
if(option == JFileChooser.APPROVE_OPTION) {
try {
// 開啟選取的檔案
BufferedReader buf =new BufferedReader(new FileReader(fileChooser.getSelectedFile()));
// 設定檔案标題
setTitle(fileChooser.getSelectedFile().toString());
// 清除前一次檔案
clearjta();
// 取得系統相依的換行字元
String lineSeparator = System.getProperty("line.separator");//擷取系統參數
// 讀取檔案并附加至文字編輯區
String text;//定義文本
while((text = buf.readLine()) != null) {
jta.append(text);
jta.append(lineSeparator);
}
buf.close();
}
catch(IOException e) {
JOptionPane.showMessageDialog(null, e.toString(),
"開啟檔案失敗", JOptionPane.ERROR_MESSAGE);
}
}
}
private void clearjta() {
jta.selectAll();
jta.replaceSelection("");
}
public static void main(String[] args){
EasyTXT tx=new EasyTXT();
tx.TextEditor();
tx.init();
}
}
這裡也順便記錄一下關于setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE)方法,上述代碼沒有用到:
沒有設定的話,預設點關閉時隻是隐藏窗體,在背景程序中還可以看到,如果有多個視窗,隻是銷毀調用dispose的視窗,其他視窗仍然存在,整個應用程式還是處于運作狀态。