java简易编辑器
基于Swing组件。
一、项目结构
二、GUI界面的实现
界面最终要完成的效果如下:
界面采用的设计布局为: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){
}
}
}
}