JavaSwing實現的文本比較軟件

先看效果:截圖1java

截圖2:git

實現思路:github

 一、界面UI設計算法

二、功能點 : a 打開文件進行比較    b 粘貼內容進去比較   c 提示幫助  d 窗口能夠任意拖動數組

三、文本比較算法app

 

 java類 :ide

        MainUI 類實現界面設計       Read_File 類實現文件讀取      DNASequence 類文本比較算法佈局

 

項目結構:字體

源代碼:this

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(), "手動輸入輸入或者選擇文間打開\n點擊覈對試試\n紅色表示錯誤字符\n藍色表示多餘或缺失字符", 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,"使用方法:輸入或者點擊打開兩個文本,按覈對鍵進行比較\n紅色表示匹配失敗,藍色表示多餘,黑色爲正常匹配文本","使用指南",JOptionPane.PLAIN_MESSAGE);             
                }
            }
        );
        about.addActionListener(new ActionListener()//窗口監聽
            {
                public void actionPerformed(ActionEvent e4)//菜單項
                {
                    JOptionPane.showMessageDialog(null,"原創:將軍\nQQ 2910001378@qq.com \n人生苦短,歡迎轉載","將軍原創",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

若是以爲不錯的話 就在GitHub裏面給我點亮 Star吧

相關文章
相關標籤/搜索