• JavaSwing实现的文本比较软件


    先看效果:截图1

    截图2:

    实现思路:

     1、界面UI设计

    2、功能点 : a 打开文件进行比较    b 粘贴内容进去比较   c 提示帮助  d 窗口可以任意拖动

    3、文本比较算法

     java类 :

            MainUI 类实现界面设计       Read_File 类实现文件读取      DNASequence 类文本比较算法

     

    项目结构:

    源代码:

    Star.java

    import javax.swing.text.BadLocationException;
    import javax.swing.text.Document;
    import javax.swing.text.SimpleAttributeSet;
    import javax.swing.text.StyleConstants;
    
    public class Star
    {
        public static void main(String args[]) throws BadLocationException
        {
            //初始化界面
            Windowm windowm = new Windowm();
            
            
            //属性设置
            SimpleAttributeSet attrset = new SimpleAttributeSet();
            //字体大小
            StyleConstants.setFontSize(attrset,16);
            //获取JTextPane对象
            Document docs1=windowm.text1.getDocument();
            //设置初次显示文本
            docs1.insertString(docs1.getLength(), "手动输入或者选择文件打开", attrset);        
            Document docs2=windowm.text2.getDocument();
            docs2.insertString(docs2.getLength(), "手动输入输入或者选择文间打开
    点击核对试试
    红色表示错误字符
    蓝色表示多余或缺失字符", attrset);
        }
    }
    View Code

    MainUI.java

    import algorithm.DNASequence;
    import open_file.Read_File;
    
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.ComponentAdapter;
    import java.awt.event.ComponentEvent;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.io.File;
    import javax.swing.*;
    import javax.swing.text.Document;
    import javax.swing.text.SimpleAttributeSet;
    import javax.swing.text.StyleConstants;
    
    class Windowm extends JFrame
    {
        String path1;//第一个文件目录
        String path2;//第二个文件目录
        String File1;//第一个文件
        String File2;//第二个文件
        int point;//保存当前活动窗口
        
        private static final long serialVersionUID = 1L;
        JPanel myPanel1 = new JPanel();//面板1.1
        JPanel myPanel2 =new JPanel();//面板2.1
        JPanel myPanel3 =new JPanel();//面板3
        JPanel myPanel4 =new JPanel();//面板4
        JTextPane text1=new JTextPane();
        JTextPane text2=new JTextPane();
        
        JButton bt1 = new JButton("打开文档1");
        JButton bt2 = new JButton("打开文档2");
        JButton bt3 = new JButton("核对");
       
        JPopupMenu jm = new JPopupMenu();//右键菜单
        JMenuItem copy = new JMenuItem("复制");//菜单项
        JMenuItem path = new JMenuItem("粘贴");  
        JMenuItem cut = new JMenuItem("剪切");
        JMenuItem help = new JMenuItem("帮助");
        JMenuItem about = new JMenuItem("关于");
        
        JScrollPane scro1=new JScrollPane(text1);//添加滚动条
        JScrollPane scro2=new JScrollPane(text2);//添加滚动条
        
        JSplitPane jSplitPane =new JSplitPane();//设定为拆分布局
        JSplitPane jSplitPane2 =new JSplitPane();//设定为拆分布局
        JSplitPane jSplitPane3 =new JSplitPane();//设定为拆分布局
        
        public Windowm()
        {
            setVisible(true);
            jm.add(copy);
            jm.add(path);
            jm.add(cut);
            jm.add(help);
            jm.add(about);
             
            myPanel3.add(bt1);
            myPanel3.add(bt2);
            myPanel4.add(bt3);
             
            this.setTitle("欢迎使用文本比较软件");
            this.setBounds(100, 100, 600, 500);
            jSplitPane.setContinuousLayout(true);//操作箭头,重绘图形
            jSplitPane2.setContinuousLayout(true);//操作箭头,重绘图形
            jSplitPane3.setContinuousLayout(true);//操作箭头,重绘图形
            
            jSplitPane2.setOrientation(JSplitPane.VERTICAL_SPLIT);//垂直方向
            jSplitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);//水平方向
            jSplitPane3.setOrientation(JSplitPane.VERTICAL_SPLIT);//垂直方向
            
            myPanel1.setBorder(BorderFactory.createLineBorder(Color.green));
            myPanel2.setBorder(BorderFactory.createLineBorder(Color.red));
            myPanel3.setBorder(BorderFactory.createLineBorder(Color.yellow));
            myPanel4.setBorder(BorderFactory.createLineBorder(Color.blue));
    
            jSplitPane.setLeftComponent(scro1);//左右布局中添加组件 ,面板1
            jSplitPane.setRightComponent(scro2);//左右布局中添加组件 ,面板2
    
            jSplitPane2.setTopComponent(myPanel3);//上下布局中添加组件 ,面板1
            jSplitPane2.setBottomComponent(jSplitPane);//上下布局中添加组件 ,面板1
            
            jSplitPane3.setTopComponent(jSplitPane2);
            jSplitPane3.setBottomComponent(myPanel4);
            
            jSplitPane.setDividerSize(5);//设置分割线的宽度
            jSplitPane2.setDividerSize(5);//设置分割线的宽度
            jSplitPane3.setDividerSize(5);//设置分割线的宽度
            setContentPane(jSplitPane3);//设置为父模块
      
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            copy.addActionListener(new ActionListener()//窗口监听
                {
                    public void actionPerformed(ActionEvent e4)//菜单项
                    {
                           try{    
                            text1.copy();
                            text2.copy();
                        }catch(Exception e1){
                        }
                    }
                   }
            );
            path.addActionListener(new ActionListener()//窗口监听
                {
                    public void actionPerformed(ActionEvent e4)//菜单项
                    {
                           try{    
                               if(point==1)//由于有两个窗口,因此设计point来确定粘贴在某个窗口
                                   text1.paste();
                               else
                                text2.paste();
                        }catch(Exception e1){
                        }
                    }
                   }
            );
            cut.addActionListener(new ActionListener()//窗口监听
                {
                    public void actionPerformed(ActionEvent e4)//菜单项
                    {
                        try{    
                               text1.cut();
                               text2.cut();
                        }catch(Exception e1){
                        }
                    }
                }
            );
            help.addActionListener(new ActionListener()//窗口监听
                {
                    public void actionPerformed(ActionEvent e4)//菜单项
                    {
                        JOptionPane.showMessageDialog(null,"使用方法:输入或者点击打开两个文本,按核对键进行比较
    红色表示匹配失败,蓝色表示多余,黑色为正常匹配文本","使用指南",JOptionPane.PLAIN_MESSAGE);             
                    }
                }
            );
            about.addActionListener(new ActionListener()//窗口监听
                {
                    public void actionPerformed(ActionEvent e4)//菜单项
                    {
                        JOptionPane.showMessageDialog(null,"原创:将军
    QQ 2910001378@qq.com 
    人生苦短,欢迎转载","将军原创",JOptionPane.PLAIN_MESSAGE);             
                    }
                }
            );
            
            text1.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    if (e.getButton() == MouseEvent.BUTTON3) {      
                        jm.show(text1, e.getX(), e.getY()); // 弹出菜单
                        point=1;
                    }
                }
            });
            
            text2.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    if (e.getButton() == MouseEvent.BUTTON3) {      
                        jm.show(text2, e.getX(), e.getY()); // 弹出菜单
                        point=2;
                    }
                }
            });
            
            jSplitPane.addComponentListener(new ComponentAdapter() {//拖动窗口监听
                public void componentResized(ComponentEvent e) {  
                    jSplitPane.setDividerLocation(jSplitPane3.getWidth()/2-7);//设置第一条宽度  
                }  
            }); 
           jSplitPane2.setDividerLocation(50);//设定分割线的距离左边的位置
           jSplitPane3.addComponentListener(new ComponentAdapter() {//拖动窗口监听 
               public void componentResized(ComponentEvent e) {  
                   jSplitPane3.setDividerLocation(jSplitPane3.getHeight()-50);//设置第三条高度 
               }  
           }); 
           
        bt1.addActionListener(new ActionListener()//窗口监听
            {
                public void actionPerformed(ActionEvent e4)//菜单项
                {
                    try{    
                        text1.setText("");
                        JFileChooser jfc=new JFileChooser();
                        jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES );
                        jfc.showDialog(new JLabel(), "选择");
                        File file=jfc.getSelectedFile();
                        path1=file.getAbsolutePath();//获取文件绝对地址    
                        new Read_File(path1);
                        File1= Read_File.getFile();
                        SimpleAttributeSet attrset = new SimpleAttributeSet();
                        StyleConstants.setFontSize(attrset,16);//设置字号
                        Document docs=text1.getDocument();
                        docs.insertString(docs.getLength(), File1, attrset);
                    }catch(Exception e1){
                    }
                }
            }
        );
        bt2.addActionListener(new ActionListener()//窗口监听
            {
                public void actionPerformed(ActionEvent e4)//菜单项
                {
                    try{    
                        text2.setText("");
                        JFileChooser jfc=new JFileChooser();
                        jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES );
                        jfc.showDialog(new JLabel(), "选择");
                        File file=jfc.getSelectedFile();
                        path2=file.getAbsolutePath();//获取文件绝对地址        
                        new Read_File(path2);
                        File2= Read_File.getFile();
                        SimpleAttributeSet attrset = new SimpleAttributeSet();
                        StyleConstants.setFontSize(attrset,16);//设置字号
                        Document docs=text2.getDocument();
                        docs.insertString(docs.getLength(), File2, attrset);
                    }catch(Exception e1){
                        System.out.println("选择文件出错");
                    }
                }
            }
        );
        bt3.addActionListener(new ActionListener()//窗口监听
            {
                public void actionPerformed(ActionEvent e4)//菜单项
                {
                    try{
                        String dnas1;//算法处理之后的字符串1
                        String dnas2;//算法处理之后的字符串2
                        String jtp1;//JTextpane的内容1
                        String jtp2;//JTextpane的内容2
                        int len=0;    //处理后的字符串长度
                                    
                        jtp1=text1.getText();//获取窗口文本
                        jtp2=text2.getText();
                        text1.setText("");//清空之前内容
                        text2.setText("");
                        Document docs1=text1.getDocument();
                        Document docs2=text2.getDocument();                            
                        DNASequence dna=new DNASequence(jtp1,jtp2);//通过构造方法传递参数
                        dna.runAnalysis();
                        dna.traceback();
                        dnas1=dna.getString1();//获取处理后的字符串
                        dnas2=dna.getString2();
                        char[] s = dnas1.toCharArray();//字符串转Char数组
                        char[] p = dnas2.toCharArray();
                        len=dnas1.length();
                        SimpleAttributeSet set2 = new SimpleAttributeSet();//设置一个属性
                        StyleConstants.setFontSize(set2,16);//设置字号
                        for(int i=0;i<len;i++){
                            if(s[i]=='-'){
                                StyleConstants.setForeground(set2,Color.BLUE);//设置文字颜色
                                docs2.insertString(docs2.getLength(),String.valueOf(p[i]), set2);
                            }else if(p[i]=='-'){
                                StyleConstants.setForeground(set2,Color.BLUE);//设置文字颜色
                                docs1.insertString(docs1.getLength(),String.valueOf(s[i]), set2);
                            }else if(s[i]==p[i]){
                                StyleConstants.setForeground(set2,Color.black);//设置文字颜色
                                docs1.insertString(docs1.getLength(),String.valueOf(s[i]), set2);
                                docs2.insertString(docs2.getLength(),String.valueOf(p[i]), set2);
                            }else if(s[i]!=p[i]){                                StyleConstants.setForeground(set2,Color.red);//设置文字颜色
                                docs1.insertString(docs1.getLength(),String.valueOf(s[i]), set2);
                                docs2.insertString(docs2.getLength(),String.valueOf(p[i]), set2);
                            }else{
                                System.out.print("考虑更多颜色");
                            }
                        }
                        
                    }catch(Exception e1){        
                        System.out.println("选择文件2出错");
                    }
                }
            }
        );     
        }
    }
    View Code

    Read_File.java

    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;
    
    public class Read_File {
         static  String fileName;
        
        public  Read_File(String str){
                fileName=str;    
        }
        public static String getFile(){
            BufferedReader br = null;
            StringBuffer sb = null;
            try {
                br = new BufferedReader(new InputStreamReader(new FileInputStream(fileName),"utf-8")); //这里可以控制编码
                sb = new StringBuffer();
                String line = null;
                while((line = br.readLine()) != null) {
                    sb.append(line);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    br.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }    
            }
            String data = new String(sb); //StringBuffer ==> String
            System.out.println("数据为==> " + data);
            return data;
        }
        
    //    public static void main(String[] args) {
    //        new Read_File("1");
    //    }
    }
    View Code

    DNASequence.java

    //https://codereview.stackexchange.com/questions/182601/optimizing-needleman-wunsch-algorithm-in-java
    
    public class DNASequence {
        protected final String seq_1, seq_2;    //要分析的两个序列
        public int alignmentScore;              //使用Needleman-Wunsch算法
        protected Node[][] matrix;              //存储分数和缩进
        protected final int matchScore, mismatchScore, indel;
    
        //用于打印DNA序列分析的字符串
        String top = "";        // Sequence 1
        String bottom = "";     // Sequence 2
    
        public DNASequence(String s1, String s2) {
            //我使用一个■作为缓冲,这样序列字符串正确对齐
            // 在矩阵中使用缩进和分数。
            ScoreScheme s = new ScoreScheme(2, -1, -2);  
            seq_1 = "u25A0" + s1;
            seq_2 = "u25A0" + s2;
            matchScore = s.matchScore;
            mismatchScore = s.mismatchScore;
            indel = s.indel;
    
            matrix = new Node[seq_1.length()][seq_2.length()];
            for (int i = 0; i < seq_1.length(); i++)
                matrix[i][0] = new Node(i * indel, i, 0);
    
            for (int i = 0; i < seq_2.length(); i++)
                matrix[0][i] = new Node(i * indel, 0, i);
        }
    
        //辅助方法,帮助决定使用哪种匹配/不匹配得分。
        protected int score(int i, int j) {
            if (seq_1.charAt(i) == seq_2.charAt(j))
                return matchScore;
            else
                return mismatchScore;
        }
    
        //在本地级别上实现Needleman-Wunsch algo的Helper方法。
        protected Node match(int i, int j) {
            Node s1,s2,s3;
            s1 = new Node(matrix[i-1][j-1].score + score(i, j), i, j);
            s2 = new Node(matrix[i-1][j].score + indel, i, j);
            s3 = new Node(matrix[i][j-1].score + indel, i, j);
    
            Node largest = new Node(Math.max(s1.score, Math.max(s2.score, s3.score)), i, j);
            if (s1.compareTo(largest) == 0)
                largest.prev = matrix[i-1][j-1];
            else if(s2.compareTo(largest) == 0)
                largest.prev = matrix[i-1][j];
            else
                largest.prev = matrix[i][j-1];
            return largest;
        }
    
        public Node runAnalysis() {
            for (int i = 1; i < seq_1.length(); i++) {
                for (int j = 1; j < seq_2.length(); j++){
                    matrix[i][j] = match(i, j);
                }
            }
            alignmentScore = matrix[seq_1.length()-1][seq_2.length()-1].score;
            return matrix[seq_1.length()-1][seq_2.length()-1];
        }
    
        //辅助方法,逐步构建分析结果。它将返回
        //“尾巴”,因为我们可能还需要做一些工作。
        protected Node traceHelper(Node curr) {
            while (curr.prev != null) {
                if (curr.i - curr.prev.i == 1 && curr.j - curr.prev.j == 1){    // If the path leads diagonal
                    boolean x = seq_1.charAt(curr.i) == seq_2.charAt(curr.j) ? true : false;
                    if(x){
                        top = seq_1.charAt(curr.i) +top;
                        bottom = seq_2.charAt(curr.j) +bottom;
                    }else{
                        top = seq_1.charAt(curr.i) + top;
                        bottom = seq_2.charAt(curr.j) + bottom;
                    }
                }else if (curr.i - curr.prev.i == 1){               //如果这条路通向山顶
                    top = seq_1.charAt(curr.i) + top;
                    bottom = "-" +  bottom;                     //如果这条路通向左边
                }else if (curr.j - curr.prev.j == 1){
                    top = "-" + top;
                    bottom = seq_2.charAt(curr.j) +  bottom;
                }
                curr = curr.prev;
            }
            return curr;
        }
    
    //从矩阵的最后一个节点回溯到第一个索引节点。
        public void traceback() {
            Node curr = matrix[seq_1.length()-1][seq_2.length()-1];
            curr = traceHelper(curr);
            while (curr.i != 0 || curr.j != 0) {
                if (curr.i != 0 && curr.j == 0){
                    curr.prev = matrix[curr.i-1][curr.j];
                    curr = traceHelper(curr);
                }else if (curr.i == 0 && curr.j != 0) {
                    curr.prev = matrix[curr.i][curr.j-1];
                    curr = traceHelper(curr);
                }
            }
    
        //打印DNA序列分析
    //        System.out.println(top);
    //        System.out.println(bottom);
        }
        public String getString1(){
            return top;
        }
        public String getString2(){
            return bottom;
        }    
    
    }
    class Node implements Comparable<Node>{
        int i, j;
        int score;
        Node prev;
    
        public Node(int score, int x, int y) {
            this.i = x;
            this.j = y;
            this.score = score;
            this.prev = null;
        }
        public int compareTo(Node n) {
            return this.score - n.score;
        }
        public String toString() {
            return ""+score;
        }
    }
    
    class ScoreScheme {
        int matchScore, mismatchScore, indel;
        public ScoreScheme(int m1, int m2, int i) {
            matchScore = m1;
            mismatchScore = m2;
            indel = i;
        }
    }
    View Code

     项目源代码已经上传到我的GitHub仓库  下载点击https://github.com/Wo-com/TextCheck
     项目源代码已经上传到我的Gitee仓库  下载点击 https://gitee.com/wo-com/TextCheck.git

    如果觉得不错的话 就在GitHub里面给我点亮 Star吧

  • 相关阅读:
    算法练习题
    牛XX面试题
    web前端面试题
    在js中什么情况下会返回undefined
    yarn
    Web 开发技巧
    dll 文件创建与使用
    【转】 VS2008在64位Windows平台上编译ArcEngine导致HRESULT:0x80040154 (REGDB_E_CLASSNOTREG)错误的解决办法
    Googlemap获取经纬度For APIV3
    javascript局部变量/全局变量
  • 原文地址:https://www.cnblogs.com/easyidea/p/11026060.html
Copyright © 2020-2023  润新知