component:可以显示的图文界面(按钮、下拉菜单等)
container:用来容纳其他component的元素
window是可以独立显示的
panel可以容纳其他元素,但是必须附加到window里面才能显示
Frame:可以独立显示的窗口
Dialog:对话框,模态(不处理背后的主程序不能使用)非模态(点不点对话框主程序都能运行)
创建窗口
1.调用Frame类
package gui;
import java.awt.*;
public class TestFrame {
public static void main(String[] args){
Frame f = new Frame("My first Test");
f.setSize(170,100);
f.setBackground(Color.BLACK);
f.setVisible(true);
}
}
2.继承Frame类(可以有自己的成员变量)
package gui;
import java.awt.*;
public class TestFrame2 {
public static void main(String[] args){
MyFrame f1 =
new MyFrame(100,100,200,200,Color.blue);
MyFrame f2 =
new MyFrame(300,100,200,200,Color.YELLOW);
MyFrame f3 =
new MyFrame(100,300,200,200,Color.green);
MyFrame f4 =
new MyFrame(300,300,200,200,Color.magenta);
}
}
class MyFrame extends Frame{
static int id = 0;
MyFrame(int x, int y, int w, int h, Color color ){
super("MyFrame"+ (++id) );
setBackground(color);//这里能直接调用方法是因为继承了Frame
setLayout(null);//布局管理
setBounds(x, y, w, h);
setVisible(true);
}
}
Panel
用add方法将Panel添加进去
package gui;
import java.awt.*;
public class TestPanel {
public static void main(String[] args){
new MyFrame2("haha",300,300,400,300);
}
}
class MyFrame2 extends Frame{
private Panel p1;
MyFrame2(String s, int x, int y, int w, int h){
super(s);
p1 = new Panel(null);
p1.setBounds(w/4, h/4, w/2, h/2);
p1.setBackground(Color.yellow);
setBounds(x,y,w,h);
setVisible(true);
setBackground(Color.BLUE);
add(p1);
setLayout(null);
}
}
布局管理器
每一个容器都有自己的布局管理器,不需要自己设计具体的细节
1.FlowLayout
Panel类默认布局管理器,从左到右排列型,可以设置对其方式,左右,上下的间距
package gui;
import java.awt.*;
public class TestFlowLayout {
public static void main(String[] args){
Frame f = new Frame("Flow Layout");
Button button1 = new Button("ok");
Button button2 = new Button("Open");
Button button3 = new Button("Close");
f.setLayout(new FlowLayout());
f.add(button1);
f.add(button2);
f.add(button3);
f.setSize(100,100);
f.setVisible(true);
}
}
2.BorderLayout
Frame类的默认布局管理器
把区域分成东南西北中四个区域,默认添加到中
每个区域只能加入一个组件Compoment,添加多了会覆盖
package gui;
import java.awt.*;
public class TestBorderLayout {
public static void main(String[] args){
Frame f = new Frame("BorderLayout");
f.add(new Button("BN"), BorderLayout.NORTH);
f.add(new Button("BS"), BorderLayout.SOUTH);
f.add(new Button("BW"), BorderLayout.WEST);
f.add(new Button("BE"), BorderLayout.EAST);
f.add(new Button("BC"), BorderLayout.CENTER);
f.setSize(200,200);
f.setVisible(true);
}
}
3.GridLayout
把空间划分成矩形的单元格
GridLayout(3,4)设置单元格的行和列
pack方法包住里面的按钮,刚好合适
事件管理器
在java.awt.event包下面
要监听什么事件就要实现什么接口,并将其添加到相应的组件上
ActionEvent
package gui;
import java.awt.*;
import java.awt.event.*;
public class TestActionEvent {
public static void main(String[] args){
Frame f = new Frame("Test");
Button b1 = new Button("Start");
Button b2 = new Button("Stop");
Monitor bh = new Monitor();
b1.addActionListener(bh);
b2.addActionListener(bh);
b2.setActionCommand("This is Stop");
f.add(b1, BorderLayout.NORTH);
f.add(b2, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
}
class Monitor implements ActionListener{//监听器,监听什么动作就要实现什么类
public void actionPerformed(ActionEvent e){
System.out.println(e.getActionCommand());//获取当前哪个按钮被触发的标记
}
}
TextField事件监听
文本框输入
在一个类中,想访问另一个类的原对象,可以通过getSource方法,获得事件发生时对象的信息
getSource方法会返回一个父类对象, 要注意强制转化
package gui;
import java.awt.*;
import java.awt.event.*;
public class TestField {
public static void main(String[] args){
new TFFrame("text");
}
}
class TFFrame extends Frame{
TFFrame(String name){//重写构造方法
super(name);
TextField tf = new TextField();
add(tf);
tf.addActionListener(new TFActionListener() );
pack();
setVisible(true);
}
}
class TFActionListener implements ActionListener{
public void actionPerformed(ActionEvent e){
TextField tf = (TextField)e.getSource();//获得监听器的信息,把tf指向上面那个类的文本输入
System.out.println(tf.getText());
tf.setText("");
}
}
密码框的输入
在TextField里加入
tf.setEchoChar('*');
便可以使输入变为星号
持有对方引用
把其他的类作为参数传入,这样在其他的类中可以对这个类中的成员变量进行操作
package gui;
import java.awt.*;
import java.awt.event.*;
public class TFMath {
public static void main(String[] args){
new TFFrame1().launchFrame();//调用启动器方法
}
}
class TFFrame1 extends Frame{
TextField num1,num2,num3;//务必设置成成员变量,这样才可以从别的类访问这些变量
public void launchFrame(){//启动器方法
num1 = new TextField(10);
num2 = new TextField(10);
num3 = new TextField(15);
Label lbplus = new Label("+");//静态的字符
Button btnEqual = new Button("=");
btnEqual.addActionListener(new MyMonitor(this) );//把当前的类作为参数传给其他类
setLayout(new FlowLayout() );
add(num1);
add(lbplus);
add(num2);
add(btnEqual);
add(num3);
pack();
setVisible(true);
}
}
class MyMonitor implements ActionListener{
TFFrame1 tf= null;
public MyMonitor(TFFrame1 tf){//把TFFrame作为参数传进来,这样就获得了该类的引用
this.tf = tf;
}
public void actionPerformed(ActionEvent e){
int n1 = Integer.parseInt(tf.num1.getText());//把两个对话框内的字符串转化为int
int n2 = Integer.parseInt(tf.num2.getText());
tf.num3.setText(String.valueOf(n1+n2));
}
}
内部类
好处:1.可以方便的访问包装类的成员变量成员方法
2.可以防止该类被其他类访问(例如上面的监听器,不需要被别的类访问,所以可以写在Frame内部内,加上Private,不会外部的类访问了)
适时使用:这个类不需要被其他类访问的时候
package gui;
import java.awt.*;
import java.awt.event.*;
public class TFMath {
public static void main(String[] args){
new TFFrame1().launchFrame();//调用启动器方法
}
}
class TFFrame1 extends Frame{
TextField num1,num2,num3;//务必设置成成员变量,这样才可以从别的类访问这些变量
public void launchFrame(){//启动器方法
num1 = new TextField(10);
num2 = new TextField(10);
num3 = new TextField(15);
Label lbplus = new Label("+");//静态的字符
Button btnEqual = new Button("=");
btnEqual.addActionListener(new MyMonitor() );//把当前的类作为参数传给其他类
setLayout(new FlowLayout() );
add(num1);
add(lbplus);
add(num2);
add(btnEqual);
add(num3);
pack();
setVisible(true);
}
class MyMonitor implements ActionListener{//写在了类的内部
public void actionPerformed(ActionEvent e){
int n1 = Integer.parseInt(num1.getText());//把两个对话框内的字符串转化为int
int n2 = Integer.parseInt(num2.getText());
num3.setText(String.valueOf(n1+n2));
}
}
}
Graphics类
每个Component都有一个Paint(Graphics g)方法用于绘图,每次重画该Compoent的时候都会自动调用这个方法(例如切屏等)
Graphics中好多子类可以花不同的图像
Graphics相当于一个画笔,在窗口上绘图
package gui;
import java.awt.*;
public class TestPaint {
public static void main(String[] args){
new PaintFrame().launchFrame();//不需要调用Paint方法,在Frame出现时会自动的调用
}
}
class PaintFrame extends Frame{
public void launchFrame(){
setBounds(200,200,640,480);
setVisible(true);
}
public void paint(Graphics g){//自动回调用这个方法
Color c = g.getColor();
g.setColor(Color.RED);
g.fillOval(50, 50, 30, 30);
g.setColor(Color.black);
g.fillRect(80, 80, 40, 40);
g.setColor(c);//把画笔颜色还原,良好习惯
}
}
鼠标事件适配器
抽象类java.awt.event.MouseAdapter实现了MouseListener接口,可以使用其子类作为MouseEvent的监听器,重写即可
repaint方法可以使窗口重新绘制,过程是先调用repairntupdate-paint
package gui;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class MyMouseAdapter {
public static void main(String[] args){
new MyFrame5("drawing....");
}
}
class MyFrame5 extends Frame{
ArrayList points = null;//创建一个保存点的容器
MyFrame5(String name){
super(name);
points = new ArrayList();
setLayout(null);
setBackground(new Color(204,204,255) );
setBounds(300,300,400,400);
setVisible(true);
addMouseListener( new Monitor1() );//在当前的窗口内添加一个鼠标监听器
}
public void paint(Graphics g){//窗口的画图方法,自动调用
Iterator i = points.iterator();//把所有的点都存在List里,每次刷新再画出
while(i.hasNext()){
Point p = (Point)i.next();
g.setColor(Color.blue);
g.fillOval(p.x, p.y, 10, 10);
}
}
public void addPoint(Point p){//向List中添加点
points.add(p);
}
}
class Monitor1 extends MouseAdapter{//监听器类,用Adapter作用是不用重写多余的方法
public void mouseClicked(MouseEvent e){//监听到事件发生执行此
MyFrame5 f = (MyFrame5)e.getSource();
f.addPoint(new Point(e.getX(),e.getY()));
f.repaint();//这里特别注意要使用repaint方法
}
}
Window事件--内部类
内部类,某各类,只在某个方法内部有效,写在某个方法的参数的位置,没有名字,匿名类
内部类使用的时候这个类比较简单,并且不需要变动的时候比较好用
package gui;
import java.awt.*;
import java.awt.event.*;
public class TestWindowClose {
public static void main(String[] args){
new MyFrame55("window");
}
}
class MyFrame55 extends Frame{
MyFrame55(String name){
super(name);
setLayout(null);
setBounds(300, 300, 400, 400);
setBackground(new Color(204, 204, 255));
setVisible(true);
this.addWindowListener(//内部类的写法,写在括号内
new WindowAdapter(){
public void windowClosing(WindowEvent e){
setVisible(false);
System.exit(-1);
}
}
);
}
}
计数器——action、window监听器内部类
package gui;
import java.awt.*;
import java.awt.event.*;
public class TestAnonymous2 {
Frame f = new Frame("Test");
TextField tf = new TextField(10);
Button b1 = new Button("Start");
TestAnonymous2(){
f.add(b1, BorderLayout.NORTH);
f.add(tf, BorderLayout.SOUTH);
b1.addActionListener(new ActionListener(){//按钮监听器的内部类
private int i=0;
public void actionPerformed(ActionEvent e){
tf.setText(e.getActionCommand() + ++i);
}
}
);
f.addWindowListener(new WindowAdapter(){//窗口关闭
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
f.pack();
f.setVisible(true);
f.setLocation(500,500);
}
public static void main(String[] args){
new TestAnonymous2();
}
}
键盘事件
键盘的每一个按键对应一个虚拟的静态常量在KeyEvent中
对比按键的虚拟编号可以确定是哪个键被按下
package gui;
import java.awt.*;
import java.awt.event.*;
public class TestKey {
public static void main(String[] args){
new KeyFrame().launchFrame();
}
}
class KeyFrame extends Frame{
public void launchFrame(){
setSize(200, 200);
setLocation(300, 300);
addKeyListener(new MykeyMonitor());
setVisible(true);
}
}
class MykeyMonitor extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keycode = e.getKeyCode();//获得键盘的按键
if(keycode == KeyEvent.VK_UP){
System.out.println("up");
}
}
}