java简易编辑器

基于Swing组件。

一、项目结构

Java写Java java写java编译器_Java写Java

二、GUI界面的实现

界面最终要完成的效果如下:

Java写Java java写java编译器_java_02

界面采用的设计布局为:CardLayout

白色文本区域为程序输入区

粉色为编译结果显示区

浅蓝色文本域为程序运行结果区。

我们要完成的功能是:点击上方的不同按钮显示对应的文本域

在File类中实现GUI的代码,代码如下:

public class FileWindow extends JFrame implements ActionListener, Runnable {

    /*注意:因为实现了ActionListener 和Runnable接口,所以必须要实现这两个接口的方法。这里我们先把这两个方法简单实现以下。下节课将彻底完成这两个方法。*/

    Thread compiler = null;
    Thread run_prom = null;
    boolean bn = true;
    CardLayout mycard;  //声明布局,以后会用到
    File file_saved = null;
    JButton button_input_txt,   //按钮的定义
            button_compiler_text,
            button_compiler,
            button_run_prom,
            button_see_doswin;

    JPanel p = new JPanel();
    JTextArea input_text = new JTextArea(); // 程序输入区
    JTextArea compiler_text = new JTextArea();// 编译错误显示区
    JTextArea dos_out_text = new JTextArea();// 程序的输出信息

    JTextField input_file_name_text = new JTextField();
    JTextField run_file_name_text = new JTextField();

    public FileWindow() {
        // TODO Auto-generated constructor stub
        super("Java语言编译器");
        mycard = new CardLayout();
        compiler=new Thread(this);
        run_prom=new Thread(this);
        button_input_txt=new JButton("程序输入区(白色)");
        button_compiler_text=new JButton("编译结果区(粉红色)");
        button_see_doswin=new JButton("程序运行结果(浅蓝色)");
        button_compiler=new JButton("编译程序");
        button_run_prom=new JButton("运行程序");

        p.setLayout(mycard);//设置卡片布局
        p.add("input",input_text);//定义卡片名称
        p.add("compiler", compiler_text);
        p.add("dos",dos_out_text);
        add(p,"Center");

        compiler_text.setBackground(Color.pink); //设置颜色
        dos_out_text.setBackground(Color.cyan);
        JPanel p1=new JPanel();

        p1.setLayout(new GridLayout(3, 3)); //设置表格布局
        //添加组件
        p1.add(button_input_txt);
        p1.add(button_compiler_text);
        p1.add(button_see_doswin);
        p1.add(new JLabel("输入编译文件名(.java):"));
        p1.add(input_file_name_text);
        p1.add(button_compiler);
        p1.add(new JLabel("输入应用程序主类名"));
        p1.add(run_file_name_text);
        p1.add(button_run_prom);
        add(p1,"North");

        //定义事件
        button_input_txt.addActionListener(this);
        button_compiler.addActionListener(this);
        button_compiler_text.addActionListener(this);
        button_run_prom.addActionListener(this);
        button_see_doswin.addActionListener(this);


    }

    public void actionPerformed(ActionEvent e)
    {
         //实现方法

    }

    @Override
    public void run() {
        //实现方法
    }


    }

三、测试一些GUI界面

我们做个测试类来看看GUI好不好看。

四、实现功能

涉及的知识点:

  • Java Swing 编程
  • IO 流操作
  • Runtime 类
  • Thread 的使用

五、actionPerformed 方法的实现

代码如下,其逻辑在注释中

public void actionPerformed(ActionEvent e)
        {
            if(e.getSource()==button_input_txt)
            {    //显示程序输入区
                mycard.show(p,"input");
            }
            else if(e.getSource()==button_compiler_text)
            {    //显示编译结果显示区
                mycard.show(p,"compiler");
            }
            else if(e.getSource()==button_see_doswin)
            {    //显示程序运行结果区
                mycard.show(p,"dos");
            }
            else if(e.getSource()==button_compiler)
            {    //如果是编译按钮,执行编译文件的方法
                if(!(compiler.isAlive()))
                {
                    compiler=new Thread(this);
                }
                try {
                    compiler.start();

                } catch (Exception e2) {
                    // TODO: handle exception
                    e2.printStackTrace();
                }

                mycard.show(p,"compiler");

            }
            else if(e.getSource()==button_run_prom)
            {    //如果是运行按钮,执行运行文件的方法
                if(!(run_prom.isAlive()))
                {
                    run_prom=new Thread(this);
                }
                try {
                    run_prom.start();
                } catch (Exception e2) {
                    // TODO: handle exception
                    e2.printStackTrace();
                }
                mycard.show(p,"dos");
            }

        }

