11 图形化Swing
javax.swing
包
11.1 基础GUI
-
JFrame
是个代表屏幕上window的对象。- 可以把
button
、checkbox
、text
字段等放在window上面 - 长相会根据所处平台有所不同
- 可以把
-
组件
widget
-
所有的组件都是继承自
javax.swing.JComponent
; -
组件是可以嵌套的,大致分为交互组件和背景组件(除了JFrame外,差异不明确);
-
常用组件:
-
JButton
-
JRadioButton
-
JCheckBox
-
复选框
-
JCheckBox check = new JCheckBox("Goes to 11"); check.addItemListener(this); public void itemStateChanged(ItemEvent ev){ String onOrOff = "off"; if(check.isSelected())onOrOff = "on"; System.out.println("Check box is " + onOrOff); } check.setSelected(true); check.setSelected(false);
-
-
JLabel
-
JList
-
JList的构造函数需要一个任意类型的数组
-
String[] listEntries = {/*...*/}; list = new JList(listEntries); //让list显示垂直的滚动条和下面是一样的 //把text改成list即可 list.setVisibleRowCount(4);//设定显示的行数 list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); //限制用户只能选取一个项目
-
-
JScrollPane
-
JScrollPane scroller = new JScrollPane(text); scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); //上面两句指定只使用垂直的滚动条 panel.add(scroller);
-
-
JSlider
-
JTextArea
-
可以有超过一行以上的文字,但没有滚动条功能;
-
JTextArea text = new JTextArea(10, 20); text.setText(); text.append(); text.selectAll(); text.requestFocus(); text.setLineWrap(true);//自动换行
-
-
JTextField
-
JTextField field = new JTextField(20);//字宽 JTextField field = new JTextField("You Name"); field.getText(); field.setText(); field.selectAll(); field.requestFocus();
-
-
JTable
-
-
组件不是直接加到
JFrame
上,JFrame
可以看成window
的框,组件是加到window
的pane
上面的。
-
-
//非常简单的GUI import javax.swing.*; public class SimpleGui1{ public static void main(String[] args){ JFrame frame = new Frame(); JButton button = new JButton("click me"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //这一行程序在window关闭时把程序结束掉 //放置widget frame.getContentPane().add(button); frame.setSize(300, 300); frame.setVisible(true);//把frame显示出来 } }
-
frame上放置多个widget
- GUI的布局(layout)
frame.getContentPane().add(BorderLayout.CENTER, button);
- BorderLayout.CENTE
- BorderLayout.NORTH
- BorderLayout.WEST
- BorderLayout.EAST
- BorderLayout.SOUTH
-
绘图组件
JPanel
-
创建自己的子类并覆盖掉
paintComponent()
这个方法; -
import java.awt.*; import javax.swing.*; class MyDrawPanel extends JPanel{ public void paintComponent(Graphics g){ //参数是跟实际屏幕有关的Graphics对象 //无法取得这个对象 g.setColor(Color.orange); g.fillRect(20, 50, 100, 100); } }
-
无法调用这个方法,只能由系统来调用。
-
用
repaint()
来要求系统重新绘制显示装置,然后才会产生paintComponent()
的调用。
-
11.2 布局管理器
-
可以控制Java的GUI上的widget的大小和位置的对象;
-
与特定组件相关联的Java对象,它大多数是背景组件。
-
布局管理器用来控制所关联组件上携带的其他组件。
- 如果某个框架带有面板,而面板带有按钮;
- 则面板的布局管理器控制着按钮的大小与位置,而框架的布局管理器控制着面板的大小与位置。
-
布局管理器有几种不同的类型,每个背景组件都可以有自定义规则的布局管理器。
-
//嵌套布局的例子 JPanel panelA = new JPanel(); JPanel panelB = new JPanel(); panelB.add(new JButton("button 1")); panelB.add(new JButton("button 2")); panelB.add(new JButton("button 3")); panelA.add(panelB);
几种不同的布局管理器:
-
BorderLayout
- 把背景组件分割成五个区域,每个区域只能放一个组件;
- 框架(JFrame)默认的布局管理器。
frame.getContentPane().add(BorderLayout.EAST, button1);
- 南北使用理想高度,东西使用理想宽度,中间用剩下的。
-
FlowLayout
-
从左到右依照加入的顺序以可能会换行的方式排列;
-
面板(JPanel)默认的布局管理器。
-
JFrame frame = new JFrame(); JPanel panel = new JPanel(); JButton button = new JButton("shock me"); JButton button1 = new JButton("shock you"); //面板默认就是FlowLayout panel.add(button); panel.add(button1); frame.getContentPane().add(BorderLayout.EAST, panel);
-
-
BoxLayout
-
以垂直的方式来排列,按照加入的顺序;
-
插入某种换行的机制来强制组件从新的一行进行排列。
-
//把面板的布局管理器从默认的FLowLayout改成BoxLayout JFrame frame = new JFrame(); JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); //参数:管理哪个组件、使用哪个轴 JButton button = new JButton("shock me"); JButton button1 = new JButton("shock you"); panel.add(button); panel.add(button1); frame.getContentPane().add(BorderLayout.EAST, panel);
-
几个关键问答:
框架为什么不能像面板一样直接地加上组件?
JFrame
这么特殊是因为它是让事物显示在画面上的接点。Swing
组件纯由Java构成,JFrame
必须要连接到底层的操作系统以便来存取显示装置。- 可以把面板想作安置在
JFrame
上的100%纯Java层,或者把JFrame
看作支撑面板的框架。 - 可以用自定义的
JPanel
来替换掉框架的面板。myFrame.setContentPane(myPanel);
如何替换掉框架的布局管理器?想让框架使用顺序替换边界呢?
- 最简单的方法,是创建一个
JPanel
(面板),让此面板称为框架的ContentPane
; - 只需改变面板的布局管理器即可。
- 可以调用
setLayout(null)
直接设定画面位置和大小。
11.3 监听和事件处理
在Java中,取得和处理用户操作事件的过程称为even-handling
。
监听接口是介于监听(你)与事件源(按钮)之间的桥梁。
Swing的GUI组件是事件的来源。
- 事件来源是可以用户操作(点击鼠标、按键、关闭窗口等)转换成事件的对象。
- 在Java中,事件几乎都是以对象来表示。
java.awt.event
这个包中存在一组事件的类。
- 事件源(例如按钮)会在用户做出相关动作时(按下按钮)产生事件对象。
每个事件类型都有相对应的监听者接口。
- 例如想要接收MouseEvent,就要实现MouseListener接口。
大致发生顺序图:
-
//代码举例 import javax.swing.*; import java.awt.event.*; public class SimpleGui1B implements ActionListener{ JButton button; public static void main(String[] args){ SimpleGui1B gui = new SimpleGui1B(); gui.go(); } public void go(){ JFrame frame = new Frame(); button = new JButton("Click me"); button.addActionListener(this);//向按钮注册,this表示该程序监听 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(button); frame.setSize(300, 300); frame.setVisible(true); } //实现接口上的方法,这是真正处理事件的方法 public void actionPerformed(ActionEvent event){ //按钮会议ActionEvent为参数来调用次方法 button.setText("I've been clicked"); } }
多重监听:
比如有两个按钮。
- 可以对两个按钮注册一个接口,用if判断,但是这样不面向对象。
- 创建不同的监听器,即
ActionListener
,但是这些类没办法存取到所需的变量
——> 内部类
-
内部类可以使用外部的所有方法和变量,就算是
private
也一样。 -
内部类实例一定会绑在外部类的实例上。
-
import javax.swing.*; import java.awt.event.*; public class TwoButtons{ JFrame frame; JLabel label; public static void main(String[] args){ TwoButtons gui = new TwoButtons(); gui.go(); } public void go(){ frame = new Frame(); JButton labelButton = new JButton("Change Label"); labelButton.addActionListener(new LabelListener());//向按钮注册 JButton colorButton = new JButton("Change Circle"); colorButton.addActionListener(new ColorListener());//向按钮注册 label = new JLabel("I'm a label"); MyDrawPanel drawPanel = new MyDrawPanel(); frame.getContentPane().add(BorderLayout.SOUTH, colorButton); frame.getContentPane().add(BorderLayout.CENTER, drawPanel); frame.getContentPane().add(BorderLayout.EAST, labelButton); frame.getContentPane().add(BorderLayout.WEST, label); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 300); frame.setVisible(true); } class LabelListener implements ActionListener{ public void actionPerformed(ActionEvent event){ label.setText("Ouch!"); } } class ColorListener implements ActionListener{ public void actionPerformed(ActionEvent event){ frame.repaint(); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律