某koukou老师的任务罢了,好在狂神老师居然有GUI的课,只能说是有救星了。
【狂神说Java】GUI编程入门到游戏实战
最好笑的是,老师要求掌握的居然是14年的知识,就连狂神在上这门课的时候都在吐槽:你们在网络上几乎看不到这样的教学资源,因为已经很少很少了(被淘汰了)
主要是这个学期的短学期实践十有八九是koukou老师,非得是用java设计图形化可视化,所以学还是得学,不该挂的课就是不能挂!
组建:
GUI的核心:
Swing AWT
为什么javaGUI不流行?
那么为什么要学?
用于GUI编程,AWT就是抽象窗口工具
(Eclipse和IDEA就是用java Swing写出来的)
我们现来看看第一个frame
package top.woodwhale.study; import java.awt.*; // GUI的第一个界面 public class TestFrame { public static void main(String[] args) { // Frame Frame frame = new Frame("First Java Window"); // 需要设置可见性,长度、宽度 frame.setVisible(true); frame.setSize(400,400); // 设置背景颜色 Color frame.setBackground(new Color(22, 87, 220)); // 弹出的初始位置 frame.setLocation(200,200); // 设置大小固定 frame.setResizable(false); } }
效果就是一个蓝色的、不可拉伸、不可关闭的窗口
思考:
如果我们需要同时开启多个窗口,有没有什么好的方法呢?
package top.woodwhale.study; import java.awt.*; public class TestFrame2 { public static void main(String[] args) { // 展示多个窗口 MyFrame mf1 = new MyFrame(100,100,200,200,Color.black); MyFrame mf2 = new MyFrame(300,100,200,200,Color.orange); MyFrame mf3 = new MyFrame(100,300,200,200,Color.green); MyFrame mf4 = new MyFrame(300,300,200,200,Color.pink); } } class MyFrame extends Frame{ static int id = 0; // 可能存在多个窗口,需要一个计数器 public MyFrame(int x,int y,int w,int h,Color color) { super("Myframe"+ (++id)); setBackground(color); setBounds(x,y,w,h); setVisible(true); } }
效果如下:(有点好看
面板Panel可以看成是一个空间,但是不能单独存在,可以存在与一个框架中。类似于前段的div(大概
以下的例子通过适配器模式来监听窗口关闭事件
package top.woodwhale.study; import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class TestPanel { public static void main(String[] args) { // 先创建一个框架 Frame frame = new Frame(); // 设置一个面板 Panel panel = new Panel(); // 设置布局 frame.setLayout(null); // 框架的坐标 frame.setBounds(300,300,500,500); // 框架的背景 frame.setBackground(new Color(40,161,35)); // 面板设置坐标,相对于frame panel.setBounds(50,50,400,400); panel.setBackground(new Color(190,15,60)); // frame.add() frame.add(panel); // 将面板设置为可见 frame.setVisible(true); // 监听窗口关闭事件 // 适配器模式: frame.addWindowListener(new WindowAdapter() { // 窗口点击关闭的时候需要做的事情 @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } }
效果如下:(我们点击关闭按钮可以结束进程,也就是退出
流式布局
这个按钮的年代感直接出来了,有种wine打开exe的味道了
package top.woodwhale.study; import java.awt.*; public class TestFlowLayout { public static void main(String[] args) { Frame frame = new Frame("114514"); // 组件-按钮 Button button1 = new Button("button1"); Button button2 = new Button("button2"); Button button3 = new Button("button3"); // 设置为流式布局 默认是居中 frame.setLayout(new FlowLayout()); // frame.setLayout(new FlowLayout(FlowLayout.RIGHT)); frame.setSize(200,200); // 把按钮添加上去 frame.add(button1); frame.add(button2); frame.add(button3); frame.setVisible(true); } }
东西南北中
狂神老师说这是视频软件的布局,为什么我第一反应是,上下左右都是广告,中间是小视频(bushi
package top.woodwhale.study; import java.awt.*; public class TestBorderLayout { public static void main(String[] args) { Frame frame = new Frame("114514"); Button east = new Button("east"); Button west = new Button("west"); Button south = new Button("south"); Button north = new Button("north"); Button center = new Button("center"); frame.add(east,BorderLayout.EAST); frame.add(west,BorderLayout.WEST); frame.add(south,BorderLayout.SOUTH); frame.add(north,BorderLayout.NORTH); frame.add(center,BorderLayout.CENTER); frame.setSize(300,300); frame.setVisible(true); } }
表格布局
就是类似表格的形式,这里使用了pack()方法来使大小、内容自动填充
package top.woodwhale.study; import java.awt.*; public class TestGridLayout { public static void main(String[] args) { Frame frame = new Frame("114514"); Button bt1 = new Button("bt1"); Button bt2 = new Button("bt2"); Button bt3 = new Button("bt3"); Button bt4 = new Button("bt4"); Button bt5 = new Button("bt5"); Button bt6 = new Button("bt6"); frame.setLayout(new GridLayout(3,2)); frame.add(bt1); frame.add(bt2); frame.add(bt3); frame.add(bt4); frame.add(bt5); frame.add(bt6); frame.pack(); // java方法,用来自动填充 frame.setVisible(true); } }
如何完成下图的格式布局?
直接动手
动手之前先进行构思,一个好的项目,构思占据80%,代码只有20%!!!
我们现构建一个两行一列的frame,然后在中间部分上下各设置一个面板,frame的上半部分和下半部分都使用东西南北中的布局管理,再在两个面板中设置东西南北中格式,其中上面的嵌套一个两行一列的面板,下面的嵌套一个两行两列的面板
最终效果:
代码:
package top.woodwhale.study; import java.awt.*; import java.awt.image.ImageObserver; public class MyLayout { public static void main(String[] args) { Frame frame = new Frame("114514"); frame.setSize(400,300); frame.setLocation(300,300); frame.setBackground(Color.orange); frame.setVisible(true); // 两行一列 frame.setLayout(new GridLayout(2,1)); // 4个面板 Panel panel1 = new Panel(new BorderLayout()); Panel panel2 = new Panel(new GridLayout(2,1)); Panel panel3 = new Panel(new BorderLayout()); Panel panel4 = new Panel(new GridLayout(2,2)); panel1.add(new Button("East-1"),BorderLayout.EAST); panel1.add(new Button("West-1"),BorderLayout.WEST); panel2.add(new Button("p2-btn-1")); panel2.add(new Button("p2-btn-2")); panel1.add(panel2,BorderLayout.CENTER); panel3.add(new Button("East-2"),BorderLayout.EAST); panel3.add(new Button("West-2"),BorderLayout.WEST); for (int i = 0; i < 4; i++) { panel4.add(new Button("for-"+i)); } panel3.add(panel4,BorderLayout.CENTER); frame.add(panel1); frame.add(panel3); } }
监听就是,当发生某事件后,我们监听到了这个动态,应该有某种反馈
先来点效果图:
可以观察到,我们第一次这个巨大按钮,就会在控制台输出一次114514,这是为啥呢?
package top.woodwhale.study2; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class TestActionEvent { public static void main(String[] args) { Frame frame = new Frame(); // 按下按钮的时候,触发一些事件 Button button = new Button("点我控制台输出114514"); // 因为addActionListener需要一个ActionListener,所以我们字节写一个MyActionListener类 MyActionListener myActionListener = new MyActionListener(); button.addActionListener(myActionListener); frame.add(button); frame.setSize(300,300); frame.setVisible(true); windowClose(frame); } // 关闭窗口事件 private static void windowClose(Frame frame) { frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } } class MyActionListener implements ActionListener{ @Override public void actionPerformed(ActionEvent actionEvent) { System.out.println("114514"); } }
其实是因为,我们设置了一个按钮的监听器,我们自己写了一个MyActionListener类,是ActionListener的一个接口,我们重写的方法就是只要有这个事件产生,就输出114514。
而我们在button中使用了addActionListener方法,将我们重写的监听器赋予给了这个按钮,所以我们按下这个按钮的时候就能在控制台看到输出的114514。
并且,我们通过在主类中写了一个windowClose的static方法,这样,我们通过方法的封装直接实现了点击关闭按钮关闭窗口的监听事件。
如果我们想实现多个按钮同时监听一个事件呢?我们可以只写一个监听类,通过更改setActionCommand达到不同的监听效果。
如下图所示,我们点击start按钮可以在控制台输出“开始”
如果我们点击Stop按钮,会输出“哼哼”
这种效果其实就是一个监听器监听了多个事件
package top.woodwhale.study2; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class TestActionEvent2 { public static void main(String[] args) { // 两个按钮,实现同一个监听 // 开始按钮和停止按钮 Frame frame = new Frame("Start ~ Stop"); Button button = new Button("Start"); Button button1 = new Button("Stop"); // 可以显示的定义触发会返回的命令,如果不显示定义,则会走默认的值 // 这样我们可以多个按钮,但是只需要一个监听类,只需要更改setActionCommand button1.setActionCommand("Stop"); MyMonitor myMonitor = new MyMonitor(); button.addActionListener(myMonitor); button1.addActionListener(myMonitor); frame.add(button,BorderLayout.NORTH); frame.add(button1,BorderLayout.SOUTH); frame.setSize(300,300); frame.setVisible(true); } } class MyMonitor implements ActionListener { @Override public void actionPerformed(ActionEvent actionEvent) { // actionEvent.getActionCommand()获得按钮的信息' String command = actionEvent.getActionCommand(); if (command.equals("Stop")) { System.out.println("想要Stop?哼哼哼哼哼哼哼哼哼哼哼哼哈哈哈哈哈哈哈哈哈~"); } else if (command.equals("Start")) { System.out.println("开始"); } } }
我们用TextField类可以创造出输入框的对象,输入框在很多地方都很常见,比如密码输入
这里我们用密码输入来当引子
我们应该实现什么功能?
如何实现?
效果如下:
按下回车之前:
按下回车之后:
代码实现:
package top.woodwhale.study2; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class TestText { public static void main(String[] args) { // 启动 new MyFrame(); } } class MyFrame extends Frame { public MyFrame() { // 写单行文本 TextField textField = new TextField(); // 因为MyFrame继承了Frame,可以直接使用add方法 add(textField); // 监听这个文本框输入的文字,按下enter控制台就会输出我们输入的内容,并且清空文本 MyAL myAL = new MyAL(); textField.addActionListener(myAL); // 替换编码 textField.setEchoChar('*'); setVisible(true); setSize(300,100); // 设置点击关闭监听事件 addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } } class MyAL implements ActionListener { @Override public void actionPerformed(ActionEvent actionEvent) { // 获取一些资源,返回了一个对象 TextField field = (TextField) actionEvent.getSource(); // 获得输入框的文字 System.out.println(field.getText()); field.setText(""); } }
在这章之前,狂神老师说了一点比较重要的——oop原则:组合大于继承
其实这是装饰器模式的一个体现:
比如我们如果在A类中要实现B的部分功能,一般都是将A继承B的功能。
但是因为Java不能多继承,所以组合就出现了
// 继承 public class A extends B { } // 组合 public class A { public B b; }
此外,阿里巴巴手册中提出,少用多态、少用继承!(虽然多态和继承是面向对象的三大特性之二)
在开始写代码之前,我们需要先构思。
GUI界面如下:
界面其实就是三个输入框,一个“=”按钮,一个“+”标签,然后按照流式模型就可以构造出来了
重点来了:
如何完成监听前两个输入框的值,并且将第三个输入框写入计算后的结果?
我们在面向对象的学习中,都了解到了构造器,那么我们是不是可以吧三个输入框通过构造器来获取呢?
我们在监听器类中创建三个私有的三个输入框类,通过new对象的时候将传入的三个输入框setter完成。
这样,我们在监听器类中就获取了三个输入框的对象!接下来的操作就不用多所了,代码注释中写有。
代码:
package top.woodwhale.study2; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class TestCalc { public static void main(String[] args) { new Calculator(); } } // 计算器类 class Calculator extends Frame { public Calculator() { // 3个文本框 TextField num1 = new TextField(10); TextField num2 = new TextField(10); TextField num3 = new TextField(10); // 1个按钮 Button button = new Button("="); button.addActionListener(new MyCalcListener(num1, num2, num3)); // 1个标签 Label label = new Label("+"); setLayout(new FlowLayout()); add(num1); add(label); add(num2); add(button); add(num3); pack(); setVisible(true); } } // 监听器类 class MyCalcListener implements ActionListener { private TextField num1, num2, num3; // 获取三个变量 public MyCalcListener(TextField num1, TextField num2, TextField num3) { this.num1 = num1; this.num2 = num2; this.num3 = num3; } @Override public void actionPerformed(ActionEvent actionEvent) { // 1.获得加数和被加数 int n1 = Integer.parseInt(num1.getText()); int n2 = Integer.parseInt(num2.getText()); // 2.将这个值进行加法运算后,防到第三个框 num3.setText(n1+n2+""); // 3.清除前两个框 num1.setText(""); num2.setText(""); } }
运行截图:
按下按钮前:
按下按钮后:
我们在前言部分就提到了,组合是远远好于继承的,那么如何使用组合的方式来获取三个对话框中的输入输出呢?
我们之前使用的setter方式相当于传数据,而面向对象的组合方式,就是相当于传对象了。
完整代码:
package top.woodwhale.study2; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class TestCalc2 { public static void main(String[] args) { new Calculator2().loadFrame(); } } // 计算器类 class Calculator2 extends Frame { // 属性 TextField num1, num2, num3; // 方法 public void loadFrame() { num1 = new TextField(10); num2 = new TextField(10); num3 = new TextField(10); Button button = new Button("="); button.addActionListener(new MyCalcListener2(this)); // 将自己这个Calculator对象给监听器类 Label label = new Label("+"); setLayout(new FlowLayout()); add(num1); add(label); add(num2); add(button); add(num3); pack(); setVisible(true); } } // 监听器类 class MyCalcListener2 implements ActionListener { // 获取计算器这个对象,在一个类中组合另一个类 private Calculator2 calculator = null; // 获取三个变量 public MyCalcListener2(Calculator2 calculator) { this.calculator = calculator; } @Override public void actionPerformed(ActionEvent actionEvent) { int n1 = Integer.parseInt(calculator.num1.getText()); int n2 = Integer.parseInt(calculator.num2.getText()); calculator.num3.setText(n1+n2+""); calculator.num1.setText(""); calculator.num2.setText(""); } }
效果图:
按下按钮前:
按下按钮后:
面向对象的更高级形式——内部类方法实现
如何实现?
package top.woodwhale.study2; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class TestCalc2 { public static void main(String[] args) { new Calculator2().loadFrame(); } } // 计算器类 class Calculator2 extends Frame { // 属性 TextField num1, num2, num3; // 方法 public void loadFrame() { num1 = new TextField(10); num2 = new TextField(10); num3 = new TextField(10); Button button = new Button("="); button.addActionListener(new MyCalcListener2()); // 将自己这个Calculator对象给监听器类 Label label = new Label("+"); setLayout(new FlowLayout()); add(num1); add(label); add(num2); add(button); add(num3); pack(); setVisible(true); } // 监听器类 class MyCalcListener2 implements ActionListener { @Override public void actionPerformed(ActionEvent actionEvent) { int n1 = Integer.parseInt(num1.getText()); int n2 = Integer.parseInt(num2.getText()); num3.setText(n1+n2+""); num1.setText(""); num2.setText(""); } } }
现了解这个paint方法,是Frame中的一个方法,我们自己构造一个MyPaint类,继承Frame,然后重写paint方法,这样在我们的Frame中就可以画出我们想要的东西了!
效果图:
实现代码:
package top.woodwhale.study3; import java.awt.*; public class TestPaint { public static void main(String[] args) { new MyPaint().loadFrame(); } } class MyPaint extends Frame { public void loadFrame() { setBounds(200,200,600,500); setVisible(true); } // 画笔 @Override public void paint(Graphics g) { // 画笔需要有颜色,可以画画 g.setColor(Color.red); g.fillOval(100,100,100,100); // 实心的圆 g.setColor(Color.green); g.fillRect(150,200,300,200); // 养成习惯,画笔用完,将他还原到最初的颜色 } }
目的:想要实现鼠标画画!
如何实现?
有了方法之后,我们开始构建
代码如下:
package top.woodwhale.study3; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; public class TestMouseListener { public static void main(String[] args) { new MyFrame("画画"); } } class MyFrame extends Frame { // 画画需要画笔,需要监听鼠标当前的位置,需要集合来存储这个点 ArrayList points; public MyFrame(String title) { super(title); setVisible(true); // 存储鼠标点击的坐标 points = new ArrayList<>(); setBounds(200,200,400,300); // 鼠标监听器,相对于这个窗口 this.addMouseListener(new MyMouseListener()); } @Override public void paint(Graphics g) { // 画画,监听鼠标的事件 for (Object o : points) { Point point = (Point) o; g.setColor(Color.blue); g.fillOval(point.x, point.y, 10, 10); } } // 参加一个点到界面上 public void addPaint(Point point) { points.add(point); } // 适配器模式 private static class MyMouseListener extends MouseAdapter { // 鼠标有,按下,弹起,按住不放 // 添加 @Override public void mousePressed(MouseEvent e) { MyFrame myframe = (MyFrame) e.getSource(); // 我们点击的时候,就会在界面上产生一个点(坐标形式) // 这个点就是鼠标点击的坐标 myframe.addPaint(new Point(e.getX(),e.getY())); // 每次点击鼠标都需要重新画一遍 myframe.repaint(); // 刷新 } } }
效果如图:
窗口监听其实在之前点击关闭退出那里已经讲了很多了,这里再补充一点
package top.woodwhale.study3; import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class TestWindow { public static void main(String[] args) { new WindowFrame(); } } class WindowFrame extends Frame { public WindowFrame() { setBackground(Color.blue); setBounds(100,100,200,200); setVisible(true); // 使用内部类 // addWindowListener(new MyWindowListener()); // 使用匿名内部类 this.addWindowListener(new WindowAdapter() { // 关闭窗口 @Override public void windowClosing(WindowEvent e) { System.exit(0); } // 激活窗口 @Override public void windowActivated(WindowEvent e) { WindowFrame source = (WindowFrame) e.getSource(); source.setTitle("被激活啦!"); } }); } // class MyWindowListener extends WindowAdapter{ // @Override // public void windowClosing(WindowEvent e) { // System.exit(0); // 正常退出 // } // } }
键盘监听,顾名思义,就是监听键盘的状态,用的多的就是判断键盘按下了什么键
package top.woodwhale.study3; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class TestKeyListener { public static void main(String[] args) { new KeyFrame(); } } class KeyFrame extends Frame { public KeyFrame() { setBounds(1,2,300,300); setVisible(true); // 匿名内部类实现监听器 this.addKeyListener(new KeyAdapter() { // 键盘按下 @Override public void keyPressed(KeyEvent e) { // 获得键盘下的键是哪一个 int keyCode = e.getKeyCode(); // System.out.println(keyCode); // 不需要记录KeyCode的值,直接判断 if (keyCode == KeyEvent.VK_UP) { System.out.println("upupup!~"); } } }); // 匿名内部类实现关闭 this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.out.println("See you next time!"); System.exit(0); } }); } }
AWT是Swing的基础,Swing从AWT进化而来
随便调用个一个JFrame类,进入源码看一下,直接看到extends Frame
JFrame其实和Frame类似,只不过涉及到了容器这个概念,每一个窗口都有容器,而容器需要实例化
举例代码:
package top.woodwhale.study4; import javax.swing.*; import java.awt.*; public class JFrameDemo { // init() 初始化方法 public void init() { // 顶级窗口 JFrame jFrame = new JFrame("一个JFrame窗口"); jFrame.setVisible(true); jFrame.setBounds(100,100,200,200); // 设置文字 JLabel JLabel jLabel = new JLabel("1145141919810"); // 让文本居中 jLabel.setHorizontalAlignment(SwingConstants.CENTER); jFrame.add(jLabel); // jf有容器,容器需要实例化 Container container = jFrame.getContentPane(); container.setBackground(Color.orange); // JFrame自带的设置关闭操作方法 jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { // 建立一个窗口 new JFrameDemo().init(); } }
效果如下:
JDialog是一个弹窗的窗口类,我们用一个继承JDialog的类来写一个弹窗事件
package top.woodwhale.study4; import javax.swing.*; import javax.swing.text.LabelView; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; // 主窗口 public class DialogDemo extends JFrame { public DialogDemo() { this.setVisible(true); this.setSize(700,500); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // JFrame 放东西,放入容器中 Container container = this.getContentPane(); // 绝对布局 container.setLayout(null); // 按钮 JButton jButton = new JButton("点击弹出114514"); // 创建 jButton.setBounds(30,30,200,50); // 点击这个按钮,弹出一个弹窗,需要一个监听事件 jButton.addActionListener(new ActionListener() { // 监听器 @Override public void actionPerformed(ActionEvent actionEvent) { // 弹窗 new MyDialogDemo(); } }); container.add(jButton); } public static void main(String[] args) { new DialogDemo(); } } // 弹窗的窗口,默认就有点击关闭事件 class MyDialogDemo extends JDialog{ public MyDialogDemo() { this.setVisible(true); this.setBounds(100,100,500,500); Container contentPane = this.getContentPane(); // contentPane.setLayout(null); contentPane.add(new JLabel("1145141919810")); } }
来点效果图:
label就是标签
new JLabel("114514");
图标、图片是icon
显示一个自己画的图标:
package top.woodwhale.study4; import javax.swing.*; import java.awt.*; // 图标是一个接口,需要实现类,JFrame继承 public class IconDemo extends JFrame implements Icon { private int width; private int height; public IconDemo() throws HeadlessException { } public IconDemo(int width, int height) throws HeadlessException { this.width = width; this.height = height; } public static void main(String[] args) { new IconDemo().init(); } public void init() { IconDemo iconDemo = new IconDemo(15,15); JLabel jLabel = new JLabel("iconTest", iconDemo, SwingConstants.CENTER); Container container = getContentPane(); container.add(jLabel); this.setVisible(true); this.setSize(300,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } @Override public void paintIcon(Component component, Graphics graphics, int i, int i1) { graphics.fillOval(i,i1,this.width,this.height); } @Override public int getIconWidth() { return this.width; } @Override public int getIconHeight() { return this.height; } }
效果如下:
那么如何来设置自定义图片icon呢?
效果如下的这种:
也很简单:
package top.woodwhale.study4; import javax.swing.*; import java.awt.*; import java.net.URL; public class ImageIconDemo extends JFrame { public static void main(String[] args) { new ImageIconDemo(); } public ImageIconDemo() throws HeadlessException { // 获取图片的地质 JLabel jLabel = new JLabel("ImageIcon"); URL url = ImageIconDemo.class.getResource("woodwhale.jpg"); assert url != null; ImageIcon imageIcon = new ImageIcon(url); jLabel.setIcon(imageIcon); jLabel.setHorizontalAlignment(SwingConstants.CENTER); Container container = getContentPane(); container.add(jLabel); setVisible(true); setSize(300,300); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } }
JPanel
和之前学的Panel一样,就是多了容器操作
package top.woodwhale.study5; import javax.swing.*; import java.awt.*; public class JPanelDemo extends JFrame { public JPanelDemo() { Container container = this.getContentPane(); container.setLayout(new GridLayout(2,1,10,10)); // 后面的参数表示间距 JPanel jPanel = new JPanel(new GridLayout(1,3)); jPanel.add(new JButton("114")); jPanel.add(new JButton("514")); jPanel.add(new JButton("1919")); container.add(jPanel); this.setVisible(true); this.setSize(300,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new JPanelDemo(); } }
效果如下:
那么如何来点滚动条呢?
使用JScroll即可
代码:
package top.woodwhale.study5; import javax.swing.*; import java.awt.*; public class JScrollDemo extends JFrame { public JScrollDemo() { // 容器 Container container = this.getContentPane(); // 文本 JTextArea textArea = new JTextArea(20,50); textArea.setText("114514"); // 滚动条 JScrollPane scrollPane = new JScrollPane(textArea); container.add(scrollPane); this.setVisible(true); this.setBounds(300,300,300,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new JScrollDemo(); } }
其实Swing中的按钮和html中的选择框很像,也是需要设置选择域进行分组,许多单选框如果在一个组就只能选一个,多选就没这么限制了
Swing中的按钮分为下面三类:
图片按钮 (JButton中的setIcon实现)
效果图:
代码:
package top.woodwhale.study5; import javax.swing.*; import java.awt.*; import java.net.URL; public class JButtonDemo1 extends JFrame { public JButtonDemo1 (){ Container container = this.getContentPane(); URL rs = JButtonDemo1.class.getResource("woodwhale.jpg"); assert rs != null; Icon icon = new ImageIcon(rs); // 把这个图标放在按钮上 JButton jButton = new JButton(); jButton.setIcon(icon); jButton.setToolTipText("114514"); container.add(jButton); this.setVisible(true); this.setSize(300,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new JButtonDemo1(); } }
单选按钮 (JRadioButton和ButtonGroup)
效果如下:
代码:
package top.woodwhale.study5; import javax.swing.*; import java.awt.*; public class JButtonDemo2 extends JFrame { public JButtonDemo2() { Container container = this.getContentPane(); // 单选框 JRadioButton radioButton = new JRadioButton("JRadioButtonTest"); JRadioButton radioButton1 = new JRadioButton("JRadioButtonTest114514"); JRadioButton radioButton2 = new JRadioButton("JRadioButtonTest1919810"); // 由于单选框只能选择一个,所以需要分组 ButtonGroup buttonGroup = new ButtonGroup(); buttonGroup.add(radioButton); buttonGroup.add(radioButton1); buttonGroup.add(radioButton2); container.add(radioButton1,BorderLayout.CENTER); container.add(radioButton,BorderLayout.NORTH); container.add(radioButton2,BorderLayout.SOUTH); this.setVisible(true); this.setSize(300,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new JButtonDemo2(); } }
复选按钮 ( JCheckBox)
效果图:
代码:
package top.woodwhale.study5; import javax.swing.*; import java.awt.*; public class JButtonDemo3 extends JFrame { public JButtonDemo3() { Container container = this.getContentPane(); // 多选框 JCheckBox ch1 = new JCheckBox("114514"); JCheckBox ch2 = new JCheckBox("1919810"); container.add(ch1,BorderLayout.NORTH); container.add(ch2,BorderLayout.SOUTH); this.setVisible(true); this.setSize(300,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new JButtonDemo3(); } }
下拉框
效果如下:
代码:
package top.woodwhale.study6; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class ComboDemo1 extends JFrame { public ComboDemo1() { Container contentPane = this.getContentPane(); JComboBox comboBox = new JComboBox(); comboBox.addItem(null); comboBox.addItem("114514"); comboBox.addItem("1919810"); // 监听选择 comboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { System.out.println(comboBox.getSelectedIndex()); System.out.println(comboBox.getSelectedItem()); } }); contentPane.add(comboBox); this.setVisible(true); this.setSize(300,100); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new ComboDemo1(); } }
列表框
效果如下:
代码:
package top.woodwhale.study6; import javax.swing.*; import java.awt.*; import java.util.LinkedList; import java.util.Vector; public class ComboDemo2 extends JFrame { public ComboDemo2() { Container container = this.getContentPane(); // 生成Vector内容 Vector contents = new Vector(); JList jList = new JList(contents); // 动态添加 contents.add("114514"); contents.add("1919810"); container.add(jList); this.setVisible(true); this.setSize(300,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new ComboDemo2(); } }
应用场景:
文本框
效果如下:
代码:
package top.woodwhale.study6; import javax.swing.*; import java.awt.*; public class TextDemo1 extends JFrame { public TextDemo1() { Container container = this.getContentPane(); JTextField t1 = new JTextField("hello"); JTextField t2 = new JTextField("word",20); container.add(t1,BorderLayout.NORTH); container.add(t2,BorderLayout.SOUTH); this.setVisible(true); this.setSize(300,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new TextDemo1(); } }
密码框
默认效果图:
但是我们可以通过setEchoChar的方法来更改显示
代码:
package top.woodwhale.study6; import javax.swing.*; import java.awt.*; public class TestDemo2 extends JFrame { public TestDemo2() { Container container = this.getContentPane(); JPasswordField passwordField = new JPasswordField(); passwordField.setEchoChar('*'); container.add(passwordField); this.setVisible(true); this.setBounds(300,300,300,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new TestDemo2(); } }
文本域
JTextArea可以配合面板使用
效果图(上面在面板中使用的例子):
代码:
package top.woodwhale.study5; import javax.swing.*; import java.awt.*; public class JScrollDemo extends JFrame { public JScrollDemo() { // 容器 Container container = this.getContentPane(); // 文本(20行,50列) JTextArea textArea = new JTextArea(20,50); textArea.setText("114514"); // 滚动条 JScrollPane scrollPane = new JScrollPane(textArea); container.add(scrollPane); this.setVisible(true); this.setBounds(300,300,300,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new JScrollDemo(); } }