使用JAVA模拟記事本
學校老師叫用java swing寫一個記事本,雖然java窗體不是java的強項,但還是可以作為練習熟悉一下的。
因為記事本這種單一的小東西,是以不需要什麼耦合不需要太低,雖然背離了低耦合,但是寫起來是相當友善
按win7模拟出來的記事本。
大體把所需類分為如下:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX6FEVPNTVE50dNpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jMxQzM0QzM4EzMyUDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
1,文本域建立與功能
2,編輯菜單功能
3,檔案菜單功能
3,格式菜單功能
4,幫助菜單功能
5,檢視菜單功能
6,總菜單
7,主函數(主界面)
8,系統剪切闆工具
9,狀态欄
10,界面設定
界面參考如下
下面進入正式代碼分析(使用部分代碼分析,具體代碼後面用連結給出):
1,檔案
需要一個儲存路徑的變量,然後文本域裡也需要有一個變量判斷是否被修改過
建立:
這裡需要判斷檔案是否被修改過,如果有,詢問使用者是否儲存,然後再操作,如果沒有,直接清空文本域類容與清空儲存的路徑
if (CreateText.isChangeT()) {
int change = JOptionPane.showConfirmDialog(null, "是否将儲存更改", "記事本",
0);
switch (change) {
case JOptionPane.YES_NO_OPTION:
if (textpath == null) {
FileTool.setSave("儲存");
} else {
FileTool.setPreserve();
}
CreateText.getJTexts().setText("");
textpath = null;
CreateText.setChangeT(false);
break;
case JOptionPane.CLOSED_OPTION:
break;
case JOptionPane.NO_OPTION:
CreateText.getJTexts().setText("");
textpath = null;
CreateText.setChangeT(false);
break;
default:
break;
}
} else {
CreateText.getJTexts().setText("");
textpath = null;
CreateText.setChangeT(false);
}
打開:
就是一個流,但是要先判斷文本域裡的類容是否被修改過,如果有,就詢問使用者是否儲存,然後再實作用檔案選擇器選擇路徑讀取的操作,打開後,要把打開的路徑替換原來的儲存路徑,然後文本是否修改改為否
JFileChooser jfc = new JFileChooser(".");
FileFilter ff = new FileNameExtensionFilter("文本文檔(*.txt)", "txt");
jfc.setAcceptAllFileFilterUsed(false);
jfc.setFileFilter(ff);
if (jfc.showDialog(null, null) == 0) {
CreateText.getJTexts().setText("");
textpath = jfc.getSelectedFile().getAbsolutePath();
Notepad.getJf().setTitle(textpath);
try {
InputStream input = new BufferedInputStream(
new FileInputStream(textpath));
byte[] by = new byte[1024];
int len = input.read(by);
while (len != -1) {
CreateText.getJTexts().append(
new String(by, 0, len));
len = input.read(by);
}
input.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
CreateText.setChangeT(false);
儲存與另存為:
另存為多實作一個重新選擇路徑存儲,這個存儲不替換儲存的路徑。
儲存就是直接安已經儲存的路徑存儲,如果沒有儲存的路徑,就打開路徑選擇器選擇一個路徑,下面提供儲存的代碼(使用的緩沖流)
StringBuffer str = new StringBuffer();
try {
OutputStream out = new BufferedOutputStream(new FileOutputStream(
textpath));
String[] lines = CreateText.getJTexts().getText().split("\n");
for(int i = 0;i < lines.length;i++)
{
System.out.println(lines[i]);
str.append(lines[i] + "\r\n");
}
out.write(str.toString().getBytes("utf-8"));
out.close();
CreateText.setChangeT(false);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
頁面設定與列印:
由于不好測試,就實作了一個java自帶的列印機。
頁面設定也剛好帶入在裡面,頁面設定使用Robot實作模拟快捷鍵跳轉到頁面設定裡(暫時沒想到好的辦法,這種方法也有個小bug,有可能切換失敗,可以額外用一個線程,在幾十毫秒後再使用虛拟按鍵,效果應該會好很多)<—歡迎大神提出意見
private static final void setPrintf(boolean whether) {
PrinterJob print = PrinterJob.getPrinterJob();
HashPrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();
if(whether)
{
Robot robot = null;
try {
robot = new Robot();//建立Robot對象
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(KeyEvent.VK_S);
robot.keyRelease(KeyEvent.VK_S);
robot.keyRelease(KeyEvent.VK_ALT);
}
print.printDialog(attr);
}
退出:
這個就不用說了,再詢問使用者是否儲存後,直接System.exit(0)
2,編輯
文本域發生改變時判斷是否可用,撤銷的稍稍特殊下面再說,剪切,複制,删除是要選中的東西有類容才能可用
撤銷:
使用UndoManager實作,關聯文本域後,用canUndo()方法來看是否可以撤銷,如果可以,就把撤銷變為可用,撤銷的方法是undo()
剪切,複制,粘貼,删除:
前三個文本域自帶有方法,在有文字被選中後,這幾個變為可用,然後分别用cut(),copy(),paste()方法來實作前三個,
删除操作由于沒有自帶的方法,就用Robot來模拟Delete鍵
下面提供,這四個選項,啥時候可用與不可用的事件方法
jta.addCaretListener(new CaretListener() {
// 文本框類容變動事件
@Override
public void caretUpdate(CaretEvent arg0) {
// TODO Auto-generated method stub
getsetPosition();
if (undomg.canUndo()) {
MenuBar.getBjs(0).setEnabled(true);
} else {
MenuBar.getBjs(0).setEnabled(false);
}
if (ShearPlate.getCbt() != null) {
MenuBar.getBjs(3).setEnabled(true);
} else {
MenuBar.getBjs(3).setEnabled(false);
}
if(!"".equals(jta.getText()))
{
MenuBar.getBjs(5).setEnabled(true);
MenuBar.getBjs(6).setEnabled(true);
}
else
{
MenuBar.getBjs(5).setEnabled(false);
MenuBar.getBjs(6).setEnabled(false);
}
if (jta.getSelectedText() != null) {
MenuBar.getBjs(1).setEnabled(true);
MenuBar.getBjs(2).setEnabled(true);
MenuBar.getBjs(4).setEnabled(true);
} else {
MenuBar.getBjs(1).setEnabled(false);
MenuBar.getBjs(2).setEnabled(false);
MenuBar.getBjs(4).setEnabled(false);
}
}
});
查詢,查找下一個,替換:
這幾個都是息息相關的,建立兩個對話框,其中一個是查詢的,一個是查找下一個,一個是替換
查找與替換都是根據光标所在位置來操作,其中替換的操作是需要選中字元來執行替換
下面是兩個窗體預覽
裡面有類容時,這兩個選項才可用,當查找類容有類容時按鈕才可用,然後就是對文本域裡的類容一系列操作,光标定位,然後由光标向上,向下查找,選中查找的類容,替換的時候就替換選中的類容,區分大小寫這些,也是字元串的操作之一,記不起來查查API就有了,下面提供查詢的代碼,,替換就用replace實作,代碼差異不大,代碼太多,不一一展示。
String strb = CreateText.getJTexts().getText();
int len = CreateText.getJTexts().getCaretPosition();
int max = CreateText.getJTexts().getText().length();
String str;
int ch;
String rep = reps;
if (upandfl) {
rep = rep.toLowerCase();
strb = strb.toLowerCase();
}
if (lefrig) {
str = strb.substring(len, max);
ch = str.indexOf(rep);
} else {
str = strb.substring(0, len - 1);
ch = str.lastIndexOf(rep);
}
int scope = rep.length();
if (ch >= 0 && ch < max) {
if (lefrig)
CreateText.getJTexts().select(len + ch, len + ch + scope);
else
CreateText.getJTexts().select(ch, ch + scope);
} else {
JOptionPane.showConfirmDialog(null, "未找到" + reps, "記事本", 0);
}
轉到與全選:
轉到我沒寫,是以我禁用了這個選項,轉到的實作思想就是,當有類容時,變為可用,再把光标定位到所輸入的行數
全選文本域自帶有方法selectAll()
時間/日期
擷取目前日期,格式化字元串後追加到文本域裡就行,追加是預設追加到光标位置的(又能偷懶一串代碼)
public static final String getDate() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd- HH:mm ");
Date date = new Date();
String str = sdf.format(date) + String.format("%tA", date);
return str;
}
3,格式
自動換行,文本域有自帶的,當自動換行時,取消橫向的滾動條,取消狀态欄禁用檢視裡的狀态欄顯示
字型需要引入本機有的字型名,由于java的swing組價支援html4與css2,是以選擇框樣式很是友善了
1,自動換行
直接給代碼,沒啥需要注意的,就是對窗體的改變與禁用隔壁檢視的狀态欄顯示
MenuBar.getGss(0).addActionListener(new ActionListener() {
// 自動換行功能
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (!CreateText.getJTexts().getLineWrap()) {
CreateText.getJTexts().setLineWrap(true);
StatusBar.getStatusJp().setVisible(false);
MenuBar.getCks().setEnabled(false);
CreateText.getJsp().setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
} else {
CreateText.getJTexts().setLineWrap(false);
StatusBar.getStatusJp().setVisible(true);
MenuBar.getCks().setEnabled(true);
CreateText.getJsp().setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
}
}
});
2,字型
先預覽
讀取電腦裡的字型的檔案名,也隻需要檔案名
GraphicsEnvironment fonts = GraphicsEnvironment
.getLocalGraphicsEnvironment();
String[] strfile = fonts.getAvailableFontFamilyNames();
存儲後放到JList裡,在把JList放到滾動面闆裡,當使用者選擇類容後,就把類容放置到上面的框裡,其他三個框也是相同操作
for(int i = 0;i < strfile.length;i++)strfile[i] = "<html><font "+strfile[i] + "\">"+strfile[i]+"</font></html>";
final JList jliw = new JList(strfile);
jliw.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent arg0) {
// TODO Auto-generated method stub
jtf[0].setText(clearHtml((String) jliw.getSelectedValue()));
jlcs.setFont(new Font((String) jtf[0].getText(),
map.get(jtf[1].getText()), Integer.parseInt(jtf[2].getText())));
}
});
jliw.setFont(new Font("微軟雅黑", Font.PLAIN, 14));
jspw.setViewportView(jliw);
jspw.setBounds(10, 70, 260, 200);
最後到确定的時候,就改變文本域裡的字型,字形,字号(預先要有三個變量存儲這三個值),下次點開的時候,三個文本框裡預設要顯示這三個值。
confirm.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
MyFont = jtf[0].getText();
Fontset = jtf[1].getText();
MyfontSize = jtf[2].getText();
CreateText.getJTexts().setFont(
new Font(MyFont, map.get(Fontset), Integer
.parseInt(MyfontSize)));
jd.dispose();
}
});
4,檢視
檢視裡就隻有可憐的一個狀态欄是否顯示(還有可能被隔壁的自動換行禁用),單擊他,判斷狀态欄是否顯示,顯示則隐藏,隐藏則顯示
MenuBar.getCks().addActionListener(new ActionListener() {
// 狀态欄事件
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (StatusBar.getStatusJp().isVisible()) {
StatusBar.getStatusJp().setVisible(false);
} else {
StatusBar.getStatusJp().setVisible(true);
}
}
});
5,幫助
這個就不說了。。寫兩個小提示框就成,我的檢視幫助沒寫,感覺沒必要,關于記事本倒是寫了一個,下面是效果,附帶一個文本域字型,字形,字号改變
不怎麼用java的窗體操作,感覺java強大的地方在于web和安卓,不過這個東西很練手,對字元串操作的掌控,參數的傳遞,對代碼全局的掌控,也需要點小小的邏輯(其實這是作業,順便發表一下)
代碼不足之處,歡迎指教