01_GUI_初步_Frame_and_Panel_1
知识点:AWT,组件与容器,布局管理器,事件处理,JAVA 图形,Window 事件
使用java.awt 包来实现java GUI 图形编程实现。
关键类Component,Container,
Component - Menu Component
/ \
Button,TextField ... Container
/ \
Window Panel
/ \ \
Frame Dialog applet
两种常用的Container:
Window
Panel
Window 有分两种:
Dialog
Frame
TestFrame.java
import java.awt.*;
public class TestFrame {
public static void main( String args[]) {
Frame f = new Frame("My First Test");
f.setLocation(300, 300);
f.setSize( 170,100);
f.setBackground( Color.blue);
f.setResizable(false);
f.setVisible( true);
}
}
注意应该设置visible 为 true ,否则会出现窗口不能显示的问题。
但是上面的程序结果出来的窗口不能关掉,所以需要下面的知识来解决.
06 事件模型- ActionEvent
事件监听
例子:
/* 范例名称:Java事件处理举例
* 源文件名称:TestActionEvent.java
* 要 点:
* 1. Java事件处理机制
* 2. 事件源、事件监听器概念及作用
* 3. 如何在一个现有组件上注册监听器
*/
import java.awt.*;
import java.awt.event.*;
public class TestActionEvent {
public static void main(String args[]) {
Frame f = new Frame("Test");
Button b = new Button("Press Me!");
Monitor bh = new Monitor();
b.addActionListener(bh);
f.add(b,BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
}
class Monitor implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("a button has been pressed");
}
}
理解ActionEvent 类,ActionListener 接口
事件源,事件监听器的概念及作用
java 的事件处理机制,定义一个事件源对象,定义一个监听器,在该事件源对象上添加事件监听器,
如何在一个现有的组件上注册监听器.
07 ActionEvent-2
一个监听器监听两个对象,存在一个问题:这个监听器对象怎么区分两个事件源.
事件源里有一个ActionCommand 属性.这也是一种命令模式.
例子:
/* 范例名称:Java事件处理举例
* 源文件名称:TestActionEvent2.java
* 要 点:
* 1. 一个事件源组件上可以同时注册多个监听器
* 2. 一个监听器对象可以同时注册到多个事件源组件上
* 3. 事件源的信息可以随它所触发的事件自动传递到所有注册过的监听器
*/
import java.awt.*;
import java.awt.event.*;
public class TestActionEvent2 {
public static void main(String args[]) {
Frame f = new Frame("Test");
Button b1 = new Button("Start");
Button b2 = new Button("Stop");
Monitor2 bh = new Monitor2();
b1.addActionListener(bh);
b2.addActionListener(bh);
// b2.setActionCommand("game over");
f.add(b1,"North");
f.add(b2,"Center");
f.pack();
f.setVisible(true);
}
}
class Monitor2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("a button has been pressed," +
"the relative info is:\n " + e.getActionCommand());
}
}
08 TextField ActionEvent
例子:
import java.awt.*;
import java.awt.event.*;
public class TFActionEvent {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new TFFrame();
}
}
class TFFrame extends Frame
{
TFFrame()
{
TextField tf = new TextField();
// 设置回显字符为*
tf.setEchoChar('*');
add(tf);
tf.addActionListener(new TFActionListener());
pack();
setVisible(true);
}
}
class TFActionListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
TextField tf = (TextField)e.getSource();
System.out.println(tf.getText());
//tf.setText("");
}
}
09- 持有对方引用
(BorderLayout,FlowLayout)
仔细体会这里面采用的三种方案,回头自己实现以下来测试理解。
用java 写一个加法运算器.当点击= Button 时,输出结果.
掌握具体问题的设计方案,
方案二实际上用了门面设计模式。
例子:
import java.awt.*;
import java.awt.event.*;
public class TFMath {
public static void main(String[] args) {
new TFFrame().launchFrame();
}
}
class TFFrame extends Frame {
TextField num1, num2, num3;
public void launchFrame() {
num1 = new TextField(10);
num2 = new TextField(10);
num3 = new TextField(15);
Label lblPlus = new Label("+");
Button btnEqual = new Button("=");
btnEqual.addActionListener(new MyMonitor());
setLayout(new FlowLayout());
add(num1);
add(lblPlus);
add(num2);
add(btnEqual);
add(num3);
pack();
setVisible(true);
}
private class MyMonitor implements ActionListener {
public void actionPerformed(ActionEvent e) {
int n1 = Integer.parseInt(num1.getText());
int n2 = Integer.parseInt(num2.getText());
num3.setText("" + (n1+n2));
}
}
}
//class MyMonitor implements ActionListener {
//TextField num1, num2, num3;
/*
public MyMonitor(TextField num1, TextField num2, TextField num3) {
this.num1 = num1;
this.num2 = num2;
this.num3 = num3;
}
*/
/*
TFFrame tf = null;
public MyMonitor(TFFrame tf) {
this.tf = tf;
}
public void actionPerformed(ActionEvent e) {
int n1 = Integer.parseInt(tf.num1.getText());
int n2 = Integer.parseInt(tf.num2.getText());
tf.num3.setText("" + (n1+n2));
}
}
*/
10-内部类方案实现
通过参数传递,内部类 来交流信息.
内部类的好处:
1.可以方便的访问外部类的成员。
2.可以防止其它的类访问某一个你不想让它访问的类。(该类不允许或不需要其它类进行访问,只让外部类用它)
3.实现多个接口时方法同名问题,可以用内部类来是实现其中一个接口.
11 - Paint 方法
Graphic 类 画图形
在窗口画一个圆形,长方形
例子:
import java.awt.*;
public class TestPaint {
public static void main(String[] args) {
new PaintFrame().launchFrame();
}
}
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.green);
g.fillRect(80,80,40,40);
g.setColor(c);
}
}
关于paint方法自动调用问题,什么时候会被自动调用,
该paint 方法是重写了Container 的paint 方法
拿到笔之后应该保存原来的颜色以便画完后恢复该颜色
12 - Adapter and repaint
练习:画一条直线(两点确定一条直线)
鼠标事件适配器-这个的作用,实际上这个mouseAdapter 实现的都是一些空实现。跟直接实现接口比,它的优点是不用实现或写所有的接口里的方法(有的时候我们并不需要实现所有的方法)
抽象类MouseAdapter 实现了MouseListener 接口,可以使用其子类作为MouseEvent 的监听器
例子:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class MyMouseAdapter{
public static void main(String args[]) {
new MyFrame("drawing...");
}
}
class MyFrame extends Frame {
ArrayList points = null;
MyFrame(String s) {
super(s);
points = new ArrayList();
setLayout(null);
setBounds(300,300,400,300);
this.setBackground(new Color(204,204,255));
setVisible(true);
this.addMouseListener(new Monitor());
}
public void paint(Graphics g) {
Iterator i = points.iterator();
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){
points.add(p);
}
}
class Monitor extends MouseAdapter {
public void mousePressed(MouseEvent e) {
MyFrame f = (MyFrame)e.getSource();
f.addPoint(new Point(e.getX(),e.getY()));
f.repaint();
}
}
关于事件源的概念的理解:把监听器加到哪一个component ,这个component 就是事件源
Frame 的repaint 方法重新调用paint 方法
repaint 方法 先调用 update 方法, 然后再调用paint 方法。
我们无法直接调用paint 方法,因为paint 方法需要输入一个参数Graphics
update 方法实现双缓冲?
13- Window Event and 匿名类
问题: 迭代器也还需要理解(后面跟的类型是什么概念<Point>
解决关闭窗口的问题
每一个事件都对应一个事件处理方法。
例子:
import java.awt.*;
import java.awt.event.*;
public class TestWindowClose {
public static void main(String args[]) {
new MyFrame55("MyFrame");
}
}
class MyFrame55 extends Frame {
MyFrame55(String s) {
super(s);
setLayout(null);
setBounds(300, 300, 400, 300);
this.setBackground(new Color(204, 204, 255));
setVisible(true);
//this.addWindowListener(new MyWindowMonitor());
this.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
System.exit(-1);
}
});
}
/*
class MyWindowMonitor extends WindowAdapter {
public void windowClosing(WindowEvent e) {
setVisible(false);
System.exit(0);
}
}
*/
}
为什么需要匿名类? 什么时候需要匿名类?
语句比较少,方法比较简单,不是经常用,此时可以用 new 接口(抽象类)(){});
14- KeyEvent
匿名类(带有属性)的例子:
/* 范例名称:匿名类在事件处理中的使用
* 源文件名称:TestAnonymous2.java
* 要 点:
* 1. 匿名类只能是内部类
* 2. 匿名类的两种创建方式----既可以继承父类、也可以单重实现接口
*/
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");
public TestAnonymous2(){
f.add(b1,"North");
f.add(tf,"South");
b1.addActionListener(new ActionListener(){
private int i;
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);
}
public static void main(String args[]) {
new TestAnonymous2();
}
}
KeyEvent 的常量字段VK_UP,及getKeyCode() 方法,里面的KeyCode 概念是什么?
02_GUI_初步_Frame_and_Panel_2
例子:
创建Frame 的两种方式,
1. new Frame()
2. 写一个类继承 Frame
在Frame 里加Panel
import java.awt.*;
public class TestPanel {
public static void main(String args[]) {
Frame f =
new Frame("Java Frame with Panel");
Panel p = new Panel(null);
f.setLayout(null);
f.setBounds(300,300,500,500);
f.setBackground(new Color(0,0,102));
p.setBounds(50,50,400,400);
p.setBackground(new Color(204,204,255));
f.add(p);
f.setVisible(true);
}
}
多个panel :
import java.awt.*;
public class TestMultiPanel {
public static void main(String args[]) {
new MyFrame2("MyFrameWithPanel",300,300,400,300);
}
}
class MyFrame2 extends Frame{
private Panel p1,p2,p3,p4;
MyFrame2(String s,int x,int y,int w,int h){
super(s);
setLayout(null);
p1 = new Panel(null); p2 = new Panel(null);
p3 = new Panel(null); p4 = new Panel(null);
p1.setBounds(0,0,w/2,h/2);
p2.setBounds(0,h/2,w/2,h/2);
p3.setBounds(w/2,0,w/2,h/2);
p4.setBounds(w/2,h/2,w/2,h/2);
p1.setBackground(Color.BLUE);
p2.setBackground(Color.GREEN);
p3.setBackground(Color.YELLOW);
p4.setBackground(Color.MAGENTA);
add(p1);add(p2);add(p3);add(p4);
setBounds(x,y,w,h);
setVisible(true);
}
}
03 - 布局管理器
如果往一个Frame 里放一个Panel ,那么Panel 放在哪里呢?
有两种方法:
一种自己设置这个Panel 的位置
另一种用java 提供的布局管理器类
FlowLayout 类实现了LayoutManager 接口
04 - 布局管理器2