聚天地之靈氣,集日月之精華!一個簡單的java文本編輯器由此而生。畢設所需,非常無奈!java
(1).字體類node
class MyFont{ private Font font; private Color color; public Font getFont() { return font; } public void setFont(Font font) { this.font = font; } public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } //字體名稱索引 private int familyIndex = -1; //字體大小索引 private int sizeIndex = -1; //字體顏色索引 private int colorIndex = -1; //字體風格索引 private int styleIndex = -1; public int getFamilyIndex() { return familyIndex; } public int getSizeIndex() { return sizeIndex; } public int getColorIndex() { return colorIndex; } public int getStyleIndex() { return styleIndex; } public void setFamilyIndex(int familyIndex) { this.familyIndex = familyIndex; } public void setSizeIndex(int sizeIndex) { this.sizeIndex = sizeIndex; } public void setColorIndex(int colorIndex) { this.colorIndex = colorIndex; } public void setStyleIndex(int styleIndex) { this.styleIndex = styleIndex; } @Override public String toString() { return familyIndex + " " + sizeIndex + " " + styleIndex + " " + colorIndex + " \n" + font + " " + color; } }
(2).字體選擇器正則表達式
public class JFontChooser extends JPanel { //定義變量 private String current_fontName = "宋體";//當前的字體名稱,默認宋體. private int current_fontStyle = Font.PLAIN;//當前的字樣,默認常規. private int current_fontSize = 9;//當前字體大小,默認9號. private Color current_color = Color.BLACK;//當前字色,默認黑色. private Component parent;//彈出dialog的父窗體. private JDialog dialog;//用於顯示模態的窗體 private MyFont myfont;//帶有Color的字體. private JLabel lblFont;//選擇字體的LBL private JLabel lblStyle;//選擇字型的LBL private JLabel lblSize;//選擇字大小的LBL private JLabel lblColor;//選擇Color的label private JTextField txtFont;//顯示選擇字體的TEXT private JTextField txtStyle;//顯示選擇字型的TEXT private JTextField txtSize;//顯示選擇字大小的TEXT private JList lstFont;//選擇字體的列表. private JList lstStyle;//選擇字型的列表. private JList lstSize;//選擇字體大小的列表. private JComboBox cbColor;//選擇Color的下拉框. private JButton ok, cancel;//"肯定","取消"按鈕. private JScrollPane spFont; private JScrollPane spSize; private JLabel lblShow;//顯示效果的label. private JPanel showPan;//顯示框. private Map sizeMap;//字號映射表. private Map colorMap;//字着色映射表. //定義變量_結束________________ public JFontChooser(MyFont curFont) { //實例化變量 lblFont = new JLabel("字體:"); lblStyle = new JLabel("字型:"); lblSize = new JLabel("大小:"); lblColor = new JLabel("顏色:"); lblShow = new JLabel("Sample Test!", JLabel.CENTER); txtFont = new JTextField("宋體"); txtStyle = new JTextField("常規"); txtSize = new JTextField("9"); //取得當前環境可用字體. GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); String[] fontNames = ge.getAvailableFontFamilyNames(); lstFont = new JList(fontNames); //字形. lstStyle = new JList(new String[]{"常規", "斜休", "粗休", "粗斜休"}); //字號. String[] sizeStr = new String[]{ "8", "9", "10", "11", "12", "14", "16", "18", "20", "22", "24", "26", "28", "36", "48", "72", "初號", "小初", "一號", "小一", "二號", "小二", "三號", "小三", "四號", "小四", "五號", "小五", "六號", "小六", "七號", "八號" }; int sizeVal[] = {8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 42, 36, 26, 24, 22, 18, 16, 15, 14, 12, 11, 9, 8, 7, 6, 5}; sizeMap = new HashMap(); for (int i = 0; i < sizeStr.length; ++i) { sizeMap.put(sizeStr[i], sizeVal[i]); } lstSize = new JList(sizeStr); spFont = new JScrollPane(lstFont); spSize = new JScrollPane(lstSize); String[] colorStr = new String[]{ "黑色", "藍色", "深灰", "灰色", "綠色", "淺灰", "洋紅", "桔黃", "粉紅", "紅色", "白色", "黃色" }; Color[] colorVal = new Color[]{ Color.BLACK, Color.BLUE, Color.DARK_GRAY, Color.GRAY, Color.GREEN, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.WHITE, Color.YELLOW }; colorMap = new HashMap(); for (int i = 0; i < colorStr.length; i++) { colorMap.put(colorStr[i], colorVal[i]); } cbColor = new JComboBox(colorStr); showPan = new JPanel(); ok = new JButton("肯定"); cancel = new JButton("取消"); //實例化變量_結束 //佈局控件 this.setLayout(null);//不用佈局管理器. add(lblFont); lblFont.setBounds(12, 10, 30, 20); txtFont.setEditable(false); add(txtFont); txtFont.setBounds(10, 30, 155, 20); add(spFont); spFont.setBounds(10, 50, 155, 100); add(lblStyle); lblStyle.setBounds(175, 10, 30, 20); txtStyle.setEditable(false); add(txtStyle); txtStyle.setBounds(175, 30, 130, 20); lstStyle.setBorder(javax.swing.BorderFactory.createLineBorder(Color.gray)); add(lstStyle); lstStyle.setBounds(175, 50, 130, 100); add(lblSize); lblSize.setBounds(320, 10, 30, 20); txtSize.setEditable(false); add(txtSize); txtSize.setBounds(320, 30, 60, 20); add(spSize); spSize.setBounds(320, 50, 60, 100); add(lblColor); lblColor.setBounds(13, 170, 30, 20); add(cbColor); cbColor.setBounds(10, 195, 130, 22); cbColor.setMaximumRowCount(5); showPan.setBorder(javax.swing.BorderFactory.createTitledBorder("示例")); add(showPan); showPan.setBounds(150, 170, 230, 100); showPan.setLayout(new BorderLayout()); lblShow.setBackground(Color.white); showPan.add(lblShow); add(ok); ok.setBounds(10, 240, 60, 20); add(cancel); cancel.setBounds(80, 240, 60, 20); //佈局控件_結束 //事件 lstFont.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { current_fontName = (String) lstFont.getSelectedValue(); txtFont.setText(current_fontName); lblShow.setFont(new Font(current_fontName, current_fontStyle, current_fontSize)); } }); lstStyle.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { String value = (String) ((JList) e.getSource()).getSelectedValue(); if (value.equals("常規")) { current_fontStyle = Font.PLAIN; } if (value.equals("斜休")) { current_fontStyle = Font.ITALIC; } if (value.equals("粗休")) { current_fontStyle = Font.BOLD; } if (value.equals("粗斜休")) { current_fontStyle = Font.BOLD | Font.ITALIC; } txtStyle.setText(value); lblShow.setFont(new Font(current_fontName, current_fontStyle, current_fontSize)); } }); lstSize.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { current_fontSize = (Integer) sizeMap.get(lstSize.getSelectedValue()); txtSize.setText(String.valueOf(current_fontSize)); lblShow.setFont(new Font(current_fontName, current_fontStyle, current_fontSize)); } }); cbColor.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { current_color = (Color) colorMap.get(cbColor.getSelectedItem()); lblShow.setForeground(current_color); } }); ok.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { myfont = new MyFont(); myfont.setFont(new Font(current_fontName, current_fontStyle, current_fontSize)); myfont.setColor(current_color); myfont.setColorIndex(cbColor.getSelectedIndex()); myfont.setFamilyIndex(lstFont.getSelectedIndex()); myfont.setSizeIndex(lstSize.getSelectedIndex()); myfont.setStyleIndex(lstStyle.getSelectedIndex()); dialog.dispose(); dialog = null; } }); cancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { myfont = null; dialog.dispose(); dialog = null; } }); //事件_結束 if(curFont != null){ if(curFont.getFamilyIndex() != -1) { lstFont.setSelectedIndex(curFont.getFamilyIndex()); lstFont.ensureIndexIsVisible(curFont.getFamilyIndex()); } else { lstFont.setSelectedValue("宋體", true); } lstSize.setSelectedIndex(curFont.getSizeIndex()); lstSize.ensureIndexIsVisible(curFont.getSizeIndex()); lstStyle.setSelectedIndex(curFont.getStyleIndex()); lstStyle.ensureIndexIsVisible(curFont.getStyleIndex()); cbColor.setSelectedIndex(curFont.getColorIndex()); } } public MyFont showDialog(Frame parent, String title, int dx, int dy) { if(title == null) title = "Font"; dialog = new JDialog(parent, title,true); dialog.add(this); dialog.setResizable(false); dialog.setBounds(dx, dy, 400, 310); dialog.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { myfont = null; dialog.removeAll(); dialog.dispose(); dialog = null; } }); dialog.setVisible(true); return myfont; } }
(1).字符串樣式修飾類數組
功能:主要是將JTextPane對應的Document的文本進行處理。使得不一樣類型的文本顯示爲不一樣的風格樣式。因爲這個編輯器是用來編輯java語言的,因此會對java中的關鍵字進行特殊的顯示,使得關鍵字,註釋,以及其餘串的不一樣的顯示。編輯器
class DecorateKeyWords{ //java中的關鍵字 private static final String KEYWORDS[]={"abstract","assert","boolen","break","byte","case","catch","char","class","const", "continue","default","do","double","else","enum","extends","final","finally","float","for", "if","implements","import","instanceof","int","interface","long","native","new","package", "private","protected","public","return","short","static","strictfp","super","switch","synchrpnized", "this","throw","throws","transient","try","void","volatile","while" }; // 準備關鍵字 private static HashSet<String> keywords = new HashSet<String>(); public static void decorateStyleConstants(SimpleAttributeSet attr, Font font){ StyleConstants.setFontFamily(attr, font.getFamily()); StyleConstants.setFontSize(attr, font.getSize()); switch(font.getStyle()) { case Font.BOLD : StyleConstants.setBold(attr, true); break; case Font.ITALIC : StyleConstants.setItalic(attr, true); break; case Font.PLAIN : StyleConstants.setItalic(attr, false); StyleConstants.setBold(attr, false); break; case Font.BOLD | Font.ITALIC : StyleConstants.setItalic(attr, true); StyleConstants.setBold(attr, true); break; default : break; } } public static void decorateKeyWords(JTextPane tp, MyFont myFont) { //初始化關鍵字 for(int i = 0; i<KEYWORDS.length; i++) keywords.add(KEYWORDS[i]); // 對全部關鍵詞進行修飾顏色 String text = tp.getText().replaceAll("\\r", ""); StyledDocument doc = tp.getStyledDocument(); SimpleAttributeSet keyWordAttr = new SimpleAttributeSet(); StyleConstants.setForeground(keyWordAttr, Color.cyan); decorateStyleConstants(keyWordAttr, myFont.getFont()); SimpleAttributeSet otherWordAttr = new SimpleAttributeSet(); StyleConstants.setForeground(otherWordAttr, myFont.getColor()); decorateStyleConstants(otherWordAttr, myFont.getFont()); ListIterator<WordNode> iterator1 = split(text, "\\s|\\{|\\}|\\(|\\)|\\<|\\>|\\.|\\n"); while (iterator1.hasNext()) { WordNode wn = iterator1.next(); if (keywords.contains(wn.getWord())) { doc.setCharacterAttributes(wn.getLocation(), wn.getWord().length(), keyWordAttr, true); } else { doc.setCharacterAttributes(wn.getLocation(), wn.getWord().length(), otherWordAttr, true); } } // 對註釋行進行修飾不一樣的顏色 SimpleAttributeSet annotationAttr = new SimpleAttributeSet(); StyleConstants.setForeground(annotationAttr, Color.green); decorateStyleConstants(annotationAttr, myFont.getFont()); ListIterator<WordNode> iterator2 = split(text, "\\n"); boolean exegesis = false; // 是否加了/*的註釋 while (iterator2.hasNext()) { WordNode wn = iterator2.next(); if (wn.getWord().startsWith("//")) { doc.setCharacterAttributes(wn.getLocation(), wn.getWord() .length(), annotationAttr, true); } else if (wn.getWord().startsWith("/*") && wn.getWord().endsWith("*/")) { doc.setCharacterAttributes(wn.getLocation(), wn.getWord() .length(), annotationAttr, true); } else if (wn.getWord().startsWith("/*") && !wn.getWord().endsWith("*/")) { exegesis = true; doc.setCharacterAttributes(wn.getLocation(), wn.getWord() .length(), annotationAttr, true); } else if (!wn.getWord().startsWith("/*") && wn.getWord().endsWith("*/") && true == exegesis) { doc.setCharacterAttributes(wn.getLocation(), wn.getWord() .length(), annotationAttr, true); exegesis = false; } else if (true == exegesis) { doc.setCharacterAttributes(wn.getLocation(), wn.getWord() .length(), annotationAttr, true); } } } /** * 按照指定的多個字符進行字符串分割,如‘ ’或‘,’等 * @param str * 被分割的字符串 * @param regexs * 要分割所需的符號 * @return 包含WordNodeList對象的iterator */ private static ListIterator<WordNode> split(String str,String regex) { Pattern p = Pattern.compile(regex); Matcher m = p.matcher(str); List<WordNode> nodeList = new ArrayList(); int strStart = 0; // 分割單詞的首位置 String s; // 分割的單詞 WordNode wn; // StringNode節點 while (m.find()) { s = str.substring(strStart, m.start()); if (!s.equals(new String())) { wn = new WordNode(strStart, s); nodeList.add(wn); } strStart = m.start() + 1; } s = str.substring(strStart, str.length()); wn = new WordNode(strStart, s); nodeList.add(wn); return nodeList.listIterator(); } }
(2).串節點ide
功能:經過正則表達式,將JTextPane對應的Document的文本進行分割,記錄每一個分割串的起始位置,而後經過字符串修飾類(DecorateKeyWords)中的decorateStyleConstants方法根據每一個分割串的起始位置對JTextPane對應的Document的文本進行不一樣風格樣式的修飾。函數
class WordNode { private int location; private String word; public WordNode(int location, String str) { super(); this.location = location; this.word = str; } public int getLocation() { return location; } public String getWord() { return word; } }
(3).編輯器類工具
功能:文件的新建,文件的保存,文件的編輯;肯定JTextPane中光標的位置(行號和列號),顯示行號,字體樣式的選擇,從新設置新字體樣式。佈局
經過DocumentListener能夠監聽文檔的改變,刪除和插入的時候,調用字體選擇器對文檔的內容從新設置樣式,另外在文檔刪除的時候判斷是否行數減小,若是是,則更新行號面板的顯示。字體
textPane.getDocument().addDocumentListener(new DocumentListener() { @Override public void changedUpdate(DocumentEvent e) {} @Override public void insertUpdate(final DocumentEvent e) { new Thread(new Runnable() { @Override public void run() { DecorateKeyWords.decorateKeyWords(textPane, myFont); } }).start(); } @Override public void removeUpdate(DocumentEvent e) { new Thread(new Runnable() { @Override public void run() { String text; try { text = textPane.getDocument().getText(0, textPane.getDocument().getLength()).replaceAll("\\r", ""); Pattern pattern = Pattern.compile("\\n"); Matcher matcher = pattern.matcher(text); int lineRow = 1; while(matcher.find()){ //計算行數 ++lineRow; } while(lineRow < linePane.getComponentCount()) { --lineNum; linePane.remove(linePane.getComponentCount()-1); } linePane.updateUI(); } catch (BadLocationException ex) { ex.printStackTrace(); } finally { DecorateKeyWords.decorateKeyWords(textPane, myFont); } } }).start(); } }
經過CaretListener能夠監聽光標位置的變化,實時得到光標所在的行號和列號並顯示出來。
textPane.addCaretListener(new CaretListener() { @Override public void caretUpdate(CaretEvent e) { try { String text = textPane.getDocument().getText(0, e.getDot()).replaceAll("\\r", ""); Pattern pattern = Pattern.compile("\\n"); Matcher matcher = pattern.matcher(text); int lineRow = 1; int lastLineBeginPos = -1;//記錄文本中最後一行的開始的位置 while(matcher.find()){ //計算行數 ++lineRow; lastLineBeginPos = matcher.start();//獲得下一行光標所在的位置(根據上一行的換行符) } int lineCol = e.getDot() - lastLineBeginPos; //顯示行號和列號 caretStatusBar.setText("光標 " + lineRow + " : " + lineCol); } catch (BadLocationException ey) { ey.printStackTrace(); } } });
經過KeyListener能夠監聽按鍵的操做,若是是回車鍵,那麼爲行號面板增長新的行號!
textPane.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { super.keyPressed(e); if(e.getKeyCode() == KeyEvent.VK_ENTER) { //添加新的行號 addLineNum(); } } });
編輯器所有代碼以下
public class EditorDemo extends JFrame { public static final String MAX_LINE_NUM = "9999"; private JTextPane textPane = new JTextPane(); //文本窗格,編輯窗口 private JLabel timeStatusBar = new JLabel(); //時間狀態欄 private JLabel caretStatusBar = new JLabel(); //光標位置狀態欄 private JFileChooser filechooser = new JFileChooser(); //文件選擇器 private JPanel linePane = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0)); private int lineNum = 0; private MyFont myFont = null; private void initTextPaneDocument(){ textPane.getDocument().addDocumentListener(new DocumentListener() { @Override public void changedUpdate(DocumentEvent e) {} @Override public void insertUpdate(final DocumentEvent e) { new Thread(new Runnable() { @Override public void run() { DecorateKeyWords.decorateKeyWords(textPane, myFont); } }).start(); } @Override public void removeUpdate(DocumentEvent e) { new Thread(new Runnable() { @Override public void run() { String text; try { text = textPane.getDocument().getText(0, textPane.getDocument().getLength()).replaceAll("\\r", ""); Pattern pattern = Pattern.compile("\\n"); Matcher matcher = pattern.matcher(text); int lineRow = 1; while(matcher.find()){ //計算行數 ++lineRow; } while(lineRow < linePane.getComponentCount()) { --lineNum; linePane.remove(linePane.getComponentCount()-1); } linePane.updateUI(); } catch (BadLocationException ex) { ex.printStackTrace(); } finally { DecorateKeyWords.decorateKeyWords(textPane, myFont); } } }).start(); } }); } public EditorDemo() { //構造函數 super("簡單的文本編輯器"); //調用父類構造函數 //初始字體 myFont = new MyFont(); myFont.setColor(Color.black); myFont.setFont(new Font("宋體", Font.PLAIN, 24)); myFont.setSizeIndex(19); myFont.setStyleIndex(0); myFont.setColorIndex(0); Action[] actions = //Action數組,各類操做命令 { new NewAction(), new OpenAction(), new SaveAction(), new CutAction(), new CopyAction(), new PasteAction(), new NewFontStyle(), new AboutAction(), new ExitAction() }; textPane.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { super.keyPressed(e); if(e.getKeyCode() == KeyEvent.VK_ENTER) { //添加新的行號 addLineNum(); } } }); textPane.addCaretListener(new CaretListener() { @Override public void caretUpdate(CaretEvent e) { try { String text = textPane.getDocument().getText(0, e.getDot()).replaceAll("\\r", ""); Pattern pattern = Pattern.compile("\\n"); Matcher matcher = pattern.matcher(text); int lineRow = 1; int lastLineBeginPos = -1;//記錄文本中最後一行的開始的位置 while(matcher.find()){ //計算行數 ++lineRow; lastLineBeginPos = matcher.start();//獲得下一行光標所在的位置(根據上一行的換行符) } int lineCol = e.getDot() - lastLineBeginPos; //顯示行號和列號 caretStatusBar.setText("光標 " + lineRow + " : " + lineCol); } catch (BadLocationException ey) { ey.printStackTrace(); } } }); initTextPaneDocument(); setJMenuBar(createJMenuBar(actions)); //設置菜單欄 add(createJToolBar(actions), BorderLayout.NORTH); //增長工具欄 JPanel textBackPanel = new JPanel(new BorderLayout()); textBackPanel.add(linePane, BorderLayout.WEST);//增長行號面板 textBackPanel.add(textPane, BorderLayout.CENTER);//增長文本面板 add(new JScrollPane(textBackPanel), BorderLayout.CENTER); //文本窗格嵌入到JscrollPane JPanel statusPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 50, 0)); statusPane.add(caretStatusBar); statusPane.add(timeStatusBar); //初始化光標位置 caretStatusBar.setText("光標 1 : 1"); //初始化系統時間顯示 new Timer().schedule(new TimerTask() { @Override public void run() { Date now = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//能夠方便地修改日期格式 timeStatusBar.setText(dateFormat.format(now)); } }, 0, 1000); add(statusPane, BorderLayout.SOUTH); //增長狀態欄 FontMetrics fm = FontDesignMetrics.getMetrics(myFont.getFont()); //設置光標的大小 textPane.setFont(myFont.getFont()); //設置行數面板的寬度 linePane.setPreferredSize(new Dimension(fm.stringWidth(MAX_LINE_NUM), 0)); addLineNum(); setBounds(200, 100, 800, 500); //設置窗口尺寸 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //關閉窗口時退出程序 setVisible(true); //設置窗口可視 } private void addLineNum(){ //爲textPane添加行號 String numText = String.valueOf(++lineNum); int tmpNum = MAX_LINE_NUM.length() - (int)(Math.log10(lineNum*1.0)+1); String spaces = ""; while(tmpNum > 0){ spaces += " "; --tmpNum; } JLabel lineLabel = new JLabel(numText.replaceAll("(\\d+)", spaces+"$1"), JLabel.RIGHT); lineLabel.setForeground(Color.GRAY); lineLabel.setFont(myFont.getFont()); linePane.add(lineLabel); linePane.updateUI(); } private JMenuBar createJMenuBar(Action[] actions) { //建立菜單欄 JMenuBar menubar = new JMenuBar(); //實例化菜單欄 JMenu menuFile = new JMenu("文件"); //實例化菜單 JMenu menuEdit = new JMenu("編輯"); JMenu menuAbout = new JMenu("幫助"); menuFile.add(new JMenuItem(actions[0])); //增長新菜單項 menuFile.add(new JMenuItem(actions[1])); menuFile.add(new JMenuItem(actions[2])); menuFile.add(new JMenuItem(actions[7])); menuEdit.add(new JMenuItem(actions[3])); menuEdit.add(new JMenuItem(actions[4])); menuEdit.add(new JMenuItem(actions[5])); menuAbout.add(new JMenuItem(actions[6])); menubar.add(menuFile); //增長菜單 menubar.add(menuEdit); menubar.add(menuAbout); return menubar; //返回菜單欄 } private JToolBar createJToolBar(Action[] actions) { //建立工具條 JToolBar toolBar = new JToolBar(); //實例化工具條 for (int i = 0; i < actions.length; i++) { JButton bt = new JButton(actions[i]); //實例化新的按鈕 bt.setRequestFocusEnabled(false); //設置不須要焦點 toolBar.add(bt); //增長按鈕到工具欄 } return toolBar; //返回工具欄 } class NewFontStyle extends AbstractAction{ public NewFontStyle() { super("字體"); } @Override public void actionPerformed(ActionEvent e) { JFontChooser one = new JFontChooser(myFont); MyFont tmpFont = one.showDialog(null, "字體選擇器", textPane.getLocationOnScreen().x, textPane.getLocationOnScreen().y); if(tmpFont == null) return; myFont = tmpFont; //從新設置 textPane的字體,改變光標的大小 textPane.setFont(myFont.getFont()); FontMetrics fm = FontDesignMetrics.getMetrics(myFont.getFont()); //從新設置數字行數面板的寬度 linePane.setPreferredSize(new Dimension(fm.stringWidth(MAX_LINE_NUM), 0)); //從新設置行號的字體 for(int i=0; i < linePane.getComponentCount(); ++i) linePane.getComponent(i).setFont(myFont.getFont()); StyledDocument doc = textPane.getStyledDocument(); SimpleAttributeSet wordAttr = new SimpleAttributeSet(); DecorateKeyWords.decorateStyleConstants(wordAttr, myFont.getFont()); doc.setCharacterAttributes(0, doc.getLength(), wordAttr, false); } } class NewAction extends AbstractAction { //新建文件命令 public NewAction() { super("新建"); } public void actionPerformed(ActionEvent e) { textPane.setDocument(new DefaultStyledDocument()); //清空文檔 while(linePane.getComponentCount() > 1) linePane.remove(linePane.getComponent(linePane.getComponentCount()-1)); linePane.updateUI(); lineNum = 1; initTextPaneDocument(); } } class OpenAction extends AbstractAction { //打開文件命令 public OpenAction() { super("打開"); } public void actionPerformed(ActionEvent e) { int i = filechooser.showOpenDialog(EditorDemo.this); //顯示打開文件對話框 if (i == JFileChooser.APPROVE_OPTION) { //點擊對話框中打開選項 File f = filechooser.getSelectedFile(); //獲得選擇的文件 try { InputStream is = new FileInputStream(f); //獲得文件輸入流 textPane.read(is, "d"); //讀入文件到文本窗格 is.close(); is = new FileInputStream(f); LineNumberReader lnr = new LineNumberReader(new InputStreamReader(is)); lnr.skip(Long.MAX_VALUE); int newLineNum = lnr.getLineNumber()+1; lnr.close(); if(lineNum < newLineNum){ while(lineNum < newLineNum) addLineNum(); } else { while(lineNum > newLineNum && lineNum > 1){ linePane.remove(linePane.getComponentCount()-1); --lineNum; } linePane.updateUI(); } } catch (Exception ex) { ex.printStackTrace(); //輸出出錯信息 } } DecorateKeyWords.decorateKeyWords(textPane, myFont); initTextPaneDocument(); } } class SaveAction extends AbstractAction { //保存命令 public SaveAction() { super("保存"); } public void actionPerformed(ActionEvent e) { int i = filechooser.showSaveDialog(EditorDemo.this); //顯示保存文件對話框 if (i == JFileChooser.APPROVE_OPTION) { //點擊對話框中保存按鈕 File f = filechooser.getSelectedFile(); //獲得選擇的文件 try { FileOutputStream out = new FileOutputStream(f); //獲得文件輸出流 out.write(textPane.getText().getBytes()); //寫出文件 } catch (Exception ex) { ex.printStackTrace(); //輸出出錯信息 } } } } class ExitAction extends AbstractAction { //退出命令 public ExitAction() { super("退出"); } public void actionPerformed(ActionEvent e) { System.exit(0); //退出程序 } } class CutAction extends AbstractAction { //剪切命令 public CutAction() { super("剪切"); } public void actionPerformed(ActionEvent e) { textPane.cut(); //調用文本窗格的剪切命令 } } class CopyAction extends AbstractAction { //拷貝命令 public CopyAction() { super("拷貝"); } public void actionPerformed(ActionEvent e) { textPane.copy(); //調用文本窗格的拷貝命令 } } class PasteAction extends AbstractAction { //粘貼命令 public PasteAction() { super("粘貼"); } public void actionPerformed(ActionEvent e) { textPane.paste(); //調用文本窗格的粘貼命令 } } class AboutAction extends AbstractAction { //關於選項命令 public AboutAction() { super("關於"); } public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(EditorDemo.this, "簡單的文本編輯器演示"); //顯示軟件信息 } } public static void main(String[] args) { new EditorDemo(); } }