簡單文本編輯器

一、前言

  聚天地之靈氣,集日月之精華!一個簡單的java文本編輯器由此而生。畢設所需,很是無奈!

二、界面預覽

?? ?

三、實現思路

  1.字體選擇器的實現

  (1).字體類

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;}@Overridepublic String toString() {return familyIndex + " " + sizeIndex + " " + styleIndex + " " + colorIndex + " \n" +font + " " + color; }}
View Code

  (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;//選擇字體的LBLprivate JLabel lblStyle;//選擇字型的LBLprivate JLabel lblSize;//選擇字大小的LBLprivate JLabel lblColor;//選擇Color的labelprivate JTextField txtFont;//顯示選擇字體的TEXTprivate JTextField txtStyle;//顯示選擇字型的TEXTprivate JTextField txtSize;//顯示選擇字大小的TEXTprivate 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() {@Overridepublic void windowClosing(WindowEvent e) {myfont = null;dialog.removeAll();dialog.dispose();dialog = null;}});dialog.setVisible(true);return myfont;}
}  
View Code

  2.編輯器的實現

  (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();  }  
}
View Code

  (2).串節點

    功能:通過正則表達式,將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;  }  
}  
View Code

  (3).編輯器類

    功能:文件的新建,文件的保存,文件的編輯;確定JTextPane中光標的位置(行號和列號),顯示行號,字體樣式的選擇,重新設置新字體樣式。

    通過DocumentListener可以監聽文檔的改變,刪除和插入的時候,調用字體選擇器對文檔的內容重新設置樣式,另外在文檔刪除的時候判斷是否行數減少,如果是,則更新行號面板的顯示。