六、run方法的实现

run方法是最重要的一个方法。

首先,这个方法会判断是编译还是运行:

如果当前Thread是编译,那么会将程序输入区中的代码以.java文件的形式保存到项目的当前目录下,并通过javac命令执行刚才保存的.java文件从而生成.class文件。编译后的信息会输出到编译结果显示区。

如果当前Thread是运行,那么会通过java命令执行编译生成的.class文件,并将结果显示到程序运行结果区。

public void run() {
             //TODO Auto-generated method stub
            if(Thread.currentThread()==compiler)
            {
            compiler_text.setText(null);
            String temp=input_text.getText().trim();
            byte [] buffer=temp.getBytes();
            int b=buffer.length;
            String file_name=null;
       file_name=input_file_name_text.getText().trim();

      try {
    file_saved=new File(file_name);
    FileOutputStream writefile=null;
    writefile=new FileOutputStream(file_saved);
    writefile.write(buffer, 0, b);
    writefile.close();
            } catch (Exception e) {
                    // TODO: handle exception
                    System.out.println("ERROR");
                }
    try {

    //获得该进程的错误流,才可以知道运行结果到底是失败了还是成功。
     Runtime rt=Runtime.getRuntime();
       InputStream in=rt.exec("javac "+file_name).getErrorStream(); //通过Runtime调用javac命令。注意:“javac ”这个字符串是有一个空格的!!

        BufferedInputStream bufIn=new BufferedInputStream(in);

        byte[] shuzu=new byte[100];
        int n=0;
        boolean flag=true;

        //输入错误信息
    while((n=bufIn.read(shuzu, 0,shuzu.length))!=-1)
        {
            String s=null;
              s=new String(shuzu,0,n);
            compiler_text.append(s);
            if(s!=null)
                        {
                            flag=false;
                        }
            }
                    //判断是否编译成功
                    if(flag)
                    {
                        compiler_text.append("Compile Succeed!");
                    }
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
    else if(Thread.currentThread()==run_prom)
        {
            //运行文件,并将结果输出到dos_out_text

        dos_out_text.setText(null);

        try {
              Runtime rt=Runtime.getRuntime();
    String path=run_file_name_text.getText().trim();
    Process stream=rt.exec("java "+path);//调用java命令

    InputStream in=stream.getInputStream();
                    BufferedInputStream bisErr=new BufferedInputStream(stream.getErrorStream());
                    BufferedInputStream bisIn=new BufferedInputStream(in);

    byte[] buf=new byte[150];
    byte[] err_buf=new byte[150];

    @SuppressWarnings("unused")
    int m=0;
    @SuppressWarnings("unused")
    int i=0;
    String s=null;
    String err=null;

    //打印编译信息及错误信息
    while((m=bisIn.read(buf, 0, 150))!=-1)
                    {
                        s=new String(buf,0,150);
                        dos_out_text.append(s);
                    }
                                  while((i=bisErr.read(err_buf))!=-1)
                    {
                    err=new String(err_buf,0,150);
                    dos_out_text.append(err);
                    }
        }
         catch (Exception e) {
                    // TODO: handle exception
                    }
        }
     }

七、完整代码

完整代码如下:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

public class FileWindow extends JFrame implements ActionListener,Runnable {


    Thread compiler = null;
    Thread run_prom = null;
    boolean bn = true;
    CardLayout mycard;              //声明布局
    File file_saved = null;
    JButton button_input_txt,
            button_compiler_text,
            button_compiler,
            button_run_peom,
            button_see_doswin;

    JPanel p = new JPanel();
    JTextArea input_text = new JTextArea();      //程序输入区
    JTextArea compiler_text = new JTextArea();   //编译错误显示区
    JTextArea dos_out_text = new JTextArea();    //程序的输出信息
    JTextField input_file_name_text = new JTextField();
    JTextField run_file_name_text = new JTextField();

    public FileWindow(){
        super("JAVA语言编译器");
        mycard = new CardLayout();
        compiler = new Thread(this);  //this是实现了runnable的类
        run_prom=new Thread(this);
        button_input_txt=new JButton("程序输入区(白色)");
        button_compiler_text=new JButton("编译结果区(粉红色)");
        button_see_doswin=new JButton("程序运行结果(浅蓝色)");
        button_compiler=new JButton("编译程序");
        button_run_peom=new JButton("运行程序");

        //面板1负责各区域
        p.setLayout(mycard);    //设置卡片布局
        //添加组件
        p.add("input",input_text);
        p.add("compiler",compiler_text);
        p.add("dose",dos_out_text);
        add(p,"Center");
        compiler_text.setBackground(Color.PINK);
        dos_out_text.setBackground(Color.cyan);

        JPanel p1=new JPanel();  //第二个面板,负责按钮
        p1.setLayout(new GridLayout(3,3)); //网格布局
        //添加组件
        p1.add(button_input_txt);
        p1.add(button_compiler_text);
        p1.add(button_see_doswin);
        p1.add(new JLabel("请输入编译文件名(.java): "));
        p1.add(input_file_name_text);
        p1.add(button_compiler);
        p1.add(new JLabel("输入应用程序主类名"));
        p1.add(run_file_name_text);
        p1.add(button_run_peom);
        add(p1,"North");

        //定义事件监视器
        button_input_txt.addActionListener(this);
        button_compiler.addActionListener(this);
        button_run_peom.addActionListener(this);
        button_see_doswin.addActionListener(this);
        button_compiler_text.addActionListener(this);

    }


    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource()==button_input_txt){
            //显示程序输入区
            mycard.show(p,"input");
        }else if (e.getSource()==button_compiler_text){
            //显示编译结果显示区
            mycard.show(p,"compiler");
        }else if (e.getSource()==button_see_doswin){
            //显示运行结果区
            mycard.show(p,"dose");
        }else if (e.getSource()==button_compiler){
            //如果是编译按钮,则执行编译文件的方法
            if (!compiler.isAlive()){
                compiler=new Thread(this);
            }
            try {
                compiler.start();
            }catch (Exception e2){
                e2.printStackTrace();
            }

            mycard.show(p,"compiler");
        }else if (e.getSource()==button_run_peom){
            //如果是运行按钮,则执行运行文件的方法
            if (!run_prom.isAlive()){
                run_prom = new Thread(this);
            }
            try {
                run_prom.start();
            }catch (Exception e2){
                e2.printStackTrace();
            }
            mycard.show(p,"dose");

        }

    }

    @Override
    public void run() {
        if (Thread.currentThread()==compiler){
            compiler_text.setText(null);
            String temp = input_text.getText().trim();  //读取输入区的代码

            //下面首先进行的是对代码用IO流进行一个保存,之后才能编译
            byte[] buffer = temp.getBytes();
            int b=buffer.length;
            String file_name=input_file_name_text.getText().trim();//用文件名输入区的文件命名
            try {//写入文件
                file_saved=new File(file_name);
                FileOutputStream writefile=null;
                writefile=new FileOutputStream(file_saved);
                writefile.write(buffer,0,b);
                writefile.close();
            }catch (Exception e){
                System.out.println("ERROR");
            }
            try {
                //获取该进程的错误流,这样才可以知道到底是失败了还是成功了
                Runtime rt=Runtime.getRuntime();
                InputStream in =rt.exec("javac "+file_name).getErrorStream();//通过Runtime调用javac命令
                BufferedInputStream bufin=new BufferedInputStream(in);

                byte[] shuzu = new byte[100];
                int n=0;
                boolean flag=true;

                //输入错误信息,这里用到的知识是输入流,输入流输送过来的是字节,要把它们转换为一个个的字符
                while ((n=bufin.read(shuzu,0, shuzu.length))!=-1) {
                    String s = null;
                    s = new String(shuzu, 0, n);
                    compiler_text.append(s); //在编译信息区输入符号
                    if (s != null) {
                        flag = false;
                    }
                }
                //在文末输出一个“编译成功”的信息
                if (flag){
                    compiler_text.append("Compile Succeed!");
                }
                }catch (Exception e){
                e.printStackTrace();
            }
        }else if (Thread.currentThread()==run_prom){
            //运行文件,将结果输出到dos_out_text
            dos_out_text.setText(null);
            try {
                Runtime rt=Runtime.getRuntime();
                String path=run_file_name_text.getText().trim();
                Process stream=rt.exec("java "+path); //调用java 命令运行class文件
                BufferedInputStream bisErr=new BufferedInputStream(stream.getErrorStream());
                BufferedInputStream bisIn=new BufferedInputStream(stream.getInputStream());
                
                byte[] buf =new byte[150];
                byte[] err_buf=new byte[150];
                
                @SuppressWarnings("unused")
                int m=0;
                @SuppressWarnings("unused")
                int i=0;
                
                String s=null;
                String err=null;
                
                //打印编译信息已经运行信息
                while ((m=bisIn.read(buf,0,150))!=-1){
                    s=new String(buf,0,150);
                    dos_out_text.append(s);
                }
                while ((i=bisErr.read(err_buf,0,150))!=-1){
                    err=new String(err_buf,0,150);
                    dos_out_text.append(err);
                }
            }catch (Exception e){
                
            }
        }
        
    }
}