Java GUI
java的GUI编程主要使用两个库:AWT和Swing
AWT
AWT (Abstract Window Toolkit)
是Java的原始图形工具包,它是Java平台的一部分,自Java
1.0版本起就存在了。
它提供了基本的GUI组件,如窗口、按钮、文本框等,以及布局管理器和事件处理机制。AWT组件是本地平台依赖的,这意味着AWT组件的外观和行为可能会因操作系统的不同而有所差异。AWT的优点在于它与平台紧密集成,运行速度快
然而,AWT的缺点也很明显
----因为它是本地依赖的,所以AWT应用程序的可移植性较差。
----AWT的界面风格相对较为古老,不如现代图形界面库那样美观。
Swing
Swing是Java的一个扩展图形工具包,基于AWT构建。
Swing组件是平台无关的,在不同的操作系统上看起来和行为都非常相似。它还提供了更高级的功能,如拖放支持、表格和树形控件等。
Swing的优点在于其跨平台兼容性和丰富的组件库。
然而,Swing也有一些缺点。
----某些情况下可能会比AWT原生组件慢一些。
----在处理复杂布局和高级图形效果时可能不如其他现代图形库那样灵活和高效。
AWT
Container
Container实际上继承自Components
用于存储其他components,本身没有实际作用
Frame
Frame是用于承载整个窗口的容器
常常自定义一个新的容器来继承Frame,并在构造函数中初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class Main{ public static void main(String[] args) { frame fr = new frame("Hello Java GUI"); } }
class frame extends Frame{ public frame(String title) { super(title); setVisible(true); setSize(400,400); setBackground(new Color(59, 162, 198)); addWindowListener(new WindowAdapter(){ @Override public void windowClosing(WindowEvent e) { System.exit(0); }; }); } }
|
Panel
Panel是用于装载组件的容器
一般来说,一个Frame包含多个Panel,一个Panel包含多个组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class frame extends Frame{ public Panel panel = new Panel(); public frame(String title) { super(title); setBounds(100,100,400,400); setBackground(new Color(59, 162, 198)); setVisible(true); setLayout(null); add(panel);
panel.setBounds(100,100,200,200); panel.setBackground(new Color(225, 20, 20, 242)); panel.setVisible(true); } }
|
LayoutManager
LayoutManger主要有三个子类:FlowLayout(流式布局)、GridLayout(表格布局)、BorderLayout(边缘布局)
this.setLayout(null) -> 绝对布局
FlowLayout
从左到右,从上到下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class frame extends Frame{ public Button but1 = new Button("button1"); public Button but2 = new Button("button2"); public Button but3 = new Button("button3"); public Button but4 = new Button("button4"); public Button but5 = new Button("button5"); public Button but6 = new Button("button6");
public frame(String title) { super(title); setBounds(100,100,200,200); setBackground(new Color(59, 162, 198)); setVisible(true); setLayout(new FlowLayout());
add(but1);add(but2);add(but3);add(but4);add(but5);add(but6); } }
|
BorderLayout
按东西南北中的顺序,依次排布
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class frame extends Frame{ public Button but1 = new Button("east"); public Button but2 = new Button("west"); public Button but3 = new Button("south"); public Button but4 = new Button("north"); public Button but5 = new Button("center");
public frame(String title) { super(title); setBounds(100,100,200,200); setBackground(new Color(59, 162, 198)); setVisible(true); setLayout(new BorderLayout()); add(but1,BorderLayout.EAST); add(but2,BorderLayout.WEST); add(but3,BorderLayout.SOUTH); add(but4,BorderLayout.NORTH); add(but5,BorderLayout.CENTER); } }
|
GridLayout
表格布局,设置几行几列,从左到右,从上到下地放入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class frame extends Frame{ public Button but1 = new Button("button1"); public Button but2 = new Button("button2"); public Button but3 = new Button("button3"); public Button but4 = new Button("button4"); public Button but5 = new Button("button5"); public Button but6 = new Button("button6");
public frame(String title) { super(title); setBounds(100,100,200,200); setBackground(new Color(59, 162, 198)); setVisible(true); setLayout(new GridLayout(2,3,10,10)); add(but1);add(but2);add(but3);add(but4);add(but5);add(but6); } }
|
Mix-used
通过对Panel和Frame分别设置不同的LayoutManager来实现多种布局方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class frame extends Frame{ public Panel p1 = new Panel(new BorderLayout()); public Panel tab1 = new Panel(new GridLayout(2,1)); public Panel p2 = new Panel(new BorderLayout()); public Panel tab2 = new Panel(new GridLayout(2,2));
public frame(String title) { super(title); setBounds(100,100,400,400); setBackground(new Color(59, 162, 198)); setVisible(true); setLayout(new GridLayout(2,1));
p1.add(new Button("east-1"),BorderLayout.EAST); p1.add(new Button("west-1"),BorderLayout.WEST); p1.add(tab1,BorderLayout.CENTER); tab1.add(new Button("tab1-(1,1)")); tab1.add(new Button("tab1-(2-1)"));
p2.add(new Button("east-2"),BorderLayout.EAST); p2.add(new Button("west-2"),BorderLayout.WEST); p2.add(tab2,BorderLayout.CENTER); tab2.add(new Button("tab2-(1,1)")); tab2.add(new Button("tab2-(1,2)")); tab2.add(new Button("tab2-(2,1)")); tab2.add(new Button("tab2-(2,2)"));
add(p1);add(p2); } }
|
EventLisener
Java提供了如下接口来实现 自定义的
监听器接口,它们都继承自EventListener
WindowListener 窗口监听
MouseListener 鼠标监听
ActionListener 动作监听
KeyListener 键盘监听
WindowListener
窗口监听器,常用的就只有windowClosing和windowActivated
分别是关闭和打开窗口时候发生的事件
1 2 3 4 5 6 7 8 9
| public interface WindowListener extends EventListener { public void windowOpened(WindowEvent e); public void windowClosing(WindowEvent e); public void windowClosed(WindowEvent e); public void windowIconified(WindowEvent e); public void windowDeiconified(WindowEvent e); public void windowActivated(WindowEvent e); public void windowDeactivated(WindowEvent e); }
|
直接实现该接口的方法需要重写每个类,可以采用适配器模式,
继承WindowAdaptor,只需要重写部分需要的事件
1 2 3 4 5 6
| addWindowListener(new WindowAdapter(){ @Override public void windowClosing(WindowEvent e) { System.exit(0); }; });
|
MouseListener
包括如下五种事件
1 2 3 4 5 6 7
| public interface MouseListener extends EventListener { public void mouseClicked(MouseEvent e); public void mousePressed(MouseEvent e); public void mouseReleased(MouseEvent e); public void mouseEntered(MouseEvent e); public void mouseExited(MouseEvent e); }
|
同理,可以继承MouseAdaptor简化重写操作,例如:
1 2 3 4 5 6 7 8
| private class MyMouseListener extends MouseAdapter{ @Override public void mousePressed(MouseEvent e) { Point p = new Point(e.getX(),e.getY()); points.add(p); repaint(); } }
|
ActionListener
ActionListener接口里只有一个事件函数actionPerformed
通常是添加在Button和TextField组件上的监听器,例如:
1 2 3 4 5 6 7
| private class MyActionListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { System.out.println(tf.getText()); } }
|
以及
1 2 3 4 5 6 7
| private class MyActionListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { System.out.println(tf.getText()); } }
|
KeyListener
接口模式:
1 2 3 4 5
| public interface KeyListener extends EventListener { public void keyTyped(KeyEvent e); public void keyPressed(KeyEvent e); public void keyReleased(KeyEvent e); }
|
适配器模式:
1 2 3 4 5 6
| private class MyKeyListener extends KeyAdapter{ @Override public void keyPressed(KeyEvent e) { System.out.print(e.getKeyChar()); } }
|
在KeyEvent类中,存在可以判断几乎所有键盘按键的字段
例如:如下实现了判断上下左右四个按键
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| private class MyKeyListener extends KeyAdapter{ @Override public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_UP){ System.out.println("up"); }else if(e.getKeyCode() == KeyEvent.VK_DOWN){ System.out.println("down"); }else if(e.getKeyCode() == KeyEvent.VK_LEFT) { System.out.println("left"); }else if(e.getKeyCode() == KeyEvent.VK_RIGHT) { System.out.println("right"); } } }
|
Component
使用button实现一个简单的输出事件
--外部类写法,需要使用参数传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class frame extends Frame{ public Button but = new Button("press to print"); static int ClickCount = 0; public frame(String title) { super(title); setBounds(100, 100, 300, 300); setBackground(Color.white); setVisible(true); setLayout(null); but.setBounds(100, 100, 100, 100); but.addActionListener(new MyActionListener(this)); add(but); } }
class MyActionListener implements ActionListener { private frame fr = null; public MyActionListener(frame fr_){ fr = fr_; } @Override public void actionPerformed(ActionEvent e){ System.out.println("The Button is pressed." + (++fr.ClickCount) ); } }
|
--内部类写法,节省了参数传递的步骤,更简洁(后续案例都采用内部类监听器)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class frame extends Frame{ public Button but = new Button("press to print"); static int ClickCount = 0; public frame(String title) { super(title); setBounds(100, 100, 300, 300); setBackground(Color.white); setVisible(true); setLayout(null); but.setBounds(100, 100, 100, 100); but.addActionListener(new MyActionListener()); add(but); } private class MyActionListener implements ActionListener { @Override public void actionPerformed(ActionEvent e){ System.out.println("The Button is pressed." + (++ClickCount) ); } } }
|
TextField
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class frame extends Frame{ public TextField tf = new TextField(); public frame(String title) { super(title); setBounds(100, 100, 300, 300); setBackground(Color.white); setVisible(true); addWindowListener(new MyWindowsListener()); tf.addActionListener(new MyActionListener()); add(tf); } private class MyWindowsListener extends WindowAdapter{ @Override public void windowClosing(WindowEvent e) { System.exit(0); } } private class MyActionListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { System.out.println(tf.getText()); } } }
|
A Simple Caculator
使用Button和TextField实现一个简单的加法计算器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public class Main{ public static void main(String[] args) { new frame("Caculator"); } }
class frame extends Frame{ private TextField tf1 = new TextField(5); private TextField tf2 = new TextField(5); private TextField tf3 = new TextField(10); private Label lb = new Label("+"); private Button but = new Button("="); private int num1,num2,num3;
public frame(String title) { super(title); setBounds(100, 100, 400, 200); setBackground(Color.white); setLayout(new FlowLayout(FlowLayout.CENTER,15,50)); addWindowListener(new MyWindowsListener()); setVisible(true);
add(tf1);add(lb);add(tf2);add(but);add(tf3);
but.addActionListener(new MyActionListener()); } private class MyWindowsListener extends WindowAdapter{ @Override public void windowClosing(WindowEvent e) { System.exit(0); } } private class MyActionListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e){ try{ num1 = Integer.parseInt(tf1.getText()); num2 = Integer.parseInt(tf2.getText()); num3 = num1 + num2; tf3.setText(String.valueOf(num3)); }catch(Exception er){ tf3.setText("ERROR"); } } } }
|
Paint
paint函数在初始化的时候,会调用一次
重写paint函数,并调用Graphics中的函数来实现绘图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class frame extends Frame{
public frame(String title) { super(title); setBounds(100, 100, 400, 400); setBackground(Color.white); addWindowListener(new MyWindowsListener()); setVisible(true); } private class MyWindowsListener extends WindowAdapter { @Override public void windowClosing(WindowEvent e) { System.exit(0); } } @Override public void paint(Graphics g){ super.paint(g); g.setColor(Color.BLUE); g.fillOval(100,100,100,100); g.setColor(Color.RED); g.fillRect(50,50,50,50); } }
|
使用鼠标监听器实现单击画点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public class Main{ public static void main(String[] args) { new frame("Painting Points"); } } class frame extends Frame{ ArrayList points = new ArrayList<Point>();
public frame(String title) { super(title); setBounds(100, 100, 400, 400); setBackground(Color.white); addWindowListener(new MyWindowsListener()); addMouseListener(new MyMouseListener()); setVisible(true); } private class MyWindowsListener extends WindowAdapter { @Override public void windowClosing(WindowEvent e) { System.exit(0); } } private class MyMouseListener extends MouseAdapter{ @Override public void mousePressed(MouseEvent e) { Point p = new Point(e.getX(),e.getY()); points.add(p); repaint(); } } @Override public void paint(Graphics g) { super.paint(g); Iterator it = points.iterator(); while(it.hasNext()){ Point p = (Point)it.next(); g.setColor(Color.BLUE); g.fillOval(p.x,p.y,10,10); } }
}
|
Swing
JFrame
在JFrame中,往窗体中放组件和设置布局、颜色,需要调用getContentPane()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Main{ public static void main(String[] args) { new jframe("Hello JFrame"); } }
class jframe extends JFrame{ JLabel lb = new JLabel("This is a JLabel text"); public jframe(String title) { super(title); setBounds(100, 100, 400, 400); setVisible(true); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); Container ctr = this.getContentPane(); ctr.setBackground(Color.CYAN); lb.setHorizontalAlignment(SwingConstants.CENTER); ctr.add(lb); } }
|
JDialog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| class jframe extends JFrame{ JButton jbut = new JButton("Press to show a JDialog"); public jframe(String title) { super(title); setBounds(100, 100, 400, 400); setVisible(true); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); jbut.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { new MyJDialog(); } }); Container ctr = this.getContentPane(); ctr.setLayout(null); ctr.setBackground(Color.CYAN); jbut.setBounds(100,100,200,100); jbut.setHorizontalAlignment(SwingConstants.CENTER); ctr.add(jbut); } }
class MyJDialog extends JDialog{ JLabel jlb = new JLabel("I am a JLabel in JDialog"); public MyJDialog(){ super(); setBounds(100,100,200,200); setVisible(true); Container ctr = getContentPane(); jlb.setHorizontalAlignment(SwingConstants.CENTER); ctr.add(jlb); } }
|
ImageIcon
为label插入本地图标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class jframe extends JFrame{ JLabel jlb = new JLabel("here is Label"); public jframe(String title) { super(title); setBounds(100, 100, 400, 400); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); Container ctr = this.getContentPane(); ctr.setLayout(null); ctr.setBackground(Color.white);
URL url = jframe.class.getResource("test.jpg"); ImageIcon icon = new ImageIcon(url); Image newImage = icon.getImage().getScaledInstance(50, 50, Image.SCALE_DEFAULT); icon = new ImageIcon(newImage);
jlb.setIcon(icon); jlb.setBounds(100,100,200,50); jlb.setHorizontalAlignment(SwingConstants.CENTER); ctr.add(jlb); setVisible(true); } }
|
为Button插入图标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class jframe extends JFrame{ JButton jbut = new JButton(); public jframe(String title) { super(title); setBounds(100, 100, 300, 300); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
URL resource = jframe.class.getResource("test.jpg"); ImageIcon icon = new ImageIcon(resource); Image icon_new = icon.getImage().getScaledInstance(50,50,Image.SCALE_DEFAULT); icon = new ImageIcon(icon_new);
jbut.setIcon(icon); jbut.setBounds(100,100,100,50); Container ctr = this.getContentPane(); ctr.setLayout(null); ctr.setBackground(Color.white); ctr.add(jbut);
setVisible(true); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class jframe extends JFrame{ JTextArea jtextArea = new JTextArea("hello JTextArea",20,20); JScrollPane jScrollPane = new JScrollPane(jtextArea); public jframe(String title) { super(title); setBounds(100, 100, 200, 300); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); Container ctr = this.getContentPane(); ctr.setBackground(Color.white); ctr.add(jScrollPane); setVisible(true); } }
|
单选框
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class jframe extends JFrame{ public jframe(String title) { super(title); setBounds(100, 100, 300, 300); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JRadioButton jbut1 = new JRadioButton("but1"); JRadioButton jbut2 = new JRadioButton("but2"); JRadioButton jbut3 = new JRadioButton("but3");
ButtonGroup butGrp = new ButtonGroup(); butGrp.add(jbut1); butGrp.add(jbut2); butGrp.add(jbut3);
Container ctr = this.getContentPane(); ctr.setLayout(new FlowLayout()); ctr.setBackground(Color.white); ctr.add(jbut1); ctr.add(jbut2); ctr.add(jbut3);
setVisible(true); } }
|
JCheckBox
复选框
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class jframe extends JFrame{ public jframe(String title) { super(title); setBounds(100, 100, 300, 300); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JCheckBox jck1 = new JCheckBox("jck1"); JCheckBox jck2 = new JCheckBox("jck2"); JCheckBox jck3 = new JCheckBox("jck3");
Container ctr = this.getContentPane(); ctr.setLayout(new FlowLayout()); ctr.setBackground(Color.white); ctr.add(jck1); ctr.add(jck2); ctr.add(jck3);
setVisible(true); } }
|
JComboBox
下拉框
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class jframe extends JFrame{ public jframe(String title) { super(title); setBounds(100, 100, 300, 300); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JComboBox jcb = new JComboBox();
jcb.addItem("Chinese"); jcb.addItem("English"); jcb.addItem("French"); Container ctr = this.getContentPane(); ctr.setLayout(new FlowLayout()); ctr.setBackground(Color.white); ctr.add(jcb);
setVisible(true); } }
|
JList
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class jframe extends JFrame{ public jframe(String title) { super(title); setBounds(100, 100, 300, 300); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
String []strs = {"Chinese","English","French"};
JList jlist = new JList(strs);
Container ctr = this.getContentPane(); ctr.setLayout(new FlowLayout()); ctr.setBackground(Color.white); ctr.add(jlist);
setVisible(true); } }
|
JTextField
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class jframe extends JFrame{ public jframe(String title) { super(title); setBounds(100, 100, 300, 300); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JTextField jtf = new JTextField("请在此输入文本",20); JPasswordField jpf = new JPasswordField("请输入密码",20); jpf.setEchoChar('&');
Container ctr = this.getContentPane(); ctr.setLayout(new FlowLayout()); ctr.setBackground(Color.white); ctr.add(jtf); ctr.add(jpf);
setVisible(true); } }
|
JMenuBar -- 菜单栏
JMenu -- 菜单/子菜单
JMenuItem -- 菜单项(最小单元)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| class jframe extends JFrame{ public jframe(String title) { super(title); setBounds(100, 100, 300, 300); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JMenuBar jmb = new JMenuBar(); JMenu CN = new JMenu("China"); JMenu bj = new JMenu("Beijing"); bj.add(new JMenuItem("haidian")); bj.add(new JMenuItem("chaoyang")); JMenuItem fj = new JMenuItem("Fujian"); JMenuItem sh = new JMenuItem("Shanghai");
fj.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JDialog jb = new JDialog(); jb.setBounds(500,500,300,300); jb.add(new JLabel("WELCOME TO FUJIAN!!!")); jb.setVisible(true); } }); JMenu US = new JMenu("The United State"); JMenuItem bmh = new JMenuItem("Birmingham"); JMenuItem la = new JMenuItem("LosAngeles"); JMenuItem sf = new JMenuItem("SanFrancisco"); JMenu UK = new JMenu("The United Kingdom"); JMenuItem ld = new JMenuItem("London"); JMenuItem edb = new JMenuItem("Edinburgh"); JMenuItem oxf = new JMenuItem("Oxford"); CN.add(fj);CN.add(bj);CN.add(sh); US.add(bmh);US.add(la);US.add(sf); UK.add(ld);UK.add(edb);UK.add(oxf); jmb.add(CN); jmb.add(US); jmb.add(UK); setJMenuBar(jmb); Container ctr = this.getContentPane(); ctr.setLayout(new FlowLayout()); ctr.setBackground(Color.white); setVisible(true); } }
|