GUI编程
1. dialog分为两种:model,models,model出现的时候,你必须对它进行处理,否则主程序无法运行,models,没事,你出不出理都没有关系,主程序照样运行.
2. 在new一个窗口的时候只是内存里面的一个对象而已,它没有显示呢.
3. 能继承Frame类创建自己的Frame类最好就自己创建,不要去直接的new一个Frame出来,因为自己创建的Frame类可以有自己的成员变量.
4. RGB,三原色,每个颜色用一个字节表示,所以每个颜色的数值大小从0-255.
5. 方法的调用:要记住,在一个类里面,一个方法可以直接的被本类里面的其他的方法调用,也可以被本类的构造方法调用,更可以被继承它的子类所直接的调用,调用的时候直接的调用就行了.
public class TPerson extends Person {
public static void main(String[] args) {
TPerson t=new TPerson();
}
public TPerson(){
super.d2();
this.d2();this.age=20;
this.name="dada";
// this.age=20;
// this.name="dada";
/*this.age=20;
*this.name="dada";
* 这两句话放在不同的位置结果
* 是不一样的,如果放在this.d2();
* 之前的话,结果就是this.d2();
* 调用的是父类的方法,但是调用
* 的是子类的参数,如果把他们放在
* 方法调用之后的话,那对不起,即使
* 是用了this关键字,调用的还是父类
* 里面的参数,因为你子类根本就没有
* 给出相应的参数来
*/
}
}
class Person{
String name="tiantian";
int age=20;
public void display(){
}
public void d2(){
System.out.println("Name:\t"+this.name+"\tAge:"+this.age);
}
}
总结:
子类可以调用父类的除了构造方法之外任意的方法,在调用的过程中,如果是父类的方法,而且子类中提供了此方法中所对应的参数,那么在子类对此方法进行调用的过程中就会调用子类中的参数,否则也将调用父类中的参数,如果明确的写的是super.方法,那么调用的是父类的方法而且是父类里面的参数,方法在任何的时候,任何的地点都是可以随意的调用的只要符合规范就行,因此如果能够继承一个类最好是继承而不要去使用这个类的本身,因为继承可以带来更好的扩充性能,可以为此类添加自己的变量.
这个颜色是比较好看的颜色:204,,204,205;
6. 在添加组件的时候最好使用BorderLayout.North;这种风格,因为这种情况下不容易出错,即便是出错也会被编译器给发现,而如果说使用的是”North”这种风格的话,在出现拼写错误的时候,编译器是发现不了错误的,只有在运行期间才会发现错误的,当然这两种的方法都是String类型的,它们的效率是差不多的.
7. 在遇到一个新的类的时候如果想要掌握好它的话,要做两件事
->写一个测试类把里面的属性方法都测试一番就知道它们的用途了
->在自己的项目中去应用它们
8.在一个类里面要访问另一个类事件源对象的话就要用e.getSource()这个方法,它得到的是Object类型的对象,所以再把它强制的转换一下就成为了跟事件源一样的对象了,其实强制转换的过程就是把指针指向同一个对象的过程,例如下面的示例中使用的就是这种方法:
import java.awt.Frame;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestGetSource {
public static void main(String[] args) {
MyF m=new MyF();
}
}
class MyF extends Frame {
public MyF() {
TextField tf=new TextField();
add(tf);
//ActionListener LTF = null;
tf.addActionListener( new LTF());
setVisible(true);
pack();
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
//super.windowClosed(e);
System.exit(0);
}
});
}
}
class LTF implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
TextField tf=(TextField)e.getSource();
System.out.println(tf.getText());
tf.setText("");
}
}
注意:用tf.setEchoChar('*');来设置的话结果就是它在显示的时候是*而不是具体的输入的字符,不过在读取的时候它还是你所输入的字符,其实对于JPasswordFiled()结果也是一样的,在获取的时候也是输入的真正的字符串.
9.如果要实现这样的功能就是把两个int类型的值经过运算后打印出来结果,比较简便的写法是这样的:
int a=4;
int b=8;
System.out.println(""+(a+b));
这样即实现了运算,又把运算的结果给打印了出来.
10.持有对方的引用
public class TestFacade {
public static void main(String[] args) {
F f=new F();
}
}
class F extends Frame {
TextField tf1,tf2,tf3;
public F(){
tf1=new TextField(10);
Label l=new Label("+");
tf2=new TextField(10);
Button b=new Button("=");
b.addActionListener(new Monitor1(this));
tf3=new TextField(15);
add(tf1);
add(l);
add(tf2);
add(b);
add(tf3);
setLayout(new FlowLayout());
setVisible(true);
pack();
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
super.windowClosing(e);
System.exit(0);
}
});
}
}
class Monitor1 implements ActionListener {
F f;
public Monitor1(F f){
this.f=f;
}
//这个地方这么用是为了持有要处理的对象的属性的引用才这么做的.
/*
* 这个叫做facade,是表面的意思,当然也可以这样做就是在自己
* 这边把actionPerformed(ActionEvent e)中将要用到的都给
* 定义到上面的构造方法中去,然后再上面的类被调用的地方把F类
* 具体的自己需要的组件给传入进去,但是那样做实在
* 1.浪费时间
* 2.看上去很费劲,而且在用的时候更容易糊涂
* 3.代码的执行效率很低
* 而上面第一种方法则是相当于在监听器被初始化的时候就把监听器
* 执行任务要用到的对象的引用给传进来了,这个太好了,那就可以根
* 据这个监听把事件给处理好.
*/
@Override
public void actionPerformed(ActionEvent e) {
int a1=Integer.parseInt(f.tf1.getText());
int a2=Integer.parseInt(f.tf2.getText());
f.tf3.setText(""+(a1+a2));
}
}
11.利用内部类来实现持有对方的引用
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestInnerClass {
public static void main(String[] args) {
ChildFrame cf=new ChildFrame();
}
}
class ChildFrame extends Frame {
TextField tf1,tf2,tf3;
public ChildFrame(){
tf1=new TextField(10);
Label l=new Label("+");
tf2=new TextField(10);
Button b=new Button("=");
b.addActionListener(new Monitor());
tf3=new TextField(15);
add(tf1);
add(l);
add(tf2);
add(b);
add(tf3);
setLayout(new FlowLayout());
setVisible(true);
pack();
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
super.windowClosing(e);
System.exit(0);
}
});
}
class Monitor implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int num1=Integer.parseInt(tf1.getText());
int num2=Integer.parseInt(tf2.getText());
tf3.setText(""+(num1+num2));
}
}
}
这里用的是内部类来实现持有对方的引用的,内部类的好处是:
->可以方便的访问包装类的成员
->可以更清楚的组织逻辑,防止不应该被其他类访问的类进行访问,其实这种监听器就应该作为内部类来使用,因为其他的类也没有必要来调用它们,所以最好写成private这样的话,就可以从根本上防止其他的类来调用它.
->使用的时机:该类不允许或者不需要其他类来访问时,而且内部类不需要创建构造方法,它可以随便的访问外部类的成员.
->如果在内部类前面加上private则只有本类可以访问,其他的都不可以访问了,即便是同一个.java文件里面的其他类也是无法访问到的.
内部类还有其他的用途:
有两个接口interface1(),interface2(),都定义了方法f(),返回值类型一样,方法所需要传入的参数列表也一样,有一个类,两个接口都实现了,怎么办,它们因为不构成重载,所以也要用内部类来实现如下:
public class TestTwoInterface implements itf1 {
@Override
public void d() {
}
private class Child implements itf2 {
@Override
public int d() {
// TODO Auto-generated method stub
return 0;
}
}
}
interface itf1 {
void d();
}
interface itf2 {
int d();
}
方法重载:
->参数列表必须不同
->返回类型可以不同,也可以相同.
因此对于方法重载来说重要的只有一条:参数列表必须不一样.
12.适配器的作用:
适配器的作用是连接接口与实现类的纽带,它是抽象类,对于它实现接口中所定义的所有方法,它都提供的全部都是空实现,它是抽象类,因为它本身不需要实现,它也不知道究竟实现类要怎样去实现,所以它是空的实现,而对于实现类来说,它们从适配器那里继承而来,因此它们可以重写适配器的任意多个方法,也就是根据自己的需要去重写需要重写的方法,对于它用不到的就可以不去管它们了,试想一下,如果没有适配器,那么每个实现事件的类都必须要实现监听器里面的每一个方法,那么不要说这些类要每个都写了,就是只写自己需要的那几个也够呛了,因为那么多的空的方法多占空间啊!而适配器就解决了这个问题,其实也相当于是一个分层的思维,看来分层的思维是无处不在啊!
实际上,抽象的方法可以不去实现接口中的全部方法,而可以只是实现其中的一部分,但是对于适配器而言就不是了,它的任务是连接接口和实现类,如果它不为接口中的每一个方法提供空实现的话,那么继承适配器的实现类就还要去实现接口所定义的而且没有被适配器所实现的方法,这就跟实现类的初衷背道而驰了,因为它必须要去实现接口中的方法,尽管这个方法可能它并不需要.
public class TestMouseAdapter {
public static void main(String[] args) {
GrandChild gc=new GrandChild();
gc.d1(10);
}
}
interface intface1 {
void d1();
void d2();
void d3();
}
abstract class Child1 implements intface1 {
public void d1(){}
public void d2(){}
public void d3(){}
}
class GrandChild extends Child1 {
public void d1(int i){
System.out.println("传入的数据位"+i);
}
}
13.paint()方法和repaint()方法,及update()方法paint()方法在窗体被显示的时候就会被自动调用,而repaint()方法是在窗体被改变的时候比如下列情况之一的时候会被自动调用的.
->最大化放大或者最小化缩小或者中间化
->被其他的窗体所覆盖之后又显示的时候
所以如果有一个程序需要根据鼠标的事件而去重画界面的话那么就要在鼠标事件中去调用repaint()方法,比如画画的软件,如果我画一次就要去重新的去调整窗体大小来显示的话,那就太丢人了,所以看下面的程序.
public class PaintPoints {
public static void main(String[] args) {
new FramePoint();
}
}
class FramePoint extends Frame {
ArrayList<Point> Points=new ArrayList<Point>();
public FramePoint(){
addMouseListener(new MouseMonitor());
setBounds(100, 100, 600, 400);
setBackground(new Color(204,204,255));
setVisible(true);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
super.windowClosing(e);
System.exit(0);
}
});
}
public void paint(Graphics g){
Iterator<Point> i=Points.iterator();
while(i.hasNext()){
Point p=(Point)i.next();
g.fillOval(p.x,p.y, 5, 5);
//p.getX();与p.X有什么区别?
/*区别在于p.x/p.y得到的是整数
* 而p.getX()/p.getY()得到的
* 是double类型的数据.
*/
}
}
public void addPoint(Point p){
Points.add(p);
}
}
class MouseMonitor extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e){
FramePoint fp=(FramePoint)e.getSource();
fp.addPoint(new Point(e.getX(), e.getY()));
fp.repaint();
}
}
在程序的内部调用的过程是repaint()->update()->paint().
14.匿名内部类
匿名内部类实际上是用的是对抽象类的一个内部实例化
看下面的程序就知道了.
通常情况是这样写Frame类关闭事件的
// addWindowListener(new WindowAdapter() {
// @Override
// public void windowClosing(WindowEvent e) {
// // TODO Auto-generated method stub
// super.windowClosing(e);
// System.exit(0);
// }
// });
而这个地方则把对抽象类WindowAdapter()给实例化了.
public class PaintPoints {
public static void main(String[] args) {
new FramePoint();
}
}
class FramePoint extends Frame {
ArrayList<Point> Points=new ArrayList<Point>();
public FramePoint(){
setBounds(100, 100, 600, 400);
setBackground(new Color(204,204,255));
setVisible(true);
addWindowListener(new WindowMonitor());
}
}
class WindowMonitor extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e){
FramePoint f=(FramePoint)e.getSource();
Dialog d=new Dialog(f);
Label l=new Label("对不起,您不能退出!");
d.add(l);
d.setVisible(true);
d.pack();
}
}
使用匿名类的情况:
->方法简单代码量少
->方法不会经常的变动,比较固定.
按说WindowListener有自己的Adapter,MouseListener有自己的Adapter,那么ActionListener也应该有的啊,但是事实上它没有,为什么呢?因为它只有一个方法,所以没有必要建立适配器,这个时候建立适配器反而是多余的.
15.键盘事件的处理.
public class TestKey {
public static void main(String[] args) {
new TestKey().createUI();
}
public void createUI(){
Frame f = new Frame();
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
super.windowClosing(e);
System.exit(0);
}
});
f.addKeyListener(new KeyAdapter() {
int i=0;
@Override
public void keyPressed(KeyEvent e){
//KeyEvent ke=(KeyEvent) e.getSource();
/*
* 要注意在这个地方不可以随便的就去进行强制的
* 转换,因为这个时候的e代表的是整个的Frame而
* 所以如果转换之后用ke.getKeyCode()来调用键
* 的值的话肯定是错的,因为事件的强制转换就是
* 不被允许的,更不可能去进行其他的操作了.
*/
if(e.getKeyCode()==KeyEvent.VK_DOWN){
System.out.println("You Pressed the Down key");
}
if(e.getKeyCode()==KeyEvent.VK_UP){
System.out.println("You Pressed the up key");
}if(e.getKeyCode()==KeyEvent.VK_LEFT){
System.out.println("You Pressed the left key");
}if(e.getKeyCode()==KeyEvent.VK_RIGHT){
System.out.println("You Pressed the right key");
}
}
});
}
}
java GUI编程
最新推荐文章于 2024-08-11 16:01:20 发布