textPane.getDocument().addDocumentListener(new DocumentListener() {@Overridepublic void changedUpdate(DocumentEvent e) {}@Overridepublic void insertUpdate(final DocumentEvent e) {new Thread(new Runnable() {@Overridepublic void run() {DecorateKeyWords.decorateKeyWords(textPane, myFont);}}).start();}@Overridepublic void removeUpdate(DocumentEvent e) {new Thread(new Runnable() {  @Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic void changedUpdate(DocumentEvent e) {}@Overridepublic void insertUpdate(final DocumentEvent e) {new Thread(new Runnable() {@Overridepublic void run() {DecorateKeyWords.decorateKeyWords(textPane, myFont);}}).start();}@Overridepublic void removeUpdate(DocumentEvent e) {new Thread(new Runnable() {  @Overridepublic 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() {@Overridepublic void keyPressed(KeyEvent e) {super.keyPressed(e);if(e.getKeyCode() == KeyEvent.VK_ENTER) {//添加新的行號
                    addLineNum();}}});textPane.addCaretListener(new CaretListener() {@Overridepublic 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); //文本窗格嵌入到JscrollPaneJPanel statusPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 50, 0));statusPane.add(caretStatusBar);statusPane.add(timeStatusBar);//初始化光標位置caretStatusBar.setText("光標 1 : 1");//初始化系統時間顯示new Timer().schedule(new TimerTask() {@Overridepublic 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("字體");}@Overridepublic 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();}
}
View Code

?

轉載于:https://www.cnblogs.com/hujunzheng/p/5232125.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/531342.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/531342.shtml
英文地址,請注明出處:http://en.pswp.cn/news/531342.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

u-boot新增命令后出現data abort

&#xff08;一&#xff09;問題描述 u-boot下新增了一條update的命令&#xff0c;直接輸入update沒有報錯&#xff0c;但是輸入up按TAB鍵補全時發現出現data abort&#xff0c;而且輸入不支持的命令也會有data abort &#xff08;二&#xff09;解決方法 最開始我包含的頭…

sublime text學習

Ctrl / ---------------------注釋 Ctrl 滾動 --------------字體變大/縮小 Ctrl N-------------------新建 軟件右下角可以選擇文檔語法模式 Ctrl Shift P ------------------命令模式 命令&#xff1a; sshtml模糊匹配-----語法切換到html模式&#xff0c;同理所得&am…

core文件如何分析

目錄(一&#xff09;什么是coredump(二)coredump產生的條件&#xff08;1&#xff09;coredump產生主要原因&#xff1a;&#xff08;2&#xff09;如何生成coredump(三&#xff09;gdb使用(四&#xff09;實例調試coredump文件(五&#xff09;總結(一&#xff09;什么是coredu…

SpringMVC+FreeMarker

前言&#xff1a; 最近在學習SpringMVC&#xff0c;模板引擎用的是FreeMarker&#xff0c;之前沒有接觸過。利用SpringMVC開發其實還有許多的步驟&#xff0c;比如控制層&#xff0c;服務層&#xff0c;持久化層&#xff0c;實體等等&#xff0c;先弄了一個小demo來總結一下Spr…

SpringMVC那點事

一、SpringMVC返回json數據的三種方式 1、第一種方式是spring2時代的產物&#xff0c;也就是每個json視圖controller配置一個Jsoniew。 如&#xff1a;<bean id"defaultJsonView" class"org.springframework.web.servlet.view.json.MappingJacksonJsonView&q…

js學習內容的整理

1、jquery動態添加Table中的一行 function addTableRow(tableId){var html <tr>\......\</tr>";//行首插入一行if($(#tableId).find(tr).length 1){$(html).insertAfter($(#tableId).find(tr).eq(0));} else { $(html).insertBefore($(#tableId).find(tr).e…

(一)最鄰近插值python實現

這里寫目錄標題&#xff08;一&#xff09;原始圖像&#xff08;二&#xff09;最鄰近插值實現&#xff08;三&#xff09;python實現1. 安裝庫2. python程序編寫3. 效果4. 工程文件&#xff08;一&#xff09;原始圖像 &#xff08;二&#xff09;最鄰近插值實現 一般情況下我…

(二)雙線性插值python實現

這里寫目錄標題&#xff08;一&#xff09;原始圖像&#xff08;二&#xff09;雙線性插值原理&#xff08;三&#xff09;python實現1. 安裝庫2. python程序編寫3. 效果4. 工程文件&#xff08;一&#xff09;原始圖像 &#xff08;二&#xff09;雙線性插值原理 一般情況下我…

js self = this的解釋

Demo 1: function Person(){this.name hjzgg;this.age 24;this.show function(){alert(name " " age);}}var p new Person();p.show(); 錯誤&#xff1a;name 和 age都沒有定義。 Demo 2: function Person(){this.name hjzgg;this.age 24;this.show functio…

(三)圖像轉灰度圖Python實現

這里寫目錄標題&#xff08;一&#xff09;原始圖像&#xff08;二&#xff09;轉換原理&#xff08;三&#xff09;python實現1. 安裝庫2. python程序編寫3. 效果4. 工程文件&#xff08;一&#xff09;原始圖像 &#xff08;二&#xff09;轉換原理 &#xff08;三&#xff…

SD卡實例分析fat32文件系統

目錄 環境描述 分析過程 1.SD卡格式化 2.使用winhex打開sd卡 3.MBR分析 4.DBR分析

java泛型上下限

前言&#xff1a; java的泛型上下限不是很好理解&#xff0c;尤其像我這種菜雞。反反復復看了好幾遍了...&#xff0c;真是... 一、簡單的繼承體系 class Person{}class Student extends Person{}class Worker extends Person{} 二、泛型上限&#xff08;extends 關鍵字&#x…

基于matlab的步進電機仿真(一)

這里寫目錄標題環境準備基礎準備模型參數輸入和輸出仿真原理圖仿真資源環境準備 MatLab2021b 基礎準備 打開Matlab&#xff0c;在幫助文檔里面搜索step motor,我們這里選擇如下模型 該模型實現了一個通用的步進電機模型&#xff1a; 可變磁阻步進電機永磁或混合步進電機 …

java自定義類加載器

前言 java反射&#xff0c;最常用的Class.forName()方法。做畢設的時候&#xff0c;接收到代碼字符串&#xff0c;通過 JavaCompiler將代碼字符串生成A.class文件&#xff08;存放在classpath下&#xff0c;也就是eclipse項目中的bin目錄里&#xff09;&#xff0c;然后通過jav…

常用網址

MDN : 一個不錯的前端學習網站 https://developer.mozilla.org/zh-CN/  https://developer.mozilla.org/en-US/ CodePen 是一個網站前端設計開發平臺&#xff0c;是一個針對網站前端代碼設計的開發工具。 RunJS - 在線編輯、展示、分享、交流你的 JavaScript 代碼 : http://r…

repo介紹(一)

repo簡介 Repo 是我們以 Git 為基礎構建的代碼庫管理工具,可以組織多個倉庫的上傳和下載。它是由一系列的Python腳本組成&#xff0c;封裝了一系列的Git命令&#xff0c;用來統一管理多個Git倉庫 一個大型的項目可能由很多小的倉庫組合而成的&#xff0c;為了方便統一管理各個…

hash長度擴展攻擊

作為一個信息安全的人&#xff0c;打各個學校的CTF比賽是比較重要的&#xff01; 最近一個朋友發了道題目過來&#xff0c;發現有道題目比較有意思&#xff0c;這里跟大家分享下 這串代碼的大致意思是&#xff1a; 這段代碼首先引入了一個名為"flag.php"的文件&am…

repo介紹(二)

這篇文章來實例操作 安裝repo&#xff0c;參考repo介紹這一節創建repo存放default.xml 的git倉庫 初始化repo&#xff0c;repo init -u https://gitee.com/angerial/repo-test.git 這個時候會在當前目錄生成如下文件 參考repo組成&#xff0c;修改.repo/manifest.xml,這里我的…

springmvc環境搭建以及常見問題解決

1.新建maven工程 a) 打開eclipse&#xff0c;file->new->project->Maven->Maven Project b) 下一步 c) 選擇創建的工程為webapp&#xff0c;下一步 d) 填寫項目的group id和artifact id。一般情況下&#xff0c;group id寫域名的倒序&#xff0c;artifact id…

eclipse build workspace太慢或者 js出錯問題解決

1.js文件錯誤解決辦法 右鍵項目->properties->Builders(注&#xff1a;JavaScript Validator也會引起 build workspace太慢) 2.Eclipse 一直不停 building workspace完美解決總結&#xff08;來自: http://blog.163.com/shadow_wolf/blog/static/18346909720145279519222…