【Java进阶学习 第七篇】窗体与监听
窗体基础代码
-
创建新窗体
JFrame frame = new JFrame();
-
设置窗体的大小
frame.setSize(500,800);
-
设置窗体标题
frame.setTitle("这是第一个窗体");
-
修改窗体关闭方式
如果不设置关闭方式,我们的窗体哪怕关掉了,程序也会继续执行
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
或者用下面的都可以实现关闭窗口后结束程序
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-
设置窗体可见
frame.setVisible(true);
设置窗体可见这一行代码,一定要放在整体代码的最下方,因为窗体可能需要加载图片,我们需要先加载最后才显示整体窗口的内容。下面是目前运行效果:
组件
按钮组件JButton
JButton有两个构造方法
JButton btn = new JButton("你点我啊");
JButton btn = new JButton();
控件想展示在窗口上,必须在面板对象上add控件
Frame frame = new Frame();
JButton btn = new JButton("你点我啊");
frame.getContentPane().add(btn);
此时的运行效果
按钮生成了,但是铺满了整个屏幕
为了调整按钮到合适的摆放位置,我们需要先取消上面这中窗体的默认布局layout
//取消窗体的默认布局,需要手动指定组件widget的摆放位置
frame.setLayout(null);
再使用JButton中的setBounds方法,设置按钮到窗体左上角的x与y值,并设置按钮自己的长和宽
public class JFrameDemo1 {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(500,500);
frame.setTitle("这是第一个窗口");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//取消窗体的默认布局,需要手动指定组件widget的摆放位置
frame.setLayout(null);
//创建按钮对象
JButton btn = new JButton("你点我啊");
//setBounds设置控件摆放位置和大小
btn.setBounds(100,100,100,100);
//将按钮添加到窗体的面板对象中
frame.getContentPane().add(btn);
frame.setVisible(true);
}
}
完整代码演示效果
展示组件JLabel
用于展示文本和图片,其实JLabel是一块区域
JLabel也有两种构造方法:
JLabel jl1 = new JLabel(String text);
JLabel jl1 = new JLabel(Icon image);
先使用文本的JLabel
JFrame frame = new JFrame();
frame.setSize(500,500);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLayout(null);
//JLabel展示文本
JLabel jl1 = new JLabel("窗外的麻雀");
jl1.setBounds(50,50,100,20);
frame.getContentPane().add(jl1);
JLabel jl2 = new JLabel("在屋檐上多嘴");
jl2.setBounds(150,50,100,20);
frame.getContentPane().add(jl2);
frame.setVisible(true);
可以看出JLabel是一块区域
接下来加入图片的JLabel
加载图像的代码为
JLabel jlimage1 = new JLabel(new ImageIcon("D:\\image\\xxx.png"));
//展示图形
JLabel jlimage1 = new JLabel(new ImageIcon("D:\\image\\2.png"));
jlimage1.setBounds(50,150,100,100);
frame.getContentPane().add(jlimage1);
注意事项
如果一个区域有两个JLabel图像进行重叠了,展示最早的JLabel
//展示图形
JLabel jlimage1 = new JLabel(new ImageIcon("D:\\image\\2.png"));
jlimage1.setBounds(50,150,100,100);
frame.getContentPane().add(jlimage1);
JLabel jlimage2 = new JLabel(new ImageIcon("D:\\image\\3.png"));
jlimage2.setBounds(50,150,100,100);
frame.getContentPane().add(jlimage2);
展示的还是jlimage1的图像内容
监听事件
分为事件源、事件操作、绑定监听
事件源可能是按钮文本等等,事件操作可以是鼠标单击,键盘输入,绑定监听的意思是当事件源上发生了事件操作,触发执行了某段代码
鼠标监听ActionListener
可以监听鼠标点击或者键盘敲击空格
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("ActionListenerDemo1");
frame.setSize(500, 500);
frame.setLayout(null);
JButton button = new JButton("Click Me");
button.setBounds(50, 50, 100, 100);
frame.getContentPane().add(button);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("我被点了");
}
});
frame.setVisible(true);
格式就是btn.addActionListener(接口的实现类)
这里的参数是一个接口的实现类,所以我们可以用之前学的匿名内部类来创建实现类改写里面的抽象函数。
键盘监听KeyListener
调用格式为
frame.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
});
三个抽象函数中,第一个KeyTyped能监听键盘的类型比较少,不用;第二个KeyPressd意思为按下键盘,第三个KeyRealeased意思为松开键盘
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
//只能监听普通按键 上下左右 fn都不行
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == 37) {
System.out.println("左移动业务代码执行");
} else if (keyCode == 38) {
System.out.println("上移动业务代码执行");
} else if (keyCode == 39) {
System.out.println("右移动业务代码执行");
} else if (keyCode == 40) {
System.out.println("下移动业务代码执行");
}
}
@Override
public void keyReleased(KeyEvent e) {
}
});
frame.setVisible(true);
}
抽象方法中的KeyEvent类有自己的方法可以调用,我们可以用e.getKeyCode去获取键盘按下键的ASCII码,从而进行判断。
比如在上段代码中,我们的上下左右ASCII码就是 37、38、39、40
监听冲突
按钮组件比较特殊,建立之后,程序的焦点就在按钮组件上面
但我们不需要把按钮当做焦点,所以我们可以使用按钮的取消焦点方法,让ActionListener只监听点击事件,不和键盘监听中的空格产生冲突
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("我被点了");
}
});
button.setFocusable(false);
设计模式
设计模式(Design pattern):
是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
适配器设计模式
解决接口和接口实现类之间的矛盾问题
假如说我现在的接口定义了三个方法abc,我想让一个类只重写方法a,另一个类只重写方法bc,显然直接让两个类去作为接口的实现类是不对的;所以我们需要创建一个接口适配器作为中间类。
interface A{
void a();
void b();
void c();
}
abstract class adapter1 implements A{
@Override
public void a() {
}
@Override
public void b() {
}
@Override
public void c() {
}
}
class bro extends adapter1{
@Override
public void a() {
System.out.println("aa");
}
}
class sister extends adapter1{
@Override
public void b() {
}
@Override
public void c() {
}
}
其中需要注意的是,为了避免别人直接创建适配器类,我们要在适配器类的前面加上abstract进行抽象修饰
模版设计模式
模板设计模式:
把抽象类整体就可以看做成一个模板,模板中不能决定的东西定义成抽象方法让使用模板的类(继承抽象类的类)去重写抽象方法实现需求
package yuhan;
abstract public class ModuleAdapterDemo {
public final void write(){
System.out.println("雨下整夜");
body();
System.out.println("我的爱溢出就像雨水");
}
public abstract void body();
}
先定义一个抽象类作为模板,不能决定的body作为抽象方法,让继承类进行重写;
主方法不希望子类重写,所以加上final进行修饰
class Jerry extends ModuleAdapterDemo{
@Override
public void body() {
System.out.println("哦哦");
}
}
public class test {
public static void main(String[] args) {
Jerry jerry = new Jerry();
jerry.write();
}
}
子类重写需要修改的抽象方法,调用即可