简单文本编辑器

v一、前言

  聚天地之灵气,集日月之精华!一个简单的java文本编辑器由此而生。毕设所需,很是无奈!

v二、界面预览

    

v三、实现思路

v  1.字体选择器的实现

  (1).字体类

  View Code

  (2).字体选择器

  View Code

v  2.编辑器的实现

  (1).字符串样式修饰类

    功能:主要是将JTextPane对应的Document的文本进行处理。使得不同类型的文本显示为不同的风格样式。由于这个编辑器是用来编辑java语言的,所以会对java中的关键字进行特殊的显示,使得关键字,注释,以及其他串的不同的显示。

  View Code

  (2).串节点

    功能:通过正则表达式,将JTextPane对应的Document的文本进行分割,记录每个分割串的起始位置,然后通过字符串修饰类(DecorateKeyWords)中的decorateStyleConstants方法根据每个分割串的起始位置对JTextPane对应的Document的文本进行不同风格样式的修饰。

  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();
     }
}
复制代码









本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/5232125.html,如需转载请自行联系原作者
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值