Java-GUI
1、Java-GUI(概述)
什么是GUI?
GUI就是Graphic User Interface的缩写。它提供了一个标准的制作界面、制作外观的方法。我们知道人机交互有两种方式,一个是图形化界面,还有一个是命令行接口。因此对应的有CLI,即Command Line User Interface。综上所述:
GUI:图形用户接口
CLI:命令行用户接口
以上两种人机交互方式在之前的笔记中已有详细的叙述,再次不作阐述。
java.awt、javax.Swing、java.xwt
java为GUI提供的对象都存在java.awt和java.Swing两个包中。
java.awt:Abstract Windows ToolKit(抽象窗口工具包),需要调用本地系统方法实现功能,调用系统底层,依赖于平台。跨平台性、移植性差。就比方说,在windows 2000系统下,开发的图形化界面放到windows xp系统下,界面会有点不一样。因此我们说它属重量级控件。
java.Swing:在Awt的基础下,建立的一套图形界面系统,其中提供了更多的组件。而且完全有java实现,正好弥补了java.awt的不足之处,增强了移植性,属轻量级控件。
java.xwt:eclipse界面就是用它来开发的。纯java编写的。这也是一个外观包。
下面我们来看一下,java给GUI提供的两个包中到底有那些工具类呢?
继承关系图:(常用)
2、Java-GUI(布局)
做界面,我们玩的就是窗体,当我们new一个窗体之后,往里面添加其他组件,比如按钮等,怎么添加是个问题。但是java给我们提供了布局管理器。
容器中的组件的排放方式,就是布局。
常见的布局管理器:
FlowLayout(流式布局管理器)
从左到右的顺序排列。
Panel默认的布局管理器。
BoderLayout(边界布局管理器)
东、南、西、北、中
Frame默认的布局管理器。
GridLayout(网格布局管理器)
规则的矩阵
GridBagLayout(网格包布局管理器)
非规则的矩阵
CardLayout(卡片布局管理器)
选项卡
坐标式布局
通过指定坐标可以放在任意位置
混合式布局
通过面板,窗体中添加面板,面板中添加组件。窗体可以创建这些布局管理器的对象指定布局,面板亦是。不同面板中可以是不同的布局。
FlowLayout(流式布局管理器)
BoderLayout(边界布局管理器)
GridLayout(网格布局管理器)
GridBagLayout(网格包布局管理器)
CardLayout(卡片布局管理器)
坐标式布局
混合式布局
图形化界面最难的就是布局。因此,我们在开发的时候,尽量用一些高级的编辑器,比如JBuild,比如eclipse加上一个图形化界面插件,画布,画布中有很多组件。代码自动生成。VB,C++的开发就有画布。
3、Java-GUI(Frame)
下面我们首先通过一个小程序来进入主题:
import java.awt.*;
class AwtDemo
{
public static void main(String[] args)
{
Frame f=new Frame("my awt");//创建一个带名字的 //窗体,但是不可见。
System.out.println("hello world");
}
}
通过命令行进行编译运行,发现打印出hello world ,主线程结束。但是程序并没有结束。因此我们知道,所有图形化界面都是一个单独的前台线程。此时必须通过Ctrl C结束。
我们还可以对窗体进行设置:
public AwtDemo
{
poublic static void main(String[] args)
{
Frame f=new Frame("my awt");
f.setSize(500,400);
f.setLocation(300,200);
/*
这一步必须做,不然往窗体里边加组件时,组件会铺 满整个窗体,因为Frame的默认布局是边界布局。
*/
f.setLayout(new FlowLayout());
Button b=new Button("我是一个按钮");
f.add(b);
f.setVisible(true);
}
}
现在通过命令行进行编译运行,会出现效果,但是当你点击窗口中的按钮,没有什么效果,还有就是窗体没有关闭的特点,只有放大,缩小的特点,这会涉及后面讲到的监听事件(我们操作一个东西,会发生什么样的事情)。
总结:创建图形化界面:
1、创建Frame 窗体。
2、对窗体进行基本设置。比如大小,位置,布局。
3、定义组件。
4、将组件通过窗体的add方法添加到窗体中。
5、让窗体显示,通过setVisible(true);
4、Java-GUI(事件监听机制)
在上一次的学习当中,我们知道了如何监听窗体。但是我们是在main函数中做的,类中只有一个main函数,在这一次学习中,我们将图形化界面和事件监听分离。首先我们来看一下代码的实现:
import java.awt.*;
import java.awt.event.*;
class FrameDemo
{
private Frame f;
private Button b;
FrameDemo()
{
init();
}
public void init()
{
f=new Frame("my frame");
//对窗体进行一些基本的设置。
f.setBounds(300,400,500,600);
f.setLayout(new FlowLayout());
b=new Button("my button");
//把组件加到窗体中。
f.add(b);
//加载窗体上的一些事件。
myEvent();
//显示窗体。
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
//窗体测试。
public static void main(String[] args)
{
new FrameDemo();
}
}
编译运行后,结果如下图所示:
当点击叉时,结果如下如所示:
接下来我们想通过点击按钮使窗口关闭的效果。因此,现在的事件源是按钮,我们现在应当在按钮上注册监听器,根据在窗体注册监听器的经验告诉我们需要查看该组件对象的功能,通过查阅Button的API,发现按钮支持一个特有的添加监听器的方法addActionListener(ActionListener l);同理,需要接收一个ActionListener类型的参数l,这个l就是监听器,这个ActionListener也是一个接口,但是它里边只有一个抽象方法,因此我们不需要在思考它有没有适配器来方便我们创建监听器对象,我们可以直接通过匿名内部类来创建子类对象。下面我们通过代码来看一下具体的实现:
import java.awt.*;
import java.awt.event.*;
class FrameDemo
{
private Frame f;
private Button b;
FrameDemo()
{
init();
}
public void init()
{
f=new Frame("my frame");
//对窗体进行一些基本的设置。
f.setBounds(300,400,500,600);
f.setLayout(new FlowLayout());
b=new Button("my button");
//把组件加到窗体中。
f.add(b);
//加载窗体上的一些事件。
myEvent();
//显示窗体。
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
//
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
//验证一下窗体被关闭是不是按钮干的。
System.out.println("按钮干的");
System.exit(0);
}
});
}
//窗体测试。
public static void main(String[] args)
{
new FrameDemo();
}
}
编译运行后,结果如下图所示:
当点击一下按钮,结果如下图所示:
5、Java-GUI(窗体事件)
上一次的学习当中,我们遇到了窗口不能关闭的问题,于是我们引入看事件监听机制的概念。在本次的学习中,我们将具体的学习窗口是如何被监听的?
首先,我们要在窗体上注册监听器:
f.addWindowListener(WindowListener l);该方法是Frame从它的父类Window继承而来。此时l就是监听器。
ps:我们知道监听器中有两部分内容,一个是监听的动作,一个是事件处理方式。根据面向对象的思想,l是WindowListener的一个实例,我们可以通过查看WindowListener就可以知道监听器l中是否包含这两部内容。查看之后,发现:有void windowActivated(WindowEvent e)、void windowClosing(WindowEvent e)等方法,确实体现出监听器中两部分内容。现在的问题是,WindowListener是一个接口,所以不能实例化,因此,该方法接收的一定是该接口子类的对象,而且该子类必须实现该接口中所有的方法,否则仍然是抽象类,不能实例化(但是如果现在只想监听关闭的动作,其他动作不监听,覆盖所有方法有些多余)。按照这个思路我们找到了它的一个实现类WindowAdapter,它实现了父接口WindowListener中所有的方法,但是方法体为空。因此仍然把它定义成抽象类,因为创建它的对象也毫无意义。这种情况就叫作没有一个抽象方法的抽象类。但是,它的存在是有意义的,它是一个接收窗口事件的抽象适配器类,方便创建监听器对象(正好解决了上述所讲的“多余”问题,我们只需要继承WindowAdapter(注意它所在的包是java.awt.event,所以开发时,要导包。),复写我们需要的方法,监听我们想监听的动作,如WindowClosing())。下面我们来看一下,它是如何方便的呢?
可以写出如下代码:
import java.awt.*;
import java.awt.event.*;
class AwtDemo
{
public static void main(String[] args)
{
Frame f=new Frame("窗体演示");
f.setSize(500,400);
f.setLocation(200,300);
f.setLayout(new FlowLayout());
Button b=new Button("我是一个按钮");
f.add(b);
f.addWindowListener(new MyWin());
f.setVisible(true);
}
}
class MyWin extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.out.println("关闭窗体");
System.exit(0);
}
}
将上述代码保存成一个.java文件,叫作:Awt.java。 打开命令行编译运行的结果如下图所示:
当我们点击串口的关闭按钮,则有如下变化:
现在我们在回过头来看看代码:我们可以用匿名内部类来做:
import java.awt.*;
import java.awt.event.*;
class AwtDemo
{
public static void main(String[] args)
{
Frame f=new Frame("窗体演示");
f.setSize(500,400);
f.setLocation(200,300);
f.setLayout(new FlowLayout());
Button b=new Button("我是一个按钮");
f.add(b);
f.addWindowListener(new WindowAdapter()
{
pubic void WindowClosing(WindowEvent e)
{
System.exit(0);
}
});
f.setVisible(true);
}
}
/*
class MyWin extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.out.println("关闭窗体");
System.exit(0);
}
}
*/
编译运行之后,也会出现同样的效果哦。以后开发中 会经常用到这种方法。我们还可以监听多个动作。
拓展:
import java.awt.*;
import java.awt.event.*;
class AwtDemo
{
public static void main(String[] args)
{
Frame f=new Frame("窗体演示");
f.setSize(500,400);
f.setLocation(200,300);
f.setLayout(new FlowLayout());
Button b=new Button("我是一个按钮");
f.add(b);
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
public void windowOpened(WindowEvent e)
{
System.out.println("我被打开了");
}
public void windowActivated(WindowEvent e)
{
System.out.println("我活了。");
}
});
f.setVisible(true);
}
}
编译运行后,结果如下图所示:
6、Java-GUI(Action事件)
在上一次的学习当中,我们知道了如何监听窗体。但是我们是在main函数中做的,类中只有一个main函数,在这一次学习中,我们将图形化界面和事件监听分离。首先我们来看一下代码的实现:
import java.awt.*;
import java.awt.event.*;
class FrameDemo
{
private Frame f;
private Button b;
FrameDemo()
{
init();
}
public void init()
{
f=new Frame("my frame");
//对窗体进行一些基本的设置。
f.setBounds(300,400,500,600);
f.setLayout(new FlowLayout());
b=new Button("my button");
//把组件加到窗体中。
f.add(b);
//加载窗体上的一些事件。
myEvent();
//显示窗体。
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
//窗体测试。
public static void main(String[] args)
{
new FrameDemo();
}
}
编译运行后,结果如下图所示:
当点击叉时,结果如下如所示:
接下来我们想通过点击按钮使窗口关闭的效果。因此,现在的事件源是按钮,我们现在应当在按钮上注册监听器,根据在窗体注册监听器的经验告诉我们需要查看该组件对象的功能,通过查阅Button的API,发现按钮支持一个特有的添加监听器的方法addActionListener(ActionListener l);同理,需要接收一个ActionListener类型的参数l,这个l就是监听器,这个ActionListener也是一个接口,但是它里边只有一个抽象方法,因此我们不需要在思考它有没有适配器来方便我们创建监听器对象,我们可以直接通过匿名内部类来创建子类对象。下面我们通过代码来看一下具体的实现:
import java.awt.*;
import java.awt.event.*;
class FrameDemo
{
private Frame f;
private Button b;
FrameDemo()
{
init();
}
public void init()
{
f=new Frame("my frame");
//对窗体进行一些基本的设置。
f.setBounds(300,400,500,600);
f.setLayout(new FlowLayout());
b=new Button("my button");
//把组件加到窗体中。
f.add(b);
//加载窗体上的一些事件。
myEvent();
//显示窗体。
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
//
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
//验证一下窗体被关闭是不是按钮干的。
System.out.println("按钮干的");
System.exit(0);
}
});
}
//窗体测试。
public static void main(String[] args)
{
new FrameDemo();
}
}
编译运行后,结果如下图所示:
当点击一下按钮,结果如下图所示:
7、Java-GUI(鼠标事件)
在本次的学习中,我们将会知道鼠标事件是如何监听的。首先,我们应该知道鼠标事件是所有组件都应该有的事件。添加鼠标事件监听器的方法应该在Component类中,通过查找Component的api,我们找到了一个方法叫作:
addMouseListener(MouseListener l);显然,l就是在组件中所注册的监听器,这个监听器的类型是MouseListener,该接口中有mouseClicked()、mouseEntered()等抽象方法,因此它有适配器MouseAdapter。下面,以组件button以例来讲解。看下面代码:
import java.awt.*;
import java.awt.event.*;
class MouseAndKeyDemo
{
private Frame f;
private Button b;
MouseAndKeyDemo()
{
init();
}
public void init()
{
f=new Frame("my frame");
f.setBounds(200,300,400,500);
f.setLayout(new FlowLayout());
b=new Button("my button");
f.add(b);
myEvent();
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
b.addMouseListener(new MouseAdapter()
{
private int count;
public void mouseEntered(MouseEvent e)
{
System.out.println("鼠标进入到该组件"+count++);
}
});
}
public static void main(String[] args)
{
new MouseAndKeyDemo();
}
}
编译运行后,将鼠标放在按钮上,再拿出,再放入,再拿出就,结果如下如所示:
在原有的基础上,再来监听鼠标点击按钮的动作。则在myEvent()中代码如下所示:
public void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
b.addMouseListener(new MouseAdapter()
{
private int count;
private int clickCount;
public void mouseEntered(MouseEvent e)
{
System.out.println("鼠标进入到该组件"+count++);
}
public void mouseClicked(MouseEvent e)
{
System.out.println("点击动作"+clickCount++);
}
});
}
编译运行后的结果如下所示:
再想到之前我们在按钮上注册的监听器l它是监听活动的,它的类型是ActionListener。下面我们如果给按钮添加这个监听器,结果有如何呢?
代码如下:
import java.awt.*;
import java.awt.event.*;
class MouseAndKeyDemo
{
private Frame f;
private Button b;
MouseAndKeyDemo()
{
init();
}
public void init()
{
f=new Frame("my frame");
f.setBounds(200,300,400,500);
f.setLayout(new FlowLayout());
b=new Button("my button");
f.add(b);
myEvent();
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.out.println("action ok");
}
});
b.addMouseListener(new MouseAdapter()
{
private int count;
private int clickCount;
public void mouseEntered(MouseEvent e)
{
System.out.println("鼠标进入到该组件"+count++);
}
public void mouseClicked(MouseEvent e)
{
System.out.println("点击动作"+clickCount++);
}
});
}
public static void main(String[] args)
{
new MouseAndKeyDemo();
}
}
编译运行后结果如下所示:
发现:点击动作产生的事件对象被先处理。这里需要注意,按钮只要被活动,就会产生事件对象。而鼠标和键盘会使按钮活动的更具体,所以先处理。还有就是,鼠标不放在按钮上点击或者是敲击键盘都会显示出action ok。
拓展:
现在想监听双击按钮的动作,怎么做呢?通过查阅MouseListener接口,发现并没有对应的方法,而只有相关的mouseClicked(MouseEvent e)但是,我们想,监听器只负责接收动作产生的事件对象e,而这个对象里肯定封装了一些内容,因此,是什么样的点击动作,这个对象中肯定有封装。果不其然,当我们查阅MouseEvent时,里面有一个方法getClickCount();因此我们可以做一个判断,核心代码如下:
public void mouseClicked(MouseEvent e)
{
if(e.getClickCount==2)
System.out.println("点击动作"+clickCount++);
}
编译运行结果如下所示:
8、Java-GUI(键盘事件)
在学习鼠标事件之后,键盘事件也很简单,我们仍然在按钮组件上来完成。此时,添加监听器的方法是addKeyListener(KeyListener l)。还是一样的思路,我们查阅KeyListener接口里面封装的内容,发现,有keyPressed(KeyEvent e)、keyReleased(KeyEvent e)和keyTyped(KeyEvent e)方法,因此它一定有适配器类来方便我们建立监听器对象。还有就是当键盘监听器接收到事件对象e,这个e中也封装很多的内容,通过查阅KeyEvent类的api,我们知道里面有非静态的char getkeyChar()(返回的是按下的键所对应的字符)和int getKeyCode()(返回的是按下的键所对应字符的整数,这个不用记,KeyEvent已经将它们都封装好了,如整型字段static int VK_Y,它就是一个整型常量),还有静态的String getkeyText(int keyCode)。下面我们通过监听按下的动作来演示。代码如下:
import java.awt.*;
import java.awt.event.*;
class MouseAndKeyDemo1
{
private Frame f;
private Button but;
MouseAndKeyDemo1()
{
init();
}
public void init()
{
f=new Frame("my frame");
f.setBounds(100,200,300,400);
f.setLayout(new FlowLayout());
but=new Button("my button");
f.add(but);
myEvent();
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
but.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
System.out.println(e.getKeyChar()+"....."+e.getKeyCode());
}
});
}
public static void main(String[] args)
{
new MouseAndKeyDemo1();
}
}
编译运行后,结果如下图所示:
我们可以看到,在按钮周围有一个虚线框,这表示这个按钮是当前事件源。因此,这时我们不断敲击键盘,结果如下如所示:
可是当你按下shift键的时候,结果又是什么呢?看下图:
这个时候,我们通过运行结果,我们就不知道我们到底按下的是什么键了。因此如果我们想获取键的文本,可以通过调用getKeyText(int keyCode)方法,核心代码如下:
but.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
//System.out.println(e.getKeyChar()+"....."+e.get //KeyCode());
System.out.println(KeyEvent.getKeyText(e.getKeyCo de())+"....."+e.getkeyCode());
}
});
运行结果如下图所示:
接下来,我们想一按Enter键,程序就结束。核心代码如下:
but.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
//System.out.println(e.getKeyChar()+"....."+e.get //KeyCode());
//System.out.println(KeyEvent.getKeyText(e.getKey //Code())+"....."+e.getkeyCode());
if(e.getKeyCode()==VK_ENTER)
System.exit(0);
}
});
现在我们想通过组合键(Ctr+Enter)来实现结束程序的功能,这时候,KeyEvent类中并没有对应的功能可以让我们调用,因此我们可以查找它的父类InputEvent,它里边有一个功能boolean isControlDown(),是用来判断ctl是否被按下。核心代码实现如下:
but.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if(e.isControlDown()&&e.getKeyCode()==KeyEvent.VK_ENTER)
System.out.println("ctrl+Enter is run");
}
});
编译运行后,当按下Ctrl不放,再按Enter键后,结果如下图所示:
拓展:现在创建一个TextField对象。文本框中只能添加数字。完整代码如下:
import java.awt.*;
import java.awt.event.*;
class MouseAndKeyDemo1
{
private Frame f;
private Button but;
private TextField tf;
MouseAndKeyDemo1()
{
init();
}
public void init()
{
f=new Frame("my frame");
f.setBounds(100,200,300,400);
f.setLayout(new FlowLayout());
but=new Button("my button");
tf=new TextField(20);//文本框的长度为20列。
f.add(tf);
f.add(but);
myEvent();
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
but.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if(e.isControlDown()&&e.getKeyCode()==KeyEvent.VK_ENTER)
System.out.println("ctrl+Enter is run");
}
});
/*
确定事件源,确定监听器,确定监听的动作,确定事 件处理方式。
这里要知道的就是,监听的组件和处理方式中处理的 对象可能不一样,就比如说,我们在文本框中填写内 容,我们要实现的是,当我们一点击按钮,文本框中 的内容被打印出来。
那么这里监听的组件是按钮,处理方式中处理的对象 就是文本框,两个不是同一个组件。
*/
tf.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
int code=e.getKeyCode();
if(!(code>=KeyEvent.VK_0&&code<=KeyEvent.VK_9))
System.out.println(code+"....非法的");
}
});
}
public static void main(String[] args)
{
new MouseAndKeyDemo1();
}
}
编译运行后,往文本框中输入一些字符,结果如下图所示:
通过结果图,我们发现,明明d是非法的,但还是进入到文本框中去了。我们的想法是:按可以,但是不让进。其实输入是一个连串事件,你按下和这个进入到文本框中是一个连续事件,而我判断的时候,如果不符合,可以不让它进入到文本框里边去,而直接把这个进入到文本框中的这个事件取消掉。这时,KeyEvent类里边没有相应的功能可以实现,这时找它的父类InputEvent,里边有一个consume(),使用此事件,以便不会按照默认的方式由产生此事件的源代码来处理事件。默认的话,即使不合法b也会进入,因为它们是连串事件,现在不按照默认,则不会进去。
核心代码如下:
tf.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
int code=e.getKeyCode();
if(!(code>=KeyEvent.VK_0&&code<=KeyEvent.VK_9))
{
System.out.println(code+"....非法的");
e.consume();
}
}
});
编译运行后,结果如下图所示:
再继续按合法的字符,结果如下:
9、Java-GUI(列出指定目录)
本次学习中,我们将要实现“列出指定目录内容”的功能,这个功能就好像我们windows中文件查找,我们在文本对话框中的地址栏输入指定的目录点击“转到”,将会列出该目录下的所有内容。现在我们将一步一步完成。
第一步:将文本框中内容填充到文本域中。代码如下:
import java.awt.*;
import java.awt.event.*;
class MyWindowDemo
{
private Frame f;
private Button b;
private TextField tf;
private TextArea ta;
MyWindowDemo()
{
init();
}
public void init()
{
f=new Frame("my frame");
b=new Button("转到");
tf=new TextField(40);
ta=new TextArea(25,70);
f.setBounds(200,300,600,700);
f.setLayout(new FlowLayout());
f.add(tf);
f.add(b);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
/*
实现功能:在文本框中输入内容,让后点击按钮,
文本框中的内容就在文本域中出现,而文本框被 清空。
*/
/*
调用Textfield的父类TextCompon中的方法:
getText()来获取文本框组件tf中的内容。
*/
String text=tf.getText();
/*
调用TextArea的父类TextCompon中的方法:
setText()来将此文本域组件显示的文本
设置为指定文本。
*/
ta.setText(text);
/*清空文本框*/
tf.setText("");
}
});
}
public static void main(String[] args)
{
new MyWindowDemo();
}
}
编译运行后的逐步结果图如下:
第二步:现在实现功能:在文本框中输入指定的目录,文本域中出现目录下的对应内容。代码如下:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class MyWindowDemo
{
private Frame f;
private Button b;
private TextField tf;
private TextArea ta;
MyWindowDemo()
{
init();
}
public void init()
{
f=new Frame("my frame");
b=new Button("转到");
tf=new TextField(40);
ta=new TextArea(25,70);
f.setBounds(200,300,600,700);
f.setLayout(new FlowLayout());
f.add(tf);
f.add(b);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String dirPath=tf.getText();
/*
用到io流中的一个类:File。
文件和目录路径名的抽象表示形式。
*/
//将dirPath封装成一个文件对象,
//这样才可以list。
//通过将给定路径名字符串
//转换为抽象路径名来创建
//一个新 File 实例。
File dir=new File(dirPath);
if(dir.exists()&&dir.isDirectory())
{
String names[] =dir.list();
for(String name:names)
{
ta.setText(name+"\r\n");
}
}
}
});
}
public static void main(String[] args)
{
new MyWindowDemo();
}
}
编译运行后,发现,不论指定什么目录,文本域中都只有一条内容。这是因为,我们遍历一个写入一个,前一条内容被后面一条内容覆盖掉了。我们可以用一个容器先将它存起来。一起写入。给力的是,这个功能TextArea已经把我们完成了,在它里边已经有了一个对应方法append(),将给定文本追加到文本区的当前文本。核心代码如下:
for(String name:names)
{
ta.setText(name+"\r\n");
}
编译运行后结果如下:
这时我们将文本框中的内容指定为F:\,结果如下图所示:
我们发现,不同的f:\路径下的内容被添加在了c:\路径下内容的后面。因此,我们要记得清空,核心代码如下:
if(dir.exists()&&dir.isDirectory())
{
ta.setText("");
String names[] =dir.list();
for(String name:names)
{
ta.append(name+"\r\n");
}
}
10、Java-GUI(对话框)
在上一次的“列出指定目录内容”的学习中,我们其实还有一个问题没有解决,那就是当我们在文本框中指定一个不存在的目录时,我们点击按钮并没有什么现象发生。这是因为我们只有了if语句,而没有考虑到else的情况。那么我们现在将提供几种方法。温馨提示:代码中加粗部分是解决问题的关键。
方法一:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class MyWindowDemo1
{
private Frame f;
private TextField tf;
private Button but;
private TextArea ta;
MyWindowDemo1()
{
init();
}
public void init()
{
f=new Frame("my frame");
but=new Button("转到");
tf=new TextField(60);
ta=new TextArea(40,80);
f.setBounds(100,200,500,600);
f.setLayout(new FlowLayout());
f.add(tf);
f.add(but);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
but.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String dirPath=tf.getText();
File dir=new File(dirPath);
if(dir.exists()&&dir.isDirectory())
{
ta.setText("");
String[] names=dir.list();
for(String name:names)
{
ta.append(name+"\r\n");
tf.setText("");
}
}
else
{
tf.setText("");
System.out.println("指定目录不存在,请重新输入!");
}
}
});
}
public static void main(String[] args)
{
new MyWindowDemo1();
}
}
编译运行后,结果图如下:
点击“转到”按钮:
但是,实际开发的软件,用户体验的时候,并没有什么控制台可以来显示。因此有:
方法二:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class MyWindowDemo1
{
private Frame f;
private TextField tf;
private Button but;
private TextArea ta;
MyWindowDemo1()
{
init();
}
public void init()
{
f=new Frame("my frame");
but=new Button("转到");
tf=new TextField(50);
ta=new TextArea(40,80);
f.setBounds(100,200,500,600);
f.setLayout(new FlowLayout());
f.add(tf);
f.add(but);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
but.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String dirPath=tf.getText();
File dir=new File(dirPath);
if(dir.exists()&&dir.isDirectory())
{
ta.setText("");
String[] names=dir.list();
for(String name:names)
{
ta.append(name+"\r\n");
tf.setText("");
}
}
else
{
ta.setText("指定路径不存在,请重新输入!");
tf.setText("");
}
}
});
}
public static void main(String[] args)
{
new MyWindowDemo1();
}
}
编译运行后,结果图如下:
点击“转到”按钮:
但是,这种方法还是不是很完善,我们想要windows中的一样,当指定路径不存在的时候,会出现一个提示对话框。因此有:
方法三:
用到Window类的子类Dialog。Dialog中一般有提示信息,但是文字是不能直接加在组件上的,想到Label,它可以封装文字,然后将Label对象加到Dialog中。注意Dialog的默认布局是边界布局,因此需指定为流式布局。看一下Dialog的构造函数:Dialog(Frame owner,String title, boolean modal) :构造一个最初不可见的 Dialog,它带有指定的所有者 Frame、标题和模式。模式是指:如果为true,表示一定要操作对话框,否则窗体不能操作,如果为false,表示可以不操作对话框,可以去操作窗体。
Dialog因为也是Window的子类,因此和Frame一样设置。也会用到父类Window中的setBounds()、setVisible()等方法来对自身进行一些基本设置。
Label的构造函数:Label() 构造一个空标签。还有类中的setText()方法也会用到。setText(String text) 将此标签的文本设置为指定的文本。
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class MyWindowDemo1
{
private Frame f;
private TextField tf;
private Button but;
private TextArea ta;
private Dialog d;
private Label lab;
private Button but1;
MyWindowDemo1()
{
init();
}
public void init()
{
f=new Frame("my frame");
but=new Button("转到");
tf=new TextField(50);
ta=new TextArea(40,80);
f.setBounds(100,200,600,700);
f.setLayout(new FlowLayout());
f.add(tf);
f.add(but);
f.add(ta);
//对话框的初始化。
d=new Dialog(f,"提示信息",true);
d.setBounds(100,200,250,200);
d.setLayout(new FlowLayout());
lab=new Label();
d.add(lab);
but1=new Button("确定");
d.add(but1);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
but.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String dirPath=tf.getText();
File dir=new File(dirPath);
if(dir.exists()&&dir.isDirectory())
{
ta.setText("");
String[] names=dir.list();
for(String name:names)
{
ta.append(name+"\r\n");
tf.setText("");
}
}
else
{
/*
Dialog d;
d=new Dialog(f,"提示信息",true);
d.setBounds(100,200,250,200);
d.setLayout(new FlowLayout());
Button but1;
but1=new Button("确定");
d.add(but1);
Label lab;
lab=new Label();
lab.setText("您输入的信息"+dirPath+"错误,请重新输入!");
d.add(lab);
d.setVisible(true);
*/
lab.setText("您输入的信息"+dirPath+"错误,请重新输入!");
d.setVisible(true);
}
}
});
d.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
d.setVisible(false);
}
});
but1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
d.setVisible(false);
}
});
}
public static void main(String[] args)
{
new MyWindowDemo1();
}
}
编译运行后,结果图如下所示:
点击“确定”按钮或者对话框的关闭按钮:
拓展:现在想实现我们在文本框这种指定目录,按“回车”键之后,如果路径存在,则文本域中会出现内容;如果路径不存在,则会弹出对话框。而不用在去点击“转到”按钮。
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class MyWindowDemo1
{
private Frame f;
private TextField tf;
private Button but;
private TextArea ta;
private Dialog d;
private Label lab;
private Button but1;
MyWindowDemo1()
{
init();
}
public void init()
{
f=new Frame("my frame");
but=new Button("转到");
tf=new TextField(50);
ta=new TextArea(40,80);
f.setBounds(100,200,600,700);
f.setLayout(new FlowLayout());
f.add(tf);
f.add(but);
f.add(ta);
//对话框的初始化。
d=new Dialog(f,"提示信息",true);
d.setBounds(100,200,250,200);
d.setLayout(new FlowLayout());
lab=new Label();
d.add(lab);
but1=new Button("确定");
d.add(but1);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
tf.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode()==KeyEvent.VK_ENTER)
{
String dirPath=tf.getText();
File dir=new File(dirPath);
if(dir.exists()&&dir.isDirectory())
{
ta.setText("");
String[] names=dir.list();
for(String name:names)
{
ta.append(name+"\r\n");
//tf.setText("");
}
}
else
{
tf.setText("");
lab.setText("您输入的信息"+dirPath+"错误,请重新输入!");
d.setVisible(true);
}
}
}
});
but.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String dirPath=tf.getText();
File dir=new File(dirPath);
if(dir.exists()&&dir.isDirectory())
{
ta.setText("");
String[] names=dir.list();
for(String name:names)
{
ta.append(name+"\r\n");
//tf.setText("");
}
}
else
{
tf.setText("");
lab.setText("您输入的信息"+dirPath+"错误,请重新输入!");
d.setVisible(true);
}
}
});
d.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
d.setVisible(false);
}
});
but1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
d.setVisible(false);
}
});
}
public static void main(String[] args)
{
new MyWindowDemo1();
}
}
代码优化:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class MyWindowDemo1
{
private Frame f;
private TextField tf;
private Button but;
private TextArea ta;
private Dialog d;
private Label lab;
private Button but1;
MyWindowDemo1()
{
init();
}
public void init()
{
f=new Frame("my frame");
but=new Button("转到");
tf=new TextField(50);
ta=new TextArea(40,80);
f.setBounds(100,200,600,700);
f.setLayout(new FlowLayout());
f.add(tf);
f.add(but);
f.add(ta);
//对话框的初始化。
d=new Dialog(f,"提示信息",true);
d.setBounds(100,200,250,200);
d.setLayout(new FlowLayout());
lab=new Label();
d.add(lab);
but1=new Button("确定");
d.add(but1);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
tf.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode()==KeyEvent.VK_ENTER)
{
showDir();
}
}
});
but.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
showDir();
}
});
d.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
d.setVisible(false);
}
});
but1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
d.setVisible(false);
}
});
}
private void showDir()
{
String dirPath=tf.getText();
File dir=new File(dirPath);
if(dir.exists()&&dir.isDirectory())
{
ta.setText("");
String[] names=dir.list();
for(String name:names)
{
ta.append(name+"\r\n");
}
}
else
{
tf.setText("");
lab.setText("您输入的信息"+dirPath+"错误,请重新输入!");
d.setVisible(true);
}
}
public static void main(String[] args)
{
new MyWindowDemo1();
}
}
11、Java-GUI(菜单)
什么是菜单:
一般步骤:
s1:新建一个窗口
Frame f=new Frame("演示");
s2:新建一个菜单栏
MenuBar mb=new MenuBar();
s3:新建一个菜单
Menu m=new Menu("文件");
s4:新建一个菜单项
MenuItem mi=new MenuItem("打开");
s5:将窗口和菜单栏关联
f.setMenuBar();
s6:将菜单项添加进菜单
m.add(mi);
s7:将菜单添加进菜单栏
mb.add(m);
子菜单的效果:
一般步骤:
s1:新建一个窗口
Frame f=new Frame("演示");
s2:新建一个菜单栏
MenuBar mb=new MenuBar();
s3:新建一个菜单
Menu m=new Menu("文件");
s4:新建一个子菜单
Menu subm=new Menu("打开");
s5:将窗口和菜单栏关联
f.setMenuBar();
s6:将子菜单添加进菜单
m.add(subm);
s7:将菜单添加进菜单栏
mb.add(m);
示例:
import java.awt.*;
import java.awt.event.*;
class MyMenuDemo
{
public static void main(String[] args)
{
new MyMenu();
}
}
class MyMenu
{
private Frame f;
private MenuBar mb;
private Menu m;
private MenuItem mi;
MyMenu()
{
init();
}
public void init()
{
f=new Frame();
mb=new MenuBar();
m=new Menu("文件");
mi=new MenuItem("退出");
f.setLayout(new FlowLayout());
f.setBounds(200,100,500,600);
m.add(mi);
mb.add(m);
f.setMenuBar(mb);
myEvent();
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
mi.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
}
}
12、Java-GUI(打开文件)
我们现在想要的一个效果就是像windows中的一样,我们点击文件菜单下面的打开菜单项,可以蹦出来一个文件对话框,我们可以选择文件打开,然后文件的内容在文本域中显
示出来。
ps:
① FileDialog(Dialog parent,String title,int mode):创建一个具有指定标题的文件对话框窗口,用于加载或保存文件。
mode可以取值:FileDialog.LOAD:表示打开文件
FileDialog.SAVE:表示保存文件
② String getDirectory():获取选择的文件的所在路径。
③ String getFile():获取选择的文件的名字。
示例:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class MyMenu
{
private FileDialog openDia;
private TextArea ta;
private Frame f;
private MenuBar bar;
private Menu fileMenu ;
private MenuItem openItem ,saveItem,closeItem;
MyMenu()
{
init();
}
public void init()
{
f=new Frame();
bar=new MenuBar();
fileMenu=new Menu("文件");
openItem=new MenuItem("打开");
saveItem=new MenuItem("保存");
closeItem=new MenuItem("关闭");
openDia=new FileDialog(f,"我要打开",FileDialog.LOAD);
ta=new TextArea();
f.setBounds(100,200,600,700);
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.add(closeItem);
bar.add(fileMenu);
f.setMenuBar(bar);
f.add(ta);
myEvent();
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
closeItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
openItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
openDia.setVisible(true);
String dirPath=openDia.getDirectory();
String fileName=openDia.getFile();
System.out.println(dirPath+"::"+fileName);
if(dirPath==null||fileName==null)
return;
ta.setText("");
File f=new File(dirPath,fileName);
try
{
BufferedReader bufr=new BufferedReader(new FileReader(f));
String line=null;
while((line=bufr.readLine())!=null)
{
ta.append(line+"\r\n");
}
bufr.close();
}
catch (IOException ex)
{
throw new RuntimeException("读取失败");
}
}
});
}
public static void main(String[] args)
{
new MyMenu();
}
}
13、Java-GUI(保存文件)
首先,我们得明白一点,在windows中,我们新建一个文件时,点击保存会弹出一个对话框;当我们对已存在的文件修改,点击保存不会弹出对话框。现在我们想用java语言来实现这个功能。
//需求:将文本域中内容保存成一个文本文件。
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class MyMenu
{
private FileDialog openDia;
private FileDialog saveDia;
private File file;
private TextArea ta;
private Frame f;
private MenuBar bar;
private Menu fileMenu ;
private MenuItem openItem ,saveItem,closeItem;
MyMenu()
{
init();
}
public void init()
{
f=new Frame();
bar=new MenuBar();
fileMenu=new Menu("文件");
openItem=new MenuItem("打开");
saveItem=new MenuItem("保存");
closeItem=new MenuItem("关闭");
openDia=new FileDialog(f,"我要打开",FileDialog.LOAD);
saveDia=new FileDialog(f,"我要保存",FileDialog.SAVE);
ta=new TextArea();
f.setBounds(100,200,600,700);
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.add(closeItem);
bar.add(fileMenu);
f.setMenuBar(bar);
f.add(ta);
myEvent();
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
closeItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
openItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
openDia.setVisible(true);
String dirPath=openDia.getDirectory();
String fileName=openDia.getFile();
System.out.println(dirPath+"::"+fileName);
if(dirPath==null||fileName==null)
return;
ta.setText("");
file=new File(dirPath,fileName);
try
{
BufferedReader bufr=new BufferedReader(new FileReader(file));
String line=null;
while((line=bufr.readLine())!=null)
{
ta.append(line+"\r\n");
}
bufr.close();
}
catch (IOException ex)
{
throw new RuntimeException("读取失败");
}
}
});
saveItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(file==null)
{
saveDia.setVisible(true);
String dirPath=saveDia.getDirectory();
String fileName=saveDia.getFile();
System.out.println(dirPath+"::"+fileName);
file=new File(dirPath,fileName);
}
try
{
BufferedWriter bufw=new BufferedWriter(new FileWriter(file));
String text=ta.getText();
bufw.write(text);
bufw.flush();
bufw.close();
}
catch (IOException ex)
{
throw new RuntimeException("写入失败");
}
}
});
}
public static void main(String[] args)
{
new MyMenu();
}
}
14、Java-GUI(jar包双击执行)
之前,我们写的java程序,都需要在dos命令行中,输入
相关的命令才能执行,现在我们想把它变成一个类似于一个图标一样,双击就可以被执行。
图形化界面的另外一种执行方式:
就以下面程序为例:
package mymenu;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class MyMenu
{
private FileDialog openDia;
private FileDialog saveDia;
private File file;
private TextArea ta;
private Frame f;
private MenuBar bar;
private Menu fileMenu ;
private MenuItem openItem ,saveItem,closeItem;
MyMenu()
{
init();
}
public void init()
{
f=new Frame();
bar=new MenuBar();
fileMenu=new Menu("文件");
openItem=new MenuItem("打开");
saveItem=new MenuItem("保存");
closeItem=new MenuItem("关闭");
openDia=new FileDialog(f,"我要打开",FileDialog.LOAD);
saveDia=new FileDialog(f,"我要保存",FileDialog.SAVE);
ta=new TextArea();
f.setBounds(100,200,600,700);
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.add(closeItem);
bar.add(fileMenu);
f.setMenuBar(bar);
f.add(ta);
myEvent();
f.setVisible(true);
}
public void myEvent()
{
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
closeItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
openItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
openDia.setVisible(true);
String dirPath=openDia.getDirectory();
String fileName=openDia.getFile();
System.out.println(dirPath+"::"+fileName);
if(dirPath==null||fileName==null)
return;
ta.setText("");
file=new File(dirPath,fileName);
try
{
BufferedReader bufr=new BufferedReader(new FileReader(file));
String line=null;
while((line=bufr.readLine())!=null)
{
ta.append(line+"\r\n");
}
bufr.close();
}
catch (IOException ex)
{
throw new RuntimeException("读取失败");
}
}
});
saveItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(file==null)
{
saveDia.setVisible(true);
String dirPath=saveDia.getDirectory();
String fileName=saveDia.getFile();
System.out.println(dirPath+"::"+fileName);
file=new File(dirPath,fileName);
}
try
{
BufferedWriter bufw=new BufferedWriter(new FileWriter(file));
String text=ta.getText();
bufw.write(text);
bufw.flush();
bufw.close();
}
catch (IOException ex)
{
throw new RuntimeException("写入失败");
}
}
});
}
public static void main(String[] args)
{
new MyMenu();
}
}
s1:打开dos命令行,切换到源文件目录下:
javac -d c:\myclass MyMenu.java(c:\myclass必须存在)
现象:在myclass文件中生成5个文件:MyMenu$1.class、
MyMenu$2.class、MyMenu$3.class、MyMenu$4.class、
MyMenu.class。
s2:切换到c:\myclass目录下:
jar -cvf my.jar mymenu
双击my.jar并不能执行。(原因jar包有很多个类文件,我们得告诉jar包那个类文件包含主函数,然后双击jar包,它才会自动去找告诉它的那个类文件去执行。)
s3:我们打开.jar,找到.MF文件,它里边都是一些配置信息,我们可以在里边添加Main-class,但是它不可以直接写,因此我们在C:\myclass目录下建立一个1.txt文件,在1.txt文件中写入:
Main-Class:空格+MyMenu.MyMenu+回车 (固定格式,英文)
然后在c:\myclass目录下:
jar -cvfm my.jar 1.txt mymenu
它有一个前提:必须在系统中注册过。
如果是xp:
工具-文件夹选项-文件类型-找到JAR类型-高级-有“open”操作(如果没有,可以自己新建一个)-编辑(让你填写“用于执行操作的应用程序”就是关联一下,比如:D:\jre6\bin\javaw.exe -jar,可能已经帮你填好了,是因为jdk的安装是双击安装的,而不是在别处拷过来的。)
如果是win7:
开始-运行-regedit:
|--HKEY_CLASSES_ROOT
|--Application
|--javaw.exe
|--shell
|--open
|--command
在右边的区域内选中,双击打开,编辑数值数据:D:\jre6\bin\javaw.exe -jar。
2015-12-20至2015-12-25著