zoukankan      html  css  js  c++  java
  • 简单文本编辑器

    一、前言

      聚天地之灵气,集日月之精华!一个简单的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;
        }
    
        @Override
        public String toString() {
            return familyIndex + " " + sizeIndex + " " + styleIndex + " " + colorIndex + " 
    " +
                    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;//选择字体的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;
        }
    }  
    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() {
        @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();
         }
    }
    View Code
  • 相关阅读:
    另一种阶乘问题
    韩信点兵
    java字符串大小写转换
    实现对字符串数组{"Allen","Smith","James","Martin","Ford"} 求得包含字母a的所有的名字
    将一维数组中的0去掉,不为0的项存入一个新的数组中
    hibernate -- HQL语句总结
    oracle intersect 取交集
    Spring中applicationContext.xml的bean里的id和name属性区别
    spring 源码分析
    python爬虫
  • 原文地址:https://www.cnblogs.com/hujunzheng/p/5232125.html
Copyright © 2011-2022 走看看