程序看图形界面布局
虽然勉强能看懂,但还是不太能理解到底如何理解java的布局逻辑了呢?
如题:2022年4月,第33题程序设计题
分析:
题目给出了部分程序,只需要填缺少的部分,前面28题有类似的,倒是可以比照着写出来,但还是不太明白到底是如何布局的?能准确控制吗?对此还是存有疑问了。同时多了解一下java设计的逻辑。
基本知识:
AWT图形组件的继承关系
虽然AWT已经很少使用了,但SWing组件继承了Container类,所以绝大部分swing组件都可以当作容器使用。这种继承关系决定了操作的顺序。
Swing组件的继承关系
图中可以看到四个顶层容器都直接继承自awt,所以都是重量级组件。需要依赖于本地化的gui平台。
这些组件方法,都很容易可以查到,没什么大不了的,关键是要理解java的布局逻辑?
排列逻辑:
顶层容器就相当于相框的底板,所有的照片都是放在这上面的。如:
Frame相当于一个大的框架,再它里面可以放多个面版,但是组件不能直接放在上面。
再往下是:Panel面板也是一个容器,,但是它不能单独存在,只能存在其他容器,但组件可以直接放在上面。一个Panel对象代表了一个长方形的区域。
前两层,相当于底框与底板的关系,那么底板放到底框上呢?
底框有描述底板的空间方法,底板也有描述底板的空间方法,共同点是都要占一定的空间。两个空间如何叠放,形成一张完整的相框呢?
java设计了内容窗格,想想也知道,这个内容空间的大小是由底框定,当然也可以由底板来定。所以给出了两种方法:
由底框定内容:
通过顶层容器getContentPane( )方法,返回类型为java.awt.Container。格式如下:
Container contentPane=frame.getContentPane( );
contentPane.add(button,BorderLayout.CENTER);
简化的写法为:mw.getContentPane().add(button); //mv就是个框架
由底板定内容:
建立一个JPanel对象的中间容器,把组件添加到这个容器中,再用setContentPane()把这个容器置为内容面板。
JPanel contentPane = new JPanel();
mw.setContentPane(contentPane);
有了相框,就是往里面放照片,也就是组件了,但如何排列呢?
java设计了布局管理器。每一个容器都有默认的布局管理器,
Window、Frame和Dialog的默认布局管理器是BorderLayout,Panel的默认布局管理器是FlowLayout。也可以调用容器的setLayout(null)方法,将布局管理器取消。
组件在容器中的位置和尺寸是由布局管理器来决定的。
FlowLayout
流式布局下,容器会将组件按照添加顺序从左向右放置。FlowLayout(int align,int hgap,int vgap);//可设置对齐方式,及水平垂直距离多少像素。默认是居中(也就是每行平均分布)组件间隔5个像素
如下例子:
Frame frame = new Frame();
frame.setVisible(true);
//组件-button
Button button1 = new Button("button1");
Button button2 = new Button("button2");
Button button3 = new Button("button3");
//设置流式布局:
frame.setLayout(new FlowLayout());
// frame.setLayout(new FlowLayout(FlowLayout.LEFT)); //布局偏左
// frame.setLayout(new FlowLayout(FlowLayout.RIGHT)); //布局偏右
frame.setSize(200,200);
//把button填加到frame:
frame.add(button1);
frame.add(button2);
frame.add(button3);
BorderLayout 边界布局(JWindow、JFrame,JDialog 的默认布局)
空间简单划分为东“East”,西 “West”,南 “South”,北 “North”,中 “Center”
五个区域。
一个位置放一个组件。如果某个位置要加入多个组件,应先将要加入该位置的组件放放另一个容器中,然后再将这个容器加入到这个个位置。
如下例子:
Frame frame = new Frame("TestBorderLayout:");
frame.setVisible(true);
frame.setSize(500,500);
Button button1 = new Button("East");
Button button2 = new Button("West");
Button button3 = new Button("South");
Button button4 = new Button("North");
Button button5 = new Button("Center");
//BorderLayout的使用:
frame.add(button1,BorderLayout.EAST); //add(添加的组件,边界布局设置)
frame.add(button2,BorderLayout.WEST);
frame.add(button3,BorderLayout.SOUTH);
frame.add(button4,BorderLayout.NORTH);
frame.add(button5,BorderLayout.CENTER);
GridLayout网格布局管理器
使用纵横线将容器分成n行m列大小相等的网格,每个网格中放置一个组件
使用例子:
Frame frame = new Frame("TestGridLayout:");
frame.setSize(500,500);
frame.setVisible(true);
//设置布局格式:3行2列
frame.setLayout(new GridLayout(3,2));
Button button1 = new Button("button1");
Button button2 = new Button("button2");
Button button3 = new Button("button3");
Button button4 = new Button("button4");
Button button5 = new Button("button5");
Button button6 = new Button("button6");
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.add(button4);
frame.add(button5);
frame.add(button6);
有了相框,可以显示一些东西了,但重要的是要有人机交互,才能实现动态展示一些信息?(简单了解下)
这才是真正的互联网。如何实现呢?java 设计了事件侦听,只介绍几个常用的。
窗口侦听事件(本题所涉及到的)
Window类型的窗口需要实现WindowListener接口。接着通过addWindowListener()方法为事件源注册事件监听器对象,当事件源上发生事件时,便会触发事件监听器对象,由事件监听器调用相应的方法来处理相应的事件。
public class WindowListeners {
public static void main(String[] args) {
new WindowFrame();
}
}
class WindowFrame extends Frame{
public WindowFrame(){
setBounds(100,100,400,300);
//添加button组件到界面中:
Button button = new Button("setVisible!");
add(button);
setVisible(true);
//设置窗口监听,使用适配器模式:
addWindowListener(new WindowAdapter() {
//监听窗口关闭:
@Override
public void windowClosing(WindowEvent e) {
System.out.println("windowClosing");
}
//监听窗口动态:
@Override
public void windowActivated(WindowEvent e) {
System.out.println("windowActivated");
}
});
}
}
鼠标监听事件
首先需要通过实现MouseListener接口定义监听器(也可以通过继承适配器MouseAdapter
类来实现),然后调用addMouseListener()方法将监听器绑定到事件源对象。
public class mouse extends Frame {
public mouse(){
setBounds(100,100,400,350);
setVisible(true);
Button b1 = new Button("btn1");
Button b2 = new Button("btn2");
//添加鼠标事件:
b1.addMouseListener(new MouseListen());
add(b1,BorderLayout.SOUTH);
add(b2,BorderLayout.NORTH);
}
class MouseListen extends MouseAdapter {
//定义鼠标按压触发监听效果:
@Override
public void mousePressed(MouseEvent e) {
Object source = e.getSource();
System.out.println("鼠标点击了!");
}
}
public static void main(String[] args) {
new mouse();
}
输入框TextField
使用例子如下:
public class TestTextField {
public static void main(String[] args) {
new MyFrame1();
}
}
class MyFrame1 extends Frame{
public MyFrame1(){
TextField text = new TextField();
add(text);
//监听这个文本输入的文字:
MyActionL myActionL = new MyActionL();
//按下enter,触发这个输入框的事件:
text.addActionListener(myActionL);
setSize(400,200);
setVisible(true);
text.setEchoChar('*'); //设置编码替换:把输入的数据转换为**显示
}
class MyActionL implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
TextField field = (TextField) e.getSource(); //获取资源,返回一个对象
System.out.println(field);
System.out.println(field.getText()); //获取输入框的文本
field.setText(""); //按下回车后文本框重置为空
}
}
答案:
public class Test33 {
public static void main(String[] args) {
Statement be = new Statement();
be.go();
}
}
class Statement extends WindowAdapter implements ActionListener {
JFrame f;
JButton myButton;
JLabel myLabel;
JTextField tfs;
String ad = "This is a JFrame!";
public void go() {
f = new JFrame("My JFrame");
f.setLayout(new GridLayout(6 , 1 , 10 , 10));
f.setSize(650 , 400);
myLabel = new JLabel("Statement");//标签有了
JPanel pan1 = new JPanel();
JPanel pan2 = new JPanel();//面板也有了
pan1.setLayout(new FlowLayout(FlowLayout.CENTER , 40 , 0));
//此处填写代码,分析,还少的是文本域和按钮
tfs = new JTextField("This is a JFrame");//只添加这两句的话,只显示框架,面板里的组件一个也显示不出来???
pan1.add(myLabel);
pan1.add(tfs);
pan2.setLayout(new FlowLayout(FlowLayout.CENTER , 40 , 0));
myButton = new JButton("OK");
pan2.add(myButton);
Container cp = f.getContentPane();//内容窗体,面板是不能单独存在的
cp.setLayout(new GridLayout(0 , 1));//布局很关键,否则会显示不全?这里决定了这两个面板是是竖着排列的,布局管理器的逻辑是什么?
cp.add(pan1);
cp.add(pan2);
f.pack();//这里也很关键,否则显示不成比例?
f.addWindowListener(this);
f.setVisible(true);
}
public void windowClosing(WindowEvent event) {
System.exit(0);
}
@Override
public void actionPerformed(ActionEvent e) {
}
}
答案中总结的设计窗体的步骤?
- 设计一个窗体的类,并且指明要响应的事件,如第一句:class Statement extends WindowAdapter implements ActionListener
- 在mian中新一个窗体类,分配内存空间,并调用窗体的go函数
- 在go函数里写设计过程
- 可先设计一个框架,布局可设置为表格样式,并且设置表格的大小,间距。设置框架的大小。框架的大小决定了显示里面的表格的尺寸,如果格点很大的话,会显示不全。
- 然后,设计框架里的面板,面板里添加组件,面板可单独设置布局,这个相当于一块独立的长方体。默认是flowlayout,间隔5个像素。按所选的布局管理器添加组件即可
- 可通过内容窗格,把面板放到里面,也可以直接利用框架add面板。内容窗格的添加顺序,或框架的添加顺序,决定了显示顺序。