筆者是個Java小白,這幾天用Java寫記事本的源碼,不懂的地方就在部落格上查找學習,文章中有一些代碼就是從CSDN上學習或者摘抄的嘻嘻!在這裡筆者對在寫代碼的過程中進行一些總結。另外也希望讀者看完可以的話給出一些建議或者指出我的不足嘻嘻,我将不勝感激!!!
//導包,建立所需元件和添加元件
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import javax.security.auth.callback.ConfirmationCallback;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.BadLocationException;
import javax.swing.undo.UndoManager;
class noteBookDemo extends JFrame implements ActionListener {
private Container c = getContentPane();
private JMenuBar jmb = new JMenuBar();// 菜單欄
private JPopupMenu pop = new JPopupMenu();// 彈出菜單
// 父菜單
private JMenu fileMenu = new JMenu("檔案(F)");
private JMenu editMenu = new JMenu("編輯(E)");
private JMenu helpMenu = new JMenu("幫助(H)");
private JMenu readMenu = new JMenu("檢視(V)");
private JMenu formatMenu = new JMenu("格式(O)");
// 子菜單
private JMenuItem newMenu = new JMenuItem(" 建立(N) ");
private JMenuItem openMenu = new JMenuItem(" 打開(O) ");
private JMenuItem saveMenu = new JMenuItem(" 儲存(S) ");
private JMenuItem saveAnotherMenu = new JMenuItem(" 另存為(A) ");
private JMenuItem printMenu = new JMenuItem(" 列印(P) ");
private JMenuItem setPageMenu = new JMenuItem(" 頁面設定(U) ");
private JMenuItem exitMenu = new JMenuItem(" 退出(X) ");
private JMenuItem cancelMenu1 = new JMenuItem(" 撤銷(U) "), cancelMenu2 = new JMenuItem(" 撤銷(U) ");
private JMenuItem shearMenu1 = new JMenuItem(" 剪切(T) "), shearMenu2 = new JMenuItem(" 剪切(T) ");
private JMenuItem copyMenu1 = new JMenuItem(" 複制(C) "), copyMenu2 = new JMenuItem(" 複制(C) ");
private JMenuItem pasteMenu1 = new JMenuItem(" 粘貼(P) "), pasteMenu2 = new JMenuItem(" 粘貼(P) ");
private JMenuItem deleteMenu1 = new JMenuItem(" 删除(L) "), deleteMenu2 = new JMenuItem(" 删除(L) ");
private JMenuItem foundMenu = new JMenuItem(" 查找(F) ");
private JMenuItem foundNextMenu = new JMenuItem(" 查找下一個(N) ");
private JMenuItem replaceMenu = new JMenuItem(" 替換(R) ");
private JMenuItem allSectionMenu1 = new JMenuItem(" 全選(A) "), allSectionMenu2 = new JMenuItem(" 全選(A) ");
private JMenuItem DateMenu = new JMenuItem(" 時間/日期(D) ");
private JRadioButtonMenuItem autoMenu = new JRadioButtonMenuItem(" 自動換行(W) ", true);
private JMenuItem sizeMenu = new JMenuItem(" 字型(F) ");
private JRadioButtonMenuItem stateMenu = new JRadioButtonMenuItem(" 狀态欄(S) ");
private JMenuItem readHelpMenu = new JMenuItem(" 檢視幫助(H) ");
private JMenuItem aboutMenu = new JMenuItem(" 關于記事本(A) ");
// 其他元件
private JTextArea jta = new JTextArea("");
private JScrollPane jsp = new JScrollPane(jta);
private FileDialog _Open = new FileDialog(this, "打開檔案", FileDialog.LOAD);
private FileDialog _Save = new FileDialog(this, "儲存檔案", FileDialog.SAVE)
private UndoManager undom = new UndoManager();
private JLabel jla = new JLabel("");
// 構造方法
noteBookDemo() {
super("記事本");
setJMenuBar(jmb);
// 向檔案菜單添加子菜單,設定鍵盤辨別符,快捷鍵,添加子菜單監聽器
fileMenu.add(newMenu);
newMenu.setMnemonic('N');
newMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
newMenu.addActionListener(this);
fileMenu.add(openMenu);
openMenu.setMnemonic('O');
openMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
openMenu.addActionListener(this);
fileMenu.add(saveMenu);
saveMenu.setMnemonic('S');
saveMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
saveMenu.addActionListener(this);
fileMenu.add(saveAnotherMenu);
saveAnotherMenu.setMnemonic('A');
saveAnotherMenu.addActionListener(this);
fileMenu.addSeparator();
fileMenu.add(setPageMenu);
setPageMenu.setMnemonic('U');
setPageMenu.addActionListener(this);
fileMenu.add(printMenu);
printMenu.setMnemonic('P');
printMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, ActionEvent.CTRL_MASK));
printMenu.addActionListener(this);
fileMenu.addSeparator();
fileMenu.add(exitMenu);
exitMenu.setMnemonic('X');
exitMenu.addActionListener(this);
fileMenu.setMnemonic(KeyEvent.VK_F);
// 向編輯菜單添加子菜單,設定鍵盤辨別符,快捷鍵,添加子菜單監聽器(包括彈出菜單)
editMenu.add(cancelMenu1);
cancelMenu1.setMnemonic('U');
cancelMenu1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK));
cancelMenu1.addActionListener(this);
cancelMenu2.addActionListener(this);
editMenu.addSeparator();
editMenu.add(shearMenu1);
shearMenu1.setMnemonic('T');
shearMenu1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.CTRL_MASK));
shearMenu1.addActionListener(this);
shearMenu2.addActionListener(this);
editMenu.add(copyMenu1);
copyMenu1.setMnemonic('C');
copyMenu1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK));
copyMenu1.addActionListener(this);
copyMenu2.addActionListener(this);
editMenu.add(pasteMenu1);
pasteMenu1.setMnemonic('P');
pasteMenu1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK));
pasteMenu1.addActionListener(this);
pasteMenu2.addActionListener(this);
editMenu.add(deleteMenu1);
deleteMenu1.setMnemonic('L');
deleteMenu1.setAccelerator(KeyStroke.getKeyStroke("Delete"));
deleteMenu2.setAccelerator(KeyStroke.getKeyStroke("Backspace"));
deleteMenu1.addActionListener(this);
deleteMenu2.addActionListener(this);
editMenu.addSeparator();
editMenu.add(foundMenu);
foundMenu.setMnemonic('F');
foundMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, ActionEvent.CTRL_MASK));
foundMenu.addActionListener(this);
editMenu.add(foundNextMenu);
foundNextMenu.setMnemonic('N');
foundNextMenu.setAccelerator(KeyStroke.getKeyStroke("F3"));
foundNextMenu.addActionListener(this);
editMenu.add(replaceMenu);
replaceMenu.setMnemonic('R');
replaceMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, ActionEvent.CTRL_MASK));
replaceMenu.addActionListener(this);
editMenu.addSeparator();
editMenu.add(allSectionMenu1);
allSectionMenu1.setMnemonic('A');
allSectionMenu1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.CTRL_MASK));
allSectionMenu1.addActionListener(this);
allSectionMenu2.addActionListener(this);
editMenu.add(DateMenu);
DateMenu.setMnemonic('D');
DateMenu.setAccelerator(KeyStroke.getKeyStroke("F5"));
DateMenu.addActionListener(this);
editMenu.setMnemonic(KeyEvent.VK_E);
// 向格式菜單添加子菜單,設定鍵盤辨別符,快捷鍵,添加子菜單監聽器
formatMenu.add(autoMenu);
autoMenu.setMnemonic('W');
autoMenu.addActionListener(this);
formatMenu.add(sizeMenu);
sizeMenu.setMnemonic('F');
sizeMenu.addActionListener(this);
formatMenu.setMnemonic(KeyEvent.VK_O);
// 向檢視菜單添加子菜單,設定鍵盤辨別符,快捷鍵,添加子菜單監聽器
readMenu.add(stateMenu);
stateMenu.setMnemonic('S');
stateMenu.addActionListener(this);
readMenu.setMnemonic(KeyEvent.VK_V);
// 向幫助菜單添加子菜單,設定鍵盤辨別符,快捷鍵,添加子菜單監聽器
helpMenu.add(readHelpMenu);
readHelpMenu.setMnemonic('H');
readHelpMenu.addActionListener(this);
helpMenu.addSeparator();
helpMenu.add(aboutMenu);
aboutMenu.setMnemonic('A');
aboutMenu.addActionListener(this);
helpMenu.setMnemonic(KeyEvent.VK_H);
// 添加菜單群組件
jmb.add(fileMenu);
jmb.add(editMenu);
jmb.add(formatMenu);
jmb.add(readMenu);
jmb.add(helpMenu);
c.add(jsp, BorderLayout.CENTER);
c.add(jla, BorderLayout.SOUTH);
// 設定文本域字型和自動換行
jta.setFont(new Font("宋體", 0, 25));
jta.setLineWrap(true);
jta.setWrapStyleWord(true);// 單詞格式
// 設定菜單和子菜單的字型
fileMenu.setFont(new Font("宋體", 0, 20));
editMenu.setFont(new Font("宋體", 0, 20));
formatMenu.setFont(new Font("宋體", 0, 20));
readMenu.setFont(new Font("宋體", 0, 20));
helpMenu.setFont(new Font("宋體", 0, 20));
newMenu.setFont(new Font("宋體", 0, 20));
openMenu.setFont(new Font("宋體", 0, 20));
saveMenu.setFont(new Font("宋體", 0, 20));
saveAnotherMenu.setFont(new Font("宋體", 0, 20));
setPageMenu.setFont(new Font("宋體", 0, 20));
printMenu.setFont(new Font("宋體", 0, 20));
exitMenu.setFont(new Font("宋體", 0, 20));
cancelMenu1.setFont(new Font("宋體", 0, 20));
cancelMenu2.setFont(new Font("宋體", 0, 20));
shearMenu1.setFont(new Font("宋體", 0, 20));
shearMenu2.setFont(new Font("宋體", 0, 20));
copyMenu1.setFont(new Font("宋體", 0, 20));
copyMenu2.setFont(new Font("宋體", 0, 20));
pasteMenu1.setFont(new Font("宋體", 0, 20));
pasteMenu2.setFont(new Font("宋體", 0, 20));
deleteMenu1.setFont(new Font("宋體", 0, 20));
deleteMenu2.setFont(new Font("宋體", 0, 20));
foundMenu.setFont(new Font("宋體", 0, 20));
foundNextMenu.setFont(new Font("宋體", 0, 20));
replaceMenu.setFont(new Font("宋體", 0, 20));
allSectionMenu1.setFont(new Font("宋體", 0, 20));
allSectionMenu2.setFont(new Font("宋體", 0, 20));
DateMenu.setFont(new Font("宋體", 0, 20));
autoMenu.setFont(new Font("宋體", 0, 20));
sizeMenu.setFont(new Font("宋體", 0, 20));
stateMenu.setFont(new Font("宋體", 0, 20));
readHelpMenu.setFont(new Font("宋體", 0, 20));
aboutMenu.setFont(new Font("宋體", 0, 20));
jla.setFont(new Font("宋體", 0, 30));
// 添加彈出菜單選項
pop.add(cancelMenu2);
pop.add(shearMenu2);
pop.add(copyMenu2);
pop.add(pasteMenu2);
pop.add(deleteMenu2);
pop.add(allSectionMenu2);
jta.requestFocus();
// 設定視窗屬性以及編輯器菜單的可用性
checkMenuItemEnabled();
foundMenu.setEnabled(false);
foundNextMenu.setEnabled(false);
cancelMenu1.setEnabled(false);
cancelMenu2.setEnabled(false);
jla.setVisible(false);
setBounds(200, 200, 1114, 744);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);"
總結:
1.FileDialog 類顯示一個對話框視窗,使用者可以從中選擇檔案。構造方法如下:
FileDialog(Frame parent, String title, int mode)
建立一個具有指定标題的檔案對話框視窗,用于打開或儲存檔案。其中mode包括FileDialog.LOAD和FileDialog.SAVE
2.UndoManager與撤銷操作有關(這是在CSDN上學到借鑒的代碼,詳細内容可以去看看API)
3.setMnemonic()方法是菜單的鍵盤辨別符
setAccelerator(KeyStroke keyStroke)
eg:Ctrl+C的快捷鍵 copyMenu1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK));
setLineWrap(true/false) 設定是否自動換行
setWrapStyleWord(true/false) 設定單詞格式
addSeparator() 在菜單欄添加分隔線
添加文本框的監聽器
// 通過内部類添加彈出菜單監聽器并實作文本域的滑鼠事件
jta.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (e.getModifiers() == InputEvent.BUTTON3_MASK)
pop.show(jta, e.getX(), e.getY());//彈出菜單彈出的位置
// 設定編輯中一些功能的可用性
checkMenuItemEnabled();
jta.requestFocus();
}// end mouseReleased
}// end MouseAdapter
);// end addMouseListener
// 通過内部類對文本内容添加監聽器
jta.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
cancelMenu1.setEnabled(true);
cancelMenu2.setEnabled(true);
}// end changedUpdate
@Override
public void insertUpdate(DocumentEvent e) {
cancelMenu1.setEnabled(true);
cancelMenu2.setEnabled(true);
// 當向文本輸入内容即文本不為空,查找功能可用
foundMenu.setEnabled(true);
foundNextMenu.setEnabled(true);
}// end insertUpdate
@Override
public void removeUpdate(DocumentEvent e) {
cancelMenu1.setEnabled(true);
cancelMenu2.setEnabled(true);
// 當删除(所選)文本内容時,将編輯中一些功能禁用
shearMenu1.setEnabled(false);
shearMenu2.setEnabled(false);
copyMenu1.setEnabled(false);
copyMenu2.setEnabled(false);
deleteMenu1.setEnabled(false);
deleteMenu2.setEnabled(false);
// 當文本域無内容時,将查找功能禁用
if (jta.getText().length() == 0) {
foundMenu.setEnabled(false);
foundNextMenu.setEnabled(false);
} // end if
}// end removeUpdate
}// end DocumentListener
);// end addDocumentListener
// 通過内部類對文本内容添加監聽器(撤銷功能)
jta.getDocument().addUndoableEditListener(new UndoableEditListener() {
@Override
public void undoableEditHappened(UndoableEditEvent e) {
undom.addEdit(e.getEdit());
}// end undoableEditHappened
}// end UndoableEditListener
);// end addUndoableEditListener
總結:
1.getDocument() 擷取與編輯器關聯的模型(對文本域的内容進行監控)
2.setEnabled(true/false) 設定元件的可操作性(例如菜單中的複制操作)
// 通過内部類對視窗添加監聽器(右上角關閉按鈕)
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// 如果是新檔案,即标題任為記事本,則執行exit()方法
if (getTitle() == "記事本")
exit();
// 如果不是新檔案,即有标題為包含".txt"的檔案名,則進行判斷文本域内容是否與原檔案相同
// (注意:末尾存在換行問題)(這裡有一點小bug)
else {
try {
// 定義3個String對象并獲得檔案目錄
String s = _Open.getDirectory(), str1 = "", line = "";
if (_Open.getDirectory() == null)
s = _Save.getDirectory();
// 建立指定檔案和讀取檔案流的對象
File f = new File(s + getTitle());
BufferedReader r = new BufferedReader(new FileReader(f));
// 一行一行的讀取檔案
while ((line = r.readLine()) != null)
str1 += line + "\n";
// 處理末尾換行問題
if (jta.getText().length() > 0) {
if (jta.getText().charAt(jta.getText().length() - 1) != '\n')
str1 = str1.substring(0, str1.length() - 1);
}
// 判斷兩者是否相等,不等則執行exit()方法,相等則直接關閉視窗
if (!str1.equals(jta.getText()))
exit();
else
System.exit(0);
r.close();
} // end try
catch (FileNotFoundException em) {
em.printStackTrace();
} // end catch
catch (IOException ee) {
ee.printStackTrace();
} // end catch
} // end else
}// end windowClosing
}// end WindowAdapter
);// end addWindowListener
}// end 構造方法
總結:WindowAdapter類:接收視窗事件的抽象擴充卡類。此類中的方法為空。此類存在的目的是友善建立偵聽器對象。
//實作接口中的方法
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().contains("建立"))
news();
if (e.getActionCommand().contains("打開"))
open();
if (e.getActionCommand().contains("儲存"))
save();
if (e.getActionCommand().contains("另存為"))
saveAnother();
if (e.getActionCommand().contains("頁面設定"))
setPage();
if (e.getActionCommand().contains("列印"))
print();
if (e.getActionCommand().contains("退出"))
exit();
if (e.getActionCommand().contains("撤銷"))
cancel();
if (e.getActionCommand().contains("剪切"))
shear();
if (e.getActionCommand().contains("複制"))
copy();
if (e.getActionCommand().contains("粘貼"))
paste();
if (e.getActionCommand().contains("删除"))
delete();
if (e.getActionCommand().equals(" 查找(F) "))
found();
if (e.getActionCommand().contains("替換"))
replace();
if (e.getActionCommand().contains("全選"))
allSelection();
if (e.getActionCommand().contains("日期"))
date();
if (e.getActionCommand().contains("自動換行"))
auto();
if (e.getActionCommand().contains("字型"))
font();
if (e.getActionCommand().contains("狀态欄"))
state();
if (e.getActionCommand().contains("檢視幫助"))
readHelp();
if (e.getActionCommand().contains("關于記事本"))
about();
}
// 設定編輯器的功能可用性
public void checkMenuItemEnabled() {
String selectText = jta.getSelectedText();
// 文本域沒有内容被選中時一些菜單功能不可用
if (selectText == null) {
shearMenu1.setEnabled(false);
shearMenu2.setEnabled(false);
copyMenu1.setEnabled(false);
copyMenu2.setEnabled(false);
deleteMenu1.setEnabled(false);
deleteMenu2.setEnabled(false);
} // end if
// 文本域有内容被選中時菜單功能可用
else {
shearMenu1.setEnabled(true);
shearMenu2.setEnabled(true);
copyMenu1.setEnabled(true);
copyMenu2.setEnabled(true);
deleteMenu1.setEnabled(true);
deleteMenu2.setEnabled(true);
} // end else
}// end checkMenuItemEnabled
建立功能
思路:判斷文本域是否有内容,有内容在建立之前彈出是否儲存的視窗後再進行建立,無内容則直接建立
private void news() {
// 如果文本域有内容執行以下if語句中代碼,否則直接執行建立功能
if (!jta.getText().equals("")) {
// 彈出提示視窗
int result = JOptionPane.showConfirmDialog(this, "是否儲存", "記事本", JOptionPane.YES_NO_CANCEL_OPTION);
// 執行是按鈕
if (result == JOptionPane.YES_OPTION) {
// 如果視窗标題為"記事本"即檔案尚未存在,則執行saveAnother()方法進行另存為功能
if (getTitle() == "記事本")
saveAnother();
// 如果視窗标題為包含“.txt”的檔案名即檔案已存在,則執行save()方法進行儲存功能
else
save();
// 儲存後将文本域内容清空并将标題改為"記事本",完成建立功能
jta.setText("");
setTitle("記事本");
} // end if
// 執行否按鈕,即不進行儲存工作,直接将文本域内容清空并将視窗标題改為"記事本"完成建立功能
if (result == JOptionPane.NO_OPTION) {
jta.setText("");
setTitle("記事本");
} // end if
} // end if
}// end news()
總結:
JOptionPane 有助于友善地彈出要求使用者提供值或向其發出通知的标準對話框。其中的一些方法如下:
方法名 | 描述 |
---|---|
showConfirmDialog | 詢問一個确認問題,如 yes/no/cancel |
showInputDialog | 提示要求某些輸入 |
showMessageDialog | 告知使用者某事已發生 |
showOptionDialog | 上述三項的大統一 (Grand Unification) |
messageType
定義 message 的樣式。外觀管理器根據此值對對話框進行不同地布置,并且通常提供預設圖示。可能的值為:
ERROR_MESSAGE ;INFORMATION_MESSAGE; WARNING_MESSAGE;QUESTION_MESSAGE ;
PLAIN_MESSAGE
optionType
定義在對話框的底部顯示的選項按鈕的集合:
DEFAULT_OPTION ;YES_NO_OPTION ;
YES_NO_CANCEL_OPTION ;OK_CANCEL_OPTION
例子:JOptionPane.showConfirmDialog(this, “是否儲存”, “記事本”, JOptionPane.YES_NO_CANCEL_OPTION);
打開功能
思路:打開前先彈出是否儲存的視窗判斷是否對目前内容進行儲存,然後在彈出打開視窗選擇目标檔案打開,若未選擇目标檔案(關閉選擇檔案的視窗),文本域的内容不變化,仍為執行打開前的内容
// 打開功能的實作方法
private void open() {
String str = "";
// 打開操作前判斷是否進行儲存工作
// if (getTitle() != "記事本" || jta.getText() != null) {
int result = JOptionPane.showConfirmDialog(this, "是否儲存", "記事本", JOptionPane.YES_NO_CANCEL_OPTION);
if (result == JOptionPane.YES_OPTION)
save();
if (result == JOptionPane.YES_OPTION || result == JOptionPane.NO_OPTION) {
_Open.setVisible(true);// 将打開視窗可視化
try {
// 獲得檔案名并建立流
File f = new File(_Open.getDirectory() + _Open.getFile());
BufferedReader r = new BufferedReader(new FileReader(f));
if (_Open.getFile() != null) {
jta.setText("");
// 讀取檔案内容并寫入文本域中
while ((str = r.readLine()) != null)
jta.append(str + "\n");
// 将視窗标題設定為打開檔案的檔案名
// if (_Open.getFile() != null)
this.setTitle(_Open.getFile());
}
r.close();
} // end try
catch (FileNotFoundException e) {
// 所指定的打開檔案如果不存在則彈出錯誤視窗
JOptionPane.showMessageDialog(null, "所選檔案不存在或未選擇檔案", "錯誤", JOptionPane.ERROR_MESSAGE);
} // end catch
catch (IOException e) {
e.printStackTrace();
} // end catch
} // end if
}// end open
儲存功能
思路:若檔案不存在,則彈出另存為視窗,若檔案已存在,則隻彈出是否儲存的視窗
// 儲存功能的實作方法
private void save() {
// 如果視窗标題為 "記事本"即不是檔案名,直接執行saveAnother()方法
if (this.getTitle() == "記事本")
saveAnother();
// 否則,執行儲存功能
else {
try {
// 建立指定檔案和輸出流的對象
File f = new File(_Open.getDirectory() + this.getTitle());
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
// 将文本域的内容轉換為字元并寫入指定檔案中
char[] str = jta.getText().toCharArray();
for (int i = 0; i < str.length; i++) {
if (str[i] != '\n')
w.write(str[i]);
else
w.newLine();
} // end for
w.close();
} // end try
catch (IOException e) {
e.printStackTrace();
} // end catch
} // end else
}// end save
另存為功能
思路:彈出儲存視窗,選擇儲存路徑及檔案名
// 另存為功能的方法
private void saveAnother() {
// 将另存為彈出的界面可視化
_Save.setVisible(true);
try {
// 建立指定檔案和寫檔案流的對象
File f = new File(_Save.getDirectory() + _Save.getFile());
BufferedWriter w = new BufferedWriter(new FileWriter(f));
// 将文本域的内容轉換為字元并寫入指定檔案中
char[] str = jta.getText().toCharArray();
for (int i = 0; i < str.length; i++) {
if (str[i] != '\n')
w.write(str[i]);
else
w.newLine();
} // end for
// 實作另存為功能後将視窗标題改為所存的檔案名,未實作則隻關閉提示視窗不關閉主視窗
if (_Save.getFile() != null)
this.setTitle(_Save.getFile());
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
w.close();
} // end try
catch (IOException e) {
e.printStackTrace();
} // end catch
}// end saveAnother
// 列印的方法
private void print() {
JOptionPane.showMessageDialog(null, "對不起,此菜單功能尚未實作!", "列印", JOptionPane.YES_NO_CANCEL_OPTION);
}
// 頁面設定的方法
private void setPage() {
JOptionPane.showMessageDialog(null, "對不起,此菜單功能尚未實作!", "頁面設定", JOptionPane.YES_NO_CANCEL_OPTION);
}
總結:設定使用者在此窗體上發起 “close” 時預設執行的操作。必須指定以下選項之一:
DO_NOTHING_ON_CLOSE(在 WindowConstants 中定義):不執行任何操作;要求程式在已注冊的 WindowListener 對象的 windowClosing 方法中處理該操作。
HIDE_ON_CLOSE(在 WindowConstants 中定義):調用任意已注冊的 WindowListener 對象後自動隐藏該窗體。
DISPOSE_ON_CLOSE(在 WindowConstants 中定義):調用任意已注冊 WindowListener 的對象後自動隐藏并釋放該窗體。
EXIT_ON_CLOSE(在 JFrame 中定義):使用 System exit 方法退出應用程式。僅在應用程式中使用。
預設情況下,該值被設定為 HIDE_ON_CLOSE。更改此屬性的值将導緻激發屬性更改事件,其屬性名稱為 “defaultCloseOperation”。
關閉功能
思路:彈出是否儲存視窗選擇後關閉視窗
// 關閉的方法
private void exit() {
int result = JOptionPane.showConfirmDialog(this, "是否儲存", "記事本", JOptionPane.YES_NO_CANCEL_OPTION);
// 執行是按鈕
if (result == JOptionPane.YES_OPTION) {
// 判斷标題是否為包含“.txt”的檔案名,是則執行save()方法并關閉視窗
if (this.getTitle().contains(".txt")) {
save();
System.exit(0);
}
// 标題為“記事本”即為非檔案名,執行saveAnother()方法,另存為動作完畢後,直接關閉視窗
else {
saveAnother();
if (getTitle() != "記事本")
System.exit(0);
} // end else
} // end if
// 執行否按鈕,直接關閉視窗
if (result == JOptionPane.NO_OPTION)
System.exit(1);
// 設定提示視窗的屬性,即未操作則隻關閉提示視窗而不關閉主視窗
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
}// end exit
編輯器的撤銷、剪切、複制、粘貼、删除、全選功能
// 撤銷的方法(有bug)
private void cancel() {
if (undom.canUndo()) // 撤銷
undom.undo();
else
undom.redo();// 恢複
}// end cancel
// 剪貼的方法
private void shear() {
copy();// 複制所選段
// 标記開始結束位置
int start = jta.getSelectionStart(), end = jta.getSelectionEnd();
jta.replaceRange("", start, end);// 删除所選段
}// end shear
// 複制的方法
private void copy() {
jta.requestFocus();
String temp = jta.getSelectedText();// 拖動選取文本
StringSelection text = new StringSelection(temp);// 把擷取内容複制到連續字元器
getToolkit().getSystemClipboard().setContents(text, null);// 把内容放在剪貼闆
}// end copy
// 粘貼的方法
private void paste() {
// Transferable接口,把剪貼闆内容轉換為資料
Transferable contents = getToolkit().getSystemClipboard().getContents(this);
// DataFlavor類判斷是否能把剪貼闆的内容轉換為所需資料的類型
DataFlavor flavor = DataFlavor.stringFlavor;
// 如果能轉換
if (contents.isDataFlavorSupported(flavor)) {
String str;
try {
// 開始轉換
str = (String) contents.getTransferData(flavor);
// 滑鼠已選中内容
if (jta.getSelectedText() != null) {
// 定義被選中内容的開始和末尾位置
int start = jta.getSelectionStart(), end = jta.getSelectionEnd();
jta.replaceRange(str, start, end);// 把選中的内容替換為剪貼闆的内容
} // end if
// 滑鼠未選中内容
else {
// 獲得滑鼠在文本域的位置并插入剪貼闆的内容
int mouse = jta.getCaretPosition();
jta.insert(str, mouse);
} // end else
} // end try
catch (UnsupportedFlavorException e) {
e.printStackTrace();
} // end catch
catch (IOException e) {
e.printStackTrace();
} // end catch
catch (IllegalArgumentException e) {
e.printStackTrace();
} // end catch
} // end if
}// end paste
// 删除的方法
private void delete() {
jta.replaceSelection("");
}
// 全選的方法
private void allSelection() {
jta.selectAll();
}// end allSelection
總結:
1./标記開始結束位置
int start = jta.getSelectionStart(), end = jta.getSelectionEnd();
jta.replaceRange(str, start, end); 将選中的内容替換為str
2.requestFocus() 方法用于請求此 Component 擷取輸入焦點。
getCaretPosition()方法用于獲得滑鼠在文本域的位置
setCaretPosition()方法用于設定滑鼠在文本域的位置
insert(str, mouse)方法用于在光标位置插入字元串str
3.粘貼方法的實作
StringSelection(String data) 此構造方法用于建立能傳輸指定 String 的 Transferable。
getToolkit().getSystemClipboard().setContents(text, null); 把内容放在剪貼闆 Transferable接口,把剪貼闆内容轉換為資料
Transferable contents = getToolkit().getSystemClipboard().getContents(this);
DataFlavor類判斷是否能把剪貼闆的内容轉換為所需資料的類型
DataFlavor flavor = DataFlavor.stringFlavor;
判斷是否能轉換 :contents.isDataFlavorSupported(flavor)
能轉換則轉為字元串準備進行粘貼工作 (String)contents.getTransferData(flavor)
查找功能
思路:建立查找視窗,并給其元件添加監聽器(注意是否區分大小寫,查找的方向)。視窗的截圖和代碼如下
// 查找的方法
private void found() {
// 建立查找視窗所需元件
JDialog findDialog = new JDialog(this, "查找", false);
Container con = findDialog.getContentPane();
JLabel findLabel = new JLabel("查找内容(N)");
JTextField findText = new JTextField((15));
JButton findNextButton = new JButton("查找下一個");
JButton cancelButton = new JButton("取消");
JRadioButton upButton = new JRadioButton("向上(U)");
JRadioButton downButton = new JRadioButton("向下(D)");
ButtonGroup bg = new ButtonGroup();
JCheckBox findCheckButton = new JCheckBox("區分大小寫");
GridLayout g = new GridLayout(2, 1);
g.setVgap(10);// 設定網格布局器的垂直間距
bg.add(upButton);
bg.add(downButton);
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
JPanel p4 = new JPanel();
JPanel p5 = new JPanel();
p3.setBorder(BorderFactory.createTitledBorder("方向"));
// 設定布局管理器
con.setLayout(new FlowLayout());
p4.setLayout(new BorderLayout());
p5.setLayout(g);
// 添加元件
p1.add(findLabel);
p1.add(findText);
p2.add(findCheckButton);
p2.add(p3);
p3.add(upButton);
p3.add(downButton);
p4.add(p1, BorderLayout.NORTH);
p4.add(p2, BorderLayout.CENTER);
p5.add(findNextButton);
p5.add(cancelButton);
con.add(p4, BorderLayout.CENTER);
con.add(p5, BorderLayout.EAST);
// 設定查找視窗屬性
downButton.setSelected(true);// 預設向下查找
findNextButton.setEnabled(false);
findDialog.setBounds(230, 280, 410, 150);
findDialog.setResizable(false);
findDialog.setVisible(true);
// 添加取消按鈕的監聽器(内部類的形式)
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
findDialog.dispose();
}// end actionPerformed
}// end ActionListener
);// end addActionListener
// 添加查找文本框内容的監聽器(内部類的形式)
findText.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
}
@Override
// 查找文本框内容不為空時查找按鈕可用
public void insertUpdate(DocumentEvent e) {
findNextButton.setEnabled(true);
}// end insertUpdate
@Override
// 查找文本框内容為空時查找按鈕不可用
public void removeUpdate(DocumentEvent e) {
if (findText.getText().length() == 0)
findNextButton.setEnabled(false);
}// end removeUpdate
}// end ActionListener
);// end addActionListener
// 添加查找下一個按鈕的監聽器(内部類的形式)
findNextButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int k = 0;
String str1, str2, str3, str4, strA, strB;
str1 = jta.getText();
str2 = findText.getText();
str3 = str1.toUpperCase();
str4 = str2.toUpperCase();
// 區分大小寫
if (findCheckButton.isSelected()) {
strA = str1;
strB = str2;
}
// 不區分大小寫
else {
strA = str3;
strB = str4;
}
// 向上查找的方式
if (upButton.isSelected()) {
// 文本未選中内容
if (jta.getSelectedText() == null)
k = strA.lastIndexOf(strB, jta.getCaretPosition());
// 文本已選中内容
else
k = strA.lastIndexOf(strB, jta.getCaretPosition() - strB.length() - 1);
// 查找未結束,繼續向上查找
if (k != -1) {
jta.setCaretPosition(k);
jta.select(k, k + strB.length());
}
// 查找結束,彈出錯誤視窗
else
JOptionPane.showMessageDialog(null, "找不到" + " “ " + findText.getText() + " ” ", "查找",
JOptionPane.INFORMATION_MESSAGE);
} // end 向上查找
// 向下查找的方式
else if (downButton.isSelected()) {
// 文本未選中内容
if (jta.getSelectedText() == null) {
k = strA.indexOf(strB, jta.getCaretPosition());
}
// 文本已選中内容
else
k = strA.indexOf(strB, jta.getCaretPosition() - strB.length() + 1);
// 查找未結束,繼續向下查找
if (k != -1) {
jta.setCaretPosition(k);
jta.select(k, k + strB.length());
}
// 查找結束,彈出錯誤視窗
else
JOptionPane.showMessageDialog(null, "找不到" + " “ " + findText.getText() + " ” ", "查找",
JOptionPane.INFORMATION_MESSAGE);
} // end 向下查找
}// end actionPerformed
}// end ActionListener
);// end addActionListener
// 添加菜單中查找下一個菜單的監聽器(有bug)
foundNextMenu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int k = 0;
String str1, str2, str3, str4, strA, strB;
str1 = jta.getText();
str2 = findText.getText();
str3 = str1.toUpperCase();
str4 = str2.toUpperCase();
// 區分大小寫
if (findCheckButton.isSelected()) {
strA = str1;
strB = str2;
}
// 不區分大小寫
else {
strA = str3;
strB = str4;
}
// 向上查找的方式
if (upButton.isSelected()) {
// 文本未選中内容
if (jta.getSelectedText() == null)
k = strA.lastIndexOf(strB, jta.getCaretPosition());
// 文本已選中内容
else
k = strA.lastIndexOf(strB, jta.getCaretPosition() - strB.length() - 1);
// 查找未結束,繼續向上查找
if (k != -1) {
jta.setCaretPosition(k);
jta.select(k, k + strB.length());
}
// 查找結束,彈出錯誤視窗
else
JOptionPane.showMessageDialog(null, "找不到" + " “ " + findText.getText() + " ” ", "查找",
JOptionPane.INFORMATION_MESSAGE);
} // end 向上查找
// 向下查找的方式
else if (downButton.isSelected()) {
// 文本未選中内容
if (jta.getSelectedText() == null) {
k = strA.indexOf(strB, jta.getCaretPosition());
}
// 文本已選中内容
else
k = strA.indexOf(strB, jta.getCaretPosition() - strB.length() + 1);
// 查找未結束,繼續向下查找
if (k != -1) {
jta.setCaretPosition(k);
jta.select(k, k + strB.length());
}
// 查找結束,彈出錯誤視窗
else
JOptionPane.showMessageDialog(null, "找不到" + " “ " + findText.getText() + " ” ", "查找",
JOptionPane.INFORMATION_MESSAGE);
} // end 向下查找
}// end actionPerformed
}// end ActionListener
);// end addActionListener
}// end found
總結:
1.JDialog(Dialog owner, String title, boolean modal)
此構造方法用于建立一個具有指定标題、模式和指定所有者 Dialog 的自定義對話框。參數如下:
owner - 顯示該對話框的所有者 Dialog;如果此對話框沒有所有者,則為 null
title - 該對話框的标題欄中所顯示的 String
modal - 指定對話框在顯示時是否阻塞使用者向其他頂層視窗輸入。如果為 true,則模式類型屬性被設定為 DEFAULT_MODALITY_TYPE;否則對話框是無模式的
2.網絡布局管理器中setHgap(int hgap) 方法用于将元件之間的水準間距設定為指定值。setVgap(int vgap) 方法用于将元件之間的垂直間距設定為指定值。
3.setSelected(true/false)方法用于預設選中元件
dispose()方法簡單地了解可了解為關閉視窗。
select(int start,int end) 選中内容範圍
setBorder(BorderFactory.createTitledBorder(String str))方法用于向現有邊框添加一個标題,使其具有預設的位置(位于頂線上)、預設的調整 (leading),以及預設的字型和文本顔色。(BorderFactory類具體構造方法可參考API)
替換功能
思路:與查找功能基本一緻,通過查找功能将查找出的内容替換。視窗截圖和代碼如下。
// 替換的方法
private void replace() {
// 定義替換提示視窗所需元件
JDialog replaceDialog = new JDialog(this, "替換", false);
Container replaceCon = replaceDialog.getContentPane();
JLabel findContentLabel = new JLabel("查找内容(N):");
JLabel replaceLabel = new JLabel("替換為(P):");
JTextField findField = new JTextField(15);
JTextField replaceField = new JTextField(15);
JButton findNextButton = new JButton("查找下一個(F)");
JButton replaceButton = new JButton("替換(R)");
JButton replaceAllButton = new JButton("全部替換(A)");
JButton cancelButton = new JButton("取消");
JCheckBox checkButton = new JCheckBox("區分大小寫");
JRadioButton upButton = new JRadioButton("向上(U)");
JRadioButton downButton = new JRadioButton("向下(D)");
ButtonGroup bg = new ButtonGroup();
bg.add(upButton);
bg.add(downButton);
GridLayout g = new GridLayout(4, 1);
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
JPanel p4 = new JPanel();
JPanel p5 = new JPanel();
JPanel p6 = new JPanel();
JPanel p7 = new JPanel();
p2.setBorder(BorderFactory.createTitledBorder("方向"));
// 設定布局管理器
p1.setLayout(new BorderLayout());
p4.setLayout(new BorderLayout());
p5.setLayout(g);
g.setVgap(5);// 設定網格布局管理器垂直間距
p6.setLayout(new BorderLayout());
p7.setLayout(new BorderLayout());
replaceCon.setLayout(new FlowLayout(10));
// 添加元件
p1.add(findContentLabel, BorderLayout.NORTH);
p1.add(replaceLabel, BorderLayout.CENTER);
p6.add(findField, BorderLayout.NORTH);
p6.add(replaceField, BorderLayout.CENTER);
p7.add(p1, BorderLayout.WEST);
p7.add(p6, BorderLayout.CENTER);
p2.add(upButton);
p2.add(downButton);
p3.add(checkButton);
p3.add(p2);
p4.add(p7, BorderLayout.NORTH);
p4.add(p3, BorderLayout.CENTER);
p5.add(findNextButton);
p5.add(replaceButton);
p5.add(replaceAllButton);
p5.add(cancelButton);
replaceCon.add(p4);
replaceCon.add(p5);
// 設定替換視窗屬性
downButton.setSelected(true);// 預設向下查找
findNextButton.setEnabled(false);
replaceButton.setEnabled(false);
replaceAllButton.setEnabled(false);
replaceDialog.setBounds(230, 280, 410, 180);
replaceDialog.setVisible(true);
replaceDialog.setResizable(false);
// 添加取消按鈕的監聽器(内部類的形式)
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
replaceDialog.dispose();
}// end actionPerformed
}// end ActionListener
);// end addActionListener
// 通過内部類的形式添加文本域内容的監聽器
findField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
}
@Override
// 查找文本框内容不為空時查找按鈕,替換按鈕,全部替換按鈕都可用
public void insertUpdate(DocumentEvent e) {
findNextButton.setEnabled(true);
replaceButton.setEnabled(true);
replaceAllButton.setEnabled(true);
}// end insertUpdate
@Override
// 查找文本框内容為空時查找按鈕,替換按鈕,全部替換按鈕都不可用
public void removeUpdate(DocumentEvent e) {
if (findField.getText().length() == 0) {
findNextButton.setEnabled(false);
replaceButton.setEnabled(false);
replaceAllButton.setEnabled(false);
}
}// end removeUpdate
}// end DocumentListener
);// end addDocumentListener
// 添加查找下一個按鈕的監聽器(内部類的形式)
findNextButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int k;
String str1, str2, str3, str4, strA, strB;
str1 = jta.getText();
str2 = findField.getText();
str3 = str1.toUpperCase();
str4 = str2.toUpperCase();
// 區分大小寫
if (checkButton.isSelected()) {
strA = str1;
strB = str2;
}
// 不區分大小寫
else {
strA = str3;
strB = str4;
}
// 向上查找的方式
if (upButton.isSelected()) {
// 文本未選中内容
if (jta.getSelectedText() == null)
k = strA.lastIndexOf(strB, jta.getCaretPosition());
// 文本已選中内容
else
k = strA.lastIndexOf(strB, jta.getCaretPosition() - strB.length() - 1);
// 查找未結束,繼續向上查找
if (k != -1) {
jta.setCaretPosition(k);
jta.select(k, k + strB.length());
}
// 查找結束,彈出錯誤視窗
else
JOptionPane.showMessageDialog(null, "找不到" + " “ " + findField.getText() + " ” ", "查找",
JOptionPane.INFORMATION_MESSAGE);
} // end 向上查找
// 向下查找的方式
else if (downButton.isSelected()) {
// 文本未選中内容
if (jta.getSelectedText() == null)
k = strA.lastIndexOf(strB, jta.getCaretPosition());
// 文本已選中内容
else
k = strA.lastIndexOf(strB, jta.getCaretPosition() - strB.length() + 1);
// 查找未結束,繼續向下查找
if (k != -1) {
jta.setCaretPosition(k);
jta.select(k, k + strB.length());
}
// 查找結束,彈出錯誤視窗
else
JOptionPane.showMessageDialog(null, "找不到" + " “ " + findField.getText() + " ” ", "查找",
JOptionPane.INFORMATION_MESSAGE);
} // end 向下查找
}// end actionPerformed
}// end ActionListener
);// end addActionListener
// 添加替換按鈕的監聽器(内部類的形式)
replaceButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int k = 0;
String str1, str2, str3, str4, str5, strA, strB;
str1 = jta.getText();
str2 = findField.getText();
str3 = str1.toUpperCase();
str4 = str2.toUpperCase();
str5 = replaceField.getText();
// 區分大小寫
if (checkButton.isSelected()) {
strA = str1;
strB = str2;
}
// 不區分大小寫
else {
strA = str3;
strB = str4;
}
// 向上查找的方式
if (upButton.isSelected()) {
// 文本未選中内容
if (jta.getSelectedText() == null)
k = strA.lastIndexOf(strB, jta.getCaretPosition());
// 文本已選中内容
else
k = strA.lastIndexOf(strB, jta.getCaretPosition() - strB.length() - 1);
// 查找未結束,繼續向上查找
if (k != -1) {
// 将所查找的内容替換并選中
jta.setCaretPosition(k);
jta.select(k, k + strB.length());
jta.replaceSelection(str5);
jta.select(k, k + str5.length());
}
// 查找替換結束,彈出錯誤視窗
else
JOptionPane.showMessageDialog(null, "找不到" + " “ " + findField.getText() + " ” ", "替換",
JOptionPane.INFORMATION_MESSAGE);
} // end 向上查找
// 向下查找的方式
else if (downButton.isSelected()) {
// 文本未選中内容
if (jta.getSelectedText() == null)
k = strA.indexOf(strB, jta.getCaretPosition());
// 文本已選中内容
else
k = strA.indexOf(strB, jta.getCaretPosition() - strB.length() + 1);
// 查找未結束,繼續向下查找
if (k != -1) {
// 将所查找的内容替換并選中
jta.setCaretPosition(k);
jta.select(k, k + strB.length());
jta.replaceSelection(str5);
jta.select(k, k + str5.length());
}
// 查找替換結束,彈出錯誤視窗
else
JOptionPane.showMessageDialog(null, "找不到" + " “ " + findField.getText() + " ” ", "替換",
JOptionPane.INFORMATION_MESSAGE);
}
}// end ActionPerformed
}// end ActionListener
);// end addActionListener
// 添加全部替換按鈕的監聽器(内部類)
replaceAllButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int k = 0;
String str1, str2, str3, str4, str5, strA, strB;
str1 = jta.getText();
str2 = findField.getText();
str3 = str1.toUpperCase();
str4 = str2.toUpperCase();
str5 = replaceField.getText();
// 區分大小寫
if (checkButton.isSelected()) {
strA = str1;
strB = str2;
}
// 不區分大小寫
else {
strA = str3;
strB = str4;
}
// 如果文本未選中内容,将文本中所查找的内容全部替換
if (jta.getSelectedText() != null)
jta.setText(
jta.getText().replace(jta.getSelectedText(), jta.getSelectedText().replace(strB, str5)));
// 如果文本有選中的内容,則在此内容内将所查找的内容全部替換
else
jta.setText(jta.getText().replace(strB, str5));
}// end actionPerformed
}// end ActionListener
);// end addActionListener
}// end replace
插入目前時間的功能
思路:在光标位置插入目前時間
// 擷取目前時間的方法
private void date() {
Calendar cal = Calendar.getInstance();
GregorianCalendar time = new GregorianCalendar();
// 獲得小時,分鐘,秒鐘并解決小于10的問題
String hour = "" + time.get(Calendar.HOUR_OF_DAY), min = "" + time.get(Calendar.MINUTE),
second = "" + time.get(Calendar.SECOND), year = "" + cal.get(Calendar.YEAR),
month = cal.get(Calendar.MONTH) + 1 + "", day = "" + cal.get(Calendar.DATE);
if (Integer.valueOf(hour).intValue() < 10)
hour = "0" + hour;
if (Integer.valueOf(min).intValue() < 10)
min = "0" + min;
if (Integer.valueOf(second).intValue() < 10)
second = "0" + second;
if (Integer.valueOf(month).intValue() < 10)
month = "0" + month;
if (Integer.valueOf(day).intValue() < 10)
day = "0" + day;
String str = "目前時間:" + hour + ":" + min + ":" + second + " " + year + "/" + month + "/" + day;
// 将滑鼠所指位置插入目前時間
jta.insert(str, jta.getCaretPosition());
}// end date```
自動換行功能
// 自動換行的方法
private void auto() {
// 判斷自動換行菜單按鈕是否被選中
if (!autoMenu.isSelected())
jta.setLineWrap(false);
else
jta.setLineWrap(true);
}// end auto
字型功能
思路:通過清單來設定文本框内容的字型、字形、大小。視窗截圖和代碼如下
// 自定義方法傳回字型大小(有偏差)
private int setSize(JTextField jtf, int size) {
switch (jtf.getText()) {
case "初号":size = 42;break;
case "小初":size = 36;break;
case "一号":size = 26;break;
case "小一":size = 24;break;
case "二号":size = 22;break;
case "小二":size = 18;break;
case "三号":size = 16;break;
case "小三":size = 15;break;
case "四号":size = 14;break;
case "小四":size = 12;break;
case "五号":size = 11;break;
case "小五":size = 9;break;
case "六号":size = 8;break;
case "小六":size = 7;break;
case "七号":size = 6;break;
case "八号":size = 5;break;
default:size = Integer.valueOf(jtf.getText());
}
return size;
}// end setSize
// 字型的方法
private void font() {
String fontName[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
String styleName[] = { "正常", "粗體", "斜體", "粗斜體" };
String sizeName[] = { "8", "9", "10", "11", "12", "14", "16", "18", "20", "22", "24", "26", "28", "36", "48",
"72", "初号", "小初", "一号", "小一", "二号", "小二", "三号", "小三", "四号", "小四", "五号", "小五", "六号", "小六", "七号", "八号" };
String script[] = { "中文GB2312", "西歐語言", "希臘語", "中歐字元" };
// 定義字型視窗所需的元件
JDialog fontDialog = new JDialog(this, "字型", false);
Container sizeCon = fontDialog.getContentPane();
JLabel fontLabel = new JLabel("字型(F)");
JLabel styleLabel = new JLabel("字形(Y)");
JLabel sizeLabel = new JLabel("大小(S)");
JLabel scriptLable = new JLabel("腳本(R)");
JLabel nullLabel = new JLabel();
JTextField egjtf = new JTextField(20);
JTextField fontField = new JTextField(15);
JTextField styleField = new JTextField(15);
JTextField sizeField = new JTextField(5);
JComboBox scriptBox = new JComboBox(script);
JList fontList = new JList(fontName);
JList styleList = new JList(styleName);
JList sizeList = new JList(sizeName);
JScrollPane jsp1 = new JScrollPane(fontList);
JScrollPane jsp2 = new JScrollPane(styleList);
JScrollPane jsp3 = new JScrollPane(sizeList);
JButton bt1 = new JButton("确定");
JButton bt2 = new JButton("取消");
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
JPanel p4 = new JPanel();
JPanel p5 = new JPanel();
JPanel p6 = new JPanel();
JPanel p7 = new JPanel();
JPanel p8 = new JPanel();
JPanel p9 = new JPanel();
JPanel p10 = new JPanel();
// 設定布局管理器
p1.setLayout(new BorderLayout());
p2.setLayout(new BorderLayout());
p3.setLayout(new BorderLayout());
p4.setLayout(new FlowLayout(20, 20, FlowLayout.CENTER));
p5.setLayout(new BorderLayout());
p6.setLayout(new BorderLayout(10, 10));
p7.setLayout(new FlowLayout(10, 10, FlowLayout.CENTER));
p8.setLayout(new BorderLayout(10, 10));
p9.setLayout(new BorderLayout(330, 20));
// 添加元件
p1.add(fontLabel, BorderLayout.NORTH);
p1.add(fontField, BorderLayout.CENTER);
p1.add(jsp1, BorderLayout.SOUTH);
p2.add(styleLabel, BorderLayout.NORTH);
p2.add(styleField, BorderLayout.CENTER);
p2.add(jsp2, BorderLayout.SOUTH);
p3.add(sizeLabel, BorderLayout.NORTH);
p3.add(sizeField, BorderLayout.CENTER);
p3.add(jsp3, BorderLayout.SOUTH);
p4.add(p1);
p4.add(p2);
p4.add(p3);
p5.setBorder(BorderFactory.createTitledBorder("示例"));
p5.add(egjtf, BorderLayout.NORTH);
p5.add(nullLabel, BorderLayout.CENTER);
p6.add(scriptBox, BorderLayout.CENTER);
p6.add(scriptLable, BorderLayout.NORTH);
p10.add(p6);
p7.add(bt1);
p7.add(bt2);
p8.add(p5, BorderLayout.NORTH);
p8.add(p6, BorderLayout.CENTER);
p8.add(p7, BorderLayout.SOUTH);
p9.add(nullLabel, BorderLayout.WEST);
p9.add(p8, BorderLayout.CENTER);
sizeCon.add(p4, BorderLayout.NORTH);
sizeCon.add(p9, BorderLayout.CENTER);
// 設定示例文本框的屬性
egjtf.setFont(new Font(jta.getFont().getFontName(), jta.getFont().getStyle(), jta.getFont().getSize()));
egjtf.setHorizontalAlignment(JTextField.CENTER);
egjtf.setEnabled(false);
// 設定标簽,文本框,清單,下拉清單的字型屬性
fontLabel.setFont(new Font("宋體", 0, 20));
styleLabel.setFont(new Font("宋體", 0, 20));
sizeLabel.setFont(new Font("宋體", 0, 20));
fontField.setFont(new Font("宋體", 0, 20));
styleField.setFont(new Font("宋體", 0, 20));
sizeField.setFont(new Font("宋體", 0, 20));
fontList.setFont(new Font("宋體", 0, 20));
styleList.setFont(new Font("宋體", 0, 20));
sizeList.setFont(new Font("宋體", 0, 20));
scriptLable.setFont(new Font("宋體", 0, 20));
scriptBox.setFont(new Font("宋體", 0, 20));
// 設定視窗屬性
fontDialog.setVisible(true);
setEnabled(false);
fontDialog.setResizable(false);
fontDialog.setBounds(200, 200, 600, 480);
// 設定文本框的初始内容
fontField.setText(jta.getFont().getFontName());
egjtf.setText(jta.getFont().getFontName());
if (jta.getFont().getStyle() == Font.PLAIN)
styleField.setText("正常");
if (jta.getFont().getStyle() == Font.ITALIC)
styleField.setText("傾斜");
if (jta.getFont().getStyle() == Font.BOLD)
styleField.setText("粗體");
if (jta.getFont().getStyle() == Font.BOLD + Font.ITALIC)
styleField.setText("粗斜體");
// 以數字的形式設定初始字型大小文本框的内容
for (int i = 0; i < 100000; i++) {
if (jta.getFont().getSize() == i)
sizeField.setText(i + "");
}
// 添加下拉清單的監聽器(内部類的形式)
scriptBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
// 通過選擇下拉清單來設定示例文本框的内容
if (scriptBox.getSelectedIndex() == 0)
egjtf.setText(fontField.getText());
if (scriptBox.getSelectedIndex() == 1)
egjtf.setText("ABCYyZz");
if (scriptBox.getSelectedIndex() == 2)
egjtf.setText("AaBbAαBβ");
if (scriptBox.getSelectedIndex() == 3)
egjtf.setText("AaBbÁáÔô");
}// end itemStateChanged
}// end ItemListener
);// end addItemListener
fontField.selectAll();
fontList.setSelectedValue(jta.getFont().getFontName(), true);// 從清單中選擇指定的對象
// 添加字型清單的監聽器(内部類的形式)
fontList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
int size = 0;// 定義字型大小變量
fontField.setText(fontName[fontList.getSelectedIndex()]);// 将字型文本框内容變為所選字型名稱
// 選中字型文本框中的内容(有顔色)
fontField.requestFocus();
fontField.select(0, fontField.getText().length());
// 通過自定義的方法獲得字型大小并将示例文本框的字型設定為目标字型屬性
size = setSize(sizeField, size);
egjtf.setFont(new Font(fontField.getText(), styleList.getSelectedIndex(), size));
}// end valueChanged
}// end ListSelectionListener
);// end addListSelectionListener
// 添加字形清單的監聽器(内部類的形式)
styleList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
int size = 0;// 定義字型大小變量
styleField.setText((String) styleList.getSelectedValue());// 将字形文本框内容變為所選字形名稱
// 選中字型文本框中的内容(有顔色)
styleField.requestFocus();
styleField.select(0, styleField.getText().length());
// 通過自定義的方法獲得字型大小并将示例文本框的字型設定為目标字型屬性
size = setSize(sizeField, size);
egjtf.setFont(new Font(fontField.getText(), styleList.getSelectedIndex(), size));
}// end valueChanged
}// end ListSelectionListener
);// end addListSelectionListener
// 添加字型大小清單的監聽器(内部類的形式)
sizeList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
int size = 0;// 定義字型大小變量
sizeField.setText((String) sizeList.getSelectedValue());// 将字形文本框内容變為所選字型大小
// 選中字型文本框中的内容(有顔色)
sizeField.requestFocus();
sizeField.select(0, sizeField.getText().length());
// 通過自定義的方法獲得字型大小并将示例文本框的字型設定為目标字型屬性
size = setSize(sizeField, size);
egjtf.setFont(new Font(fontField.getText(), styleList.getSelectedIndex(), size));
}// end valueChanged
}// end ListSelectionListener
);// end addListSelectionListener
// 添加确定按鈕的監聽器
bt1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int size = 0, len = 0;// 定義字型大小和fontName的長度變量
String fontname = fontField.getText(), style = styleField.getText();// 定義fontname和字形字元串變量
try {
size = setSize(sizeField, size);// 通過自定義的方法獲得字型大小
// 通過for循環判斷字型文本框的内容在系統中是否存在,存在則跳出循環,不存在則至循環結束
for (len = 0; len < fontName.length; len++) {
if (fontname.equals(fontName[len]))
break;
}
// 如果if條件成立,即for循環完整的結束,抛出比對異常
if (len == fontName.length)
throw new InputMismatchException();
// 如果if條件成立,即字形文本框内容中的字形有誤,抛出比對異常
if (!(style.equals("正常") || style.equals("斜體") || style.equals("粗體") || style.equals("粗斜體")))
throw new InputMismatchException();
// 設定記事本文本框的字型屬性
jta.setFont(new Font(fontname, styleList.getSelectedIndex(), size));
// 設定完關閉字型視窗并将記事本視窗恢複可操作性
fontDialog.dispose();
setEnabled(true);
} // end try
catch (InputMismatchException em) {
// 如果字型名稱系統不存在,捕獲異常,彈出警告視窗
if (len == fontName.length)
JOptionPane.showMessageDialog(null, "沒有該名稱的字型" + "\n請從字型清單中選擇字型", "字型",
JOptionPane.WARNING_MESSAGE);
// 如果字形名稱輸入有誤,捕獲異常,彈出警告視窗
if (!(style.equals("正常") || style.equals("斜體") || style.equals("粗體") || style.equals("粗斜體")))
JOptionPane.showMessageDialog(null, "沒有該字形的字型" + "\n請從字形清單中選擇字形", "字型",
JOptionPane.WARNING_MESSAGE);
} // end catch
catch (NumberFormatException en) {
// 如果輸入的字型大小不是整數,捕獲異常,彈出警告視窗
JOptionPane.showMessageDialog(null, "“大小”必須是整數", "字型", JOptionPane.WARNING_MESSAGE);
} // end catch
}// end actionPerformed
}// end ActionEvent
);// end addActionEvent
// 添加取消按鈕的監聽器(内部類的形式)
bt2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 不設定字型,關閉字型視窗并将記事本視窗恢複可操作性
fontDialog.dispose();
setEnabled(true);
}// end actionPerformed
}// end ActionListener
);// end addActionListener
// 添加字型文本框的監聽器(内部類的形式)
fontField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int size = 0, len = 0;// 定義字型大小和fontName的長度變量
String fontname = fontField.getText(), style = styleField.getText();// 定義fontname和字形字元串變量
try {
size = setSize(sizeField, size);// 通過自定義的方法獲得字型大小
// 通過for循環判斷字型文本框的内容在系統中是否存在,存在則跳出循環,不存在則至循環結束
for (len = 0; len < fontName.length; len++) {
if (fontname.equals(fontName[len]))
break;
}
// 如果if條件成立,即for循環完整的結束,抛出比對異常
if (len == fontName.length)
throw new InputMismatchException();
// 如果if條件成立,即字形文本框内容中的字形有誤,抛出比對異常
if (!(style.equals("正常") || style.equals("斜體") || style.equals("粗體") || style.equals("粗斜體")))
throw new InputMismatchException();
// 設定記事本文本框的字型屬性
jta.setFont(new Font(fontname, styleList.getSelectedIndex(), size));
// 設定完關閉字型視窗并将記事本視窗恢複可操作性
fontDialog.dispose();
setEnabled(true);
} // end try
catch (InputMismatchException em) {
// 如果字型名稱系統不存在,捕獲異常,彈出警告視窗
if (len == fontName.length)
JOptionPane.showMessageDialog(null, "沒有該名稱的字型" + "\n請從字型清單中選擇字型", "字型",
JOptionPane.WARNING_MESSAGE);
// 如果字形名稱輸入有誤,捕獲異常,彈出警告視窗
if (!(style.equals("正常") || style.equals("斜體") || style.equals("粗體") || style.equals("粗斜體")))
JOptionPane.showMessageDialog(null, "沒有該字形的字型" + "\n請從字形清單中選擇字形", "字型",
JOptionPane.WARNING_MESSAGE);
} // end catch
catch (NumberFormatException en) {
// 如果輸入的字型大小不是整數,捕獲異常,彈出警告視窗
JOptionPane.showMessageDialog(null, "“大小”必須是整數", "字型", JOptionPane.WARNING_MESSAGE);
} // end catch
}// end actionPerformed
}// end ActionEvent
);// end addActionEvent
// 添加字形文本框的監聽器(内部類的形式)
styleField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int size = 0, len = 0;// 定義字型大小和fontName的長度變量
String fontname = fontField.getText(), style = styleField.getText();// 定義fontname和字形字元串變量
try {
size = setSize(sizeField, size);// 通過自定義的方法獲得字型大小
// 通過for循環判斷字型文本框的内容在系統中是否存在,存在則跳出循環,不存在則至循環結束
for (len = 0; len < fontName.length; len++) {
if (fontname.equals(fontName[len]))
break;
}
// 如果if條件成立,即for循環完整的結束,抛出比對異常
if (len == fontName.length)
throw new InputMismatchException();
// 如果if條件成立,即字形文本框内容中的字形有誤,抛出比對異常
if (!(style.equals("正常") || style.equals("斜體") || style.equals("粗體") || style.equals("粗斜體")))
throw new InputMismatchException();
// 設定記事本文本框的字型屬性
jta.setFont(new Font(fontname, styleList.getSelectedIndex(), size));
// 設定完關閉字型視窗并将記事本視窗恢複可操作性
fontDialog.dispose();
setEnabled(true);
} // end try
catch (InputMismatchException em) {
// 如果字型名稱系統不存在,捕獲異常,彈出警告視窗
if (len == fontName.length)
JOptionPane.showMessageDialog(null, "沒有該名稱的字型" + "\n請從字型清單中選擇字型", "字型",
JOptionPane.WARNING_MESSAGE);
// 如果字形名稱輸入有誤,捕獲異常,彈出警告視窗
if (!(style.equals("正常") || style.equals("斜體") || style.equals("粗體") || style.equals("粗斜體")))
JOptionPane.showMessageDialog(null, "沒有該字形的字型" + "\n請從字形清單中選擇字形", "字型",
JOptionPane.WARNING_MESSAGE);
} // end catch
catch (NumberFormatException en) {
// 如果輸入的字型大小不是整數,捕獲異常,彈出警告視窗
JOptionPane.showMessageDialog(null, "“大小”必須是整數", "字型", JOptionPane.WARNING_MESSAGE);
} // end catch
}// end actionPerformed
}// end ActionEvent
);// end addActionEvent
// 添加字型大小文本框的監聽器(内部類的形式)
sizeField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int size = 0, len = 0;// 定義字型大小和fontName的長度變量
String fontname = fontField.getText(), style = styleField.getText();// 定義fontname和字形字元串變量
try {
size = setSize(sizeField, size);// 通過自定義的方法獲得字型大小
// 通過for循環判斷字型文本框的内容在系統中是否存在,存在則跳出循環,不存在則至循環結束
for (len = 0; len < fontName.length; len++) {
if (fontname.equals(fontName[len]))
break;
}
// 如果if條件成立,即for循環完整的結束,抛出比對異常
if (len == fontName.length)
throw new InputMismatchException();
// 如果if條件成立,即字形文本框内容中的字形有誤,抛出比對異常
if (!(style.equals("正常") || style.equals("斜體") || style.equals("粗體") || style.equals("粗斜體")))
throw new InputMismatchException();
// 設定記事本文本框的字型屬性
jta.setFont(new Font(fontname, styleList.getSelectedIndex(), size));
// 設定完關閉字型視窗并将記事本視窗恢複可操作性
fontDialog.dispose();
setEnabled(true);
} // end try
catch (InputMismatchException em) {
// 如果字型名稱系統不存在,捕獲異常,彈出警告視窗
if (len == fontName.length)
JOptionPane.showMessageDialog(null, "沒有該名稱的字型" + "\n請從字型清單中選擇字型", "字型",
JOptionPane.WARNING_MESSAGE);
// 如果字形名稱輸入有誤,捕獲異常,彈出警告視窗
if (!(style.equals("正常") || style.equals("斜體") || style.equals("粗體") || style.equals("粗斜體")))
JOptionPane.showMessageDialog(null, "沒有該字形的字型" + "\n請從字形清單中選擇字形", "字型",
JOptionPane.WARNING_MESSAGE);
} // end catch
catch (NumberFormatException en) {
// 如果輸入的字型大小不是整數,捕獲異常,彈出警告視窗
JOptionPane.showMessageDialog(null, "“大小”必須是整數", "字型", JOptionPane.WARNING_MESSAGE);
} // end catch
}// end actionPerformed
}// end ActionEvent
);// end addActionEvent
// 設定字型視窗右上角關閉按鈕的監聽器(内部類)
fontDialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
setEnabled(true);// 關閉字型視窗并恢複記事本視窗的可操作性
}// end windowClosing
}// end WindowAdapter
);// end addWindowListener
}// end font
總結:
1.GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();方法用于傳回本地的字型名稱(以字元串的形式)。
2.setHorizontalAlignment()方法用于設定文本對齊方式
狀态欄功能
思路:激活狀态欄時,文本域下方顯示光标位置的狀态并顯示總字數。
核心代碼
int caretpos = jta.getCaretPosition();// 傳回文本元件的文本插入符的位置
int lineNum = jta.getLineOfOffset(caretpos);// 将元件文本中的偏移量轉換為行号(從0開始)
int columnNum = caretpos - jta.getLineStartOffset(lineNum);// 文本插入符位置減去給定行起始處的偏移量就是列數
lineNum += 1;// 傳回文本的行數(從1開始)
setText("第" + lineNum + "行,第" + columnNum + "列 " + "共" + num + "字");
截圖和代碼如下
// 狀态欄的方法
private void state() {
// 狀态欄被激活
if (stateMenu.isSelected()) {
try {
// 激活時顯示初始狀态欄資訊
jla.setText("第" + String.valueOf(jta.getLineOfOffset(jta.getCaretPosition()) + 1) + "行,第"
+ String.valueOf(jta.getCaretPosition() - jta.getLineStartOffset(jta.getCaretPosition()))
+ "列 " + "共" + jta.getText().length() + "字");
} // end try
catch (BadLocationException e) {
System.out.println();
} // end catch
jta.addCaretListener(new CaretListener() {
@Override
public void caretUpdate(CaretEvent e) {
int lineNum = 0, columnNum = 0, num = jta.getText().length();
try {
int caretpos = jta.getCaretPosition();// 傳回文本元件的文本插入符的位置
lineNum = jta.getLineOfOffset(caretpos);// 将元件文本中的偏移量轉換為行号(從0開始)
columnNum = caretpos - jta.getLineStartOffset(lineNum);// 文本插入符位置減去給定行起始處的偏移量就是列數
lineNum += 1;// 傳回文本的行數(從1開始)
jla.setText("第" + lineNum + "行,第" + columnNum + "列 " + "共" + num + "字");
} // end try
catch (BadLocationException ex) {
ex.printStackTrace();
} // end catch
}// end caretUpdate
}// end CaretListener
);// end addCaretListener
jla.setVisible(true);// 設定狀态欄可視化
} // end if
// 屏蔽狀态欄
else
jla.setVisible(false);
}// end state
}// end noteBookDemo
主方法
public class noteBook {
public static void main(String[] args) {
new noteBookDemo();
}// end main
}// end noteBook
以上便是筆者對本次寫記事本代碼過程的總結。其中的不足就是有一些彈出視窗的快捷鍵未實作以及一些功能有一點bug。另外,筆者在這個寫代碼的過程中可以說是受益匪淺了嘻嘻!