【Java学习笔记】java图形界面编程

在前面的章节中,我们开发运行的应用程序都没有图形界面,但是很多应用软件,如Windows下的Office办公软件、扑克牌接龙游戏软件、企业进销存ERP系统等,都有很漂亮的图形界面。素以需要我们开发具有图形界面的软件。
Java图形界面编程内容主要包括AWT(Abstract Window Kit)和Swing两个部分。AWT是用来创建图形界面的基本工具,Swing是JFC(Java Foundation Classes)的一部分,是对AWT的有益补充。

1.AWT简介

AWT是抽象窗口工具类(Abstrat Window ToolKit)的缩写,AWT库中有60多个类和接口,几乎涵盖了创建Java图形界面程序的所有工具。利用AWT类库,可以在Applet的显示区域创建标签、按钮、复选框第二部分,还可以针对用户行为进行响应。
AWT是jdk的一部分,AWT为图形界面程序提供了所需的丰富的组件,同时还提供了对事件类、监听器类、图形处理工具,2D图形的支持
Java AWT类提供了四个主要的类,包括组件类(Component)、容器类(Container)、图形类(Graphics)和布局管理器。
AWT虽然提供了很多对图形界面的支持,但是缺少剪贴板支持、打印支持、没有弹出式菜单和滚动窗口等问题,所以产生了新的组件Swing来解决这些问题。

2.SWING基础

Swing元素比AWT元素存在更好的图形处理性能。Swing具有java的跨平台性,可以在任何平台上使用Swing图形界面组件。Swing的大部分组件是轻量级组件
Swing组件在不同平台上具有一致性的表现。Swing组件比AWT组件的实用性更强。Swing采用了MVC(Model-View-Controller,模型——视图——控制器)模式。

2.1 Swing的类层次结构

在javax.swing包中包含两种类型的组件:顶层容器(JFrame、JApplet、JDialog和JWindow)和轻量级组件。Swing轻量级组件是从AWT的Container类直接或间接派生过来的、
Swing包是JFC(Java Foundation Classes)的一部分,,javax.swing是其中最大的包,并且绝大部分Swing组件都包含在swing包中。
例:javax.swing.event包中定义了事件和事件处理类,这与java.awt.event包类似,主要包括事件类和监听器接口、事件适配等。

2.2 Swing的特点

  • MVC模式:MVC模式包括模型、视图和控制器等部分。Model(模型)用于保存所用到的数据模型,视图(View)用于显示数据内容,控制器(Controller)用于处理用户和模块交互事件。分层后,各层各司其职,协同工作,当模型的数据改变时,会通知与之相关的视图,视图通过控制器指定相应机制。为了更方便,Swing组件将视图和控制器 合二为一。

  • 组件的多样化:Swing组件的类名都是以字母J开头的。
    在这里插入图片描述

  • 可存取性支持 : 所有的Swing组件都实现了Accessible接口,这样一些辅助功能(如:屏幕阅读器)也可以得到支持

  • 设置边框:Swing组件不仅可以设置一个或多个边框,也可以让用户组合边框或自定义属于自己的边框

  • 支持键盘操作:JComponent类的RegisterKeyboardAction()方法可以实现用键盘操作替代用户鼠标操作。

  • 使用图标:Swing组件中的许多组件可以通过图标修饰自己。

2.3 swing程序结构简介

Java Swing的程序设计流程:
(1)使用import关键字导入swing包
(2)设置GUI的“外观界面风格”
(3)创建顶层容器
(4)创建按钮和标签等各种所需的组件
(5)将组件添加到顶层容器
(6)在组件周围添加边界
(7)进行事件处理
(8)结束
在这里插入图片描述

package swing;

import javax.swing.*;		//导入swing包
import java.awt.*;			//导入awt包
import java.awt.event.*;	//导入awt事件处理包


public class FirseSwingApp {

	public static void main(String[] args) {
		
		 try {				//try语句块,监视该段程序
	          UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
	        } catch (Exception e) {		//捕获异常
	            e.printStackTrace();	//输出异常信息
	        }
         
       JFrame frame = new JFrame("我的第一个Swing程序");
       Container c = frame.getContentPane();
       JPanel pane = new JPanel();
       c.add(pane);
       pane.setLayout(new FlowLayout());
       JLabel label = new JLabel();
       JButton button = new JButton("Press me");
       pane.add(label);
       pane.add(button);
       
       // 为增加按钮添加监听
       button.addActionListener(new ActionListener() {

           @Override
           public void actionPerformed(ActionEvent e) {

               label.setText("监听事件成功");
           }
       });
       
       frame.addWindowListener(new WindowAdapter() {
    	   public void windowClosing(WindowEvent e) {
    		   System.exit(0);
    	   }
    	   
       });
       frame.setSize(400,280);
       frame.setVisible(true);
	}

}

3.事件类

每一个事件类都与一个事件类接口相对应,由事件引起的动作都存放在接口需要实现的方法中。Java中,常用的事件类接口包括动作事件类、调整事件类、焦点事件类、项目事件类、按钮事件类、鼠标事件类、窗口事件类。

3.1 事件类的分类

所有与AWT相关的事件类都是java.awt.AWTEvent的派生类,AWTEvent也是java.util.EventObject类的派生类。
AWT事件包括低级事件和高级事件,低级事件时指源于组件或容器的事件,当组件或容器发生事件时,将触发事件。
高级事件是语义事件。这类事件与特定的具体事件不一定相对应,但是会 产生特定的事件对象。

3.2 动作事件类

动作事件类是指发生组件定义的语义事件。使用动作事件时需要给组件添加一个事件监听器ActionListener。ActionListener只有唯一的actionPerformed()方法。

   // 给按钮 增加 监听
        button.addActionListener(new ActionListener() {
  
            // 当按钮被点击时,就会触发 ActionEvent事件
            public void actionPerformed(ActionEvent e) {
                //按钮被操作
            }
        });

3.3 调整事件类

调整事件是滑动滚动条时发生的事件。为了监听调整事件,需要给ScrollBar添加一个调整事件监听器AdjustListener

scrollbar.addAdjustmentListener(new AdjustListener()){
   public void adjustmentValueChanged(AdjustmentEvent e){
   		//调整滚动条
   }
}

3.4 焦点事件类

焦点事件类(FocusEvent)是指界面的组件失去焦点(焦点从一个对象转移到另外一个对象)时就会发生焦点事件。得到焦点事件的组件处于激活状态。

void FocusGained(FocusEvent e){
	// 当获得焦点时发生
}
void FocusLost(FocusEvent e){
	// 当失去焦点时发生
}

3.5 项目事件类

项目事件类(ItemEvent)是指某个项目(Item)时被选定、取消的语义事件,使用项目事件必须给组件添加一个实现ItemListener接口的事件处理器。

void itemStateChange(ItemEvent e)

3.6 键盘事件类

键盘事件类(KeyEvent)是指容器内任意组件获得焦点时,组件发生键击时,组件对象将产生该事件。

 f.addKeyListener(new KeyListener() {
 
           // 键被弹起
           public void keyReleased(KeyEvent e) {
           }
 
           //键被按下
           public void keyPressed(KeyEvent e) {
               // TODO Auto-generated method stub
           }
 
           // 一个按下弹起的组合动作
           public void keyTyped(KeyEvent e) {
           }
       });

3.7 鼠标事件类

鼠标事件类(MouseEvent)是指组件中发生鼠标动作时间,当鼠标移动到某个区域或单击某个组件时会触发鼠标事件。使用鼠标事件需要给组件添加MouseListener接口的事件处理器

 l.addMouseListener(new MouseListener() {
 
           // 释放鼠标
           public void mouseReleased(MouseEvent e) {
               // TODO Auto-generated method stub
 
           }
 
           // 按下鼠标
           public void mousePressed(MouseEvent e) {
               // TODO Auto-generated method stub
 
           }
 
           // 鼠标退出
           public void mouseExited(MouseEvent e) {
               // TODO Auto-generated method stub
 
           }
 
           // 鼠标进入
           public void mouseEntered(MouseEvent e) {
 
           }
 
           // 按下释放组合动作为点击鼠标
           public void mouseClicked(MouseEvent e) {
               // TODO Auto-generated method stub
 
           }
       }); 

3.8 窗口事件类

窗口事件类(WindowEvent)是指窗口状态改变的事件。使用窗口事件必须为组件添加一个实现WindowListener接口的事件处理器。

windowOpened

void windowOpened(WindowEvent e)
窗口首次变为可见时调用。

windowClosing

void windowClosing(WindowEvent e)
用户试图从窗口的系统菜单中关闭窗口时调用。


windowClosed

void windowClosed(WindowEvent e)
因对窗口调用 dispose 而将其关闭时调用。


windowIconified

void windowIconified(WindowEvent e)
窗口从正常状态变为最小化状态时调用。对于很多平台而言,已最小化的窗口将显示为窗口 iconImage 属性中所指定的图标。


windowDeiconified

void windowDeiconified(WindowEvent e)
窗口从最小化状态变为正常状态时调用。


windowActivated

void windowActivated(WindowEvent e)
将 Window 设置为活动 Window 时调用。只有框架或对话框可以成为活动 Window。本机的窗口系统可能使用特殊装饰表示活动 Window 或其子窗口,如高亮显示标题栏。活动 Window 要么是聚焦 Window,要么是作为聚焦 Window 所有者的第一个 Frame 或 Dialog。
windowDeactivated

void windowDeactivated(WindowEvent e)
当 Window 不再是活动 Window 时调用。只有框架或对话框可以成为活动 Window。本机的窗口操作系统可能使用特殊装饰表示活动 Window 或其子窗口,如高亮显示标题栏。活动 Window 要么是聚焦 Window,要么是作为聚焦 Window 所有者的第一个 Frame 或 Dialog。

4 事件监听器

事件监听器的主要任务是对事件进行监听并进行相应处理。事件处理是图形界面程序设计必须做的工作。
当用户使用鼠标、键盘等外部设备输入发生事件时,可以使用事件监听处理器处理这些事件,从而实现相应的事件响应。事件监听器是为了处理特定时间而编写的方法。

4.1 事件监听器接口

不同的事件类对应不同的的事件监听器,他是事件监听器类的接口。

AWT的组件不仅可以注册监听器,还可以注销监听器

public void add<ListenerType> (<ListenerType>  listener ) //注册监听器
public void remove<ListenerType>(<ListenerType>  listener)//注销监听器

在这里插入图片描述

4.2 事件监听器特点

事件监听器接口是一个特殊的接口,与普通的接口相比,不同之处在于:
(1)一个监听器接口的类可以实现一个或或多个接口,并且接口之间用逗号隔开

implements MouseMotionListener,MouseLinstener,WindowListener;

(2) 同一个组件可以监听一个事件源的多个事件
即在对象ob上接收多个事件,并被同一个监听器接收和处理。

ob.addMouseMotionListener(this) ; 		//添加鼠标动作监听器
ob.addMouseListener(this);		//添加鼠标监听器
ob.addWindowListener(this);		//添加窗口监听器

(3)事件处理这和事件源可以处在同一个类中。
上述程序事件中,事件源是窗口对象ob,事件处理这是类TreeListener,其中ob是类TreeLIstener的成员变量
(4)通过事件对象可以获得一些信息。例如,可以获得组件中鼠标的位置坐标。

public void mouseMoved(MouseEvent e){
  	Strng str = "鼠标移动";
  	ob1.setText(s);
  	ob2.setText("鼠标坐标为:" + e.getX() + e.getY());
}

Java语言只支持单继承,但可以通过接口实现多继承的功能。

在AWT中经常实现多个监听器接口,每一个接口中已定义的方法必须实现。如果针对某事件不做任何处理,就不需要实现这个方法,方法体为空。

5.轻量级容器

Jframe的内部轻量级容器结构图:
在这里插入图片描述
在这里插入图片描述
用户添加的组件都在contentPane上,背景图片只能添加到layeredPane.
GlassPane是完全透明的,默认值为不可见。
覆盖content的目的是为了接收鼠标事件和组件绘图功能提供方便。

5.1 根面板(JRootPanel)

根面板(JRootPanel)由contentPane、menuBar、glassPlane构成

5.2 面板(JPanel)

面板(JPanel)是轻量级容器,用法与Panel基本相同,用于收纳其他的组件。

5.3 分层面板(JLayeredPane)

Swing有JLayeredPane、JDesktopPane两种类型的分层面板,JDesktopPane是JLayeredPane的派生类,用于创建多文档和虚拟桌面程序的容器

5.4 滚动窗口(JScrollPane)

滚动窗口(JScrollPane)是管理窗口(JViewport)、可选水平或垂直滚动的轻量级容器。滚动窗口有JScrollBar、JViewPort之间的链接组成

5.5 分隔板(JSplitPane)

分隔板(JSplitPane)用于提供可以拆分的窗口,但只能分割成两个容器。支持水平和竖直两种拆分类型,可带滚动条

5.6 选项板(JTabbedPane)

选项板(JTabbedPane)提供允许用户通过单击具有标题和图标的选项卡,在组件之间进行来回切换的组件,通过addTab()和insertTab()方式添加选项卡、组件到TabbedPane对象中。

5.7 工具栏(JToolBar)

工具栏(JToolBar)是显示常用工具组件的容器。可以将工具栏单独拖出作为一个独立的工具条。

6. Swing组件

Swing组件与AWT组件类似,但又为每个组件添加了新的方法。

6.1 按钮(Button)

在Swing中,所有类型的按钮都是javax.swing.AbstractButton类的子类。

6.2 复选框(JChekBox)

该类是javax.swing.JToggleButton类的子类。

6.3 单选框(JRadioButton)

单选框(JRadioButton)与AWT中的复选框功能类似,
JRadioButton 和 ButtonGroup配合使用时可以创建一组数组,但一次只能选择其中的一个按钮,通过add()方法将JRadioButton对象添加到该组中。

6.4 组合框(JComboBox)

组合框是将按钮、可编辑字段及下拉菜单组合在一起的操作。用户可以从下拉菜单中选则不同的值。

6.5 进度条(JProgressBar)

进度条是以图形化的方式来描述任务进度的组件。在任务完成的过程中,进度条显示该任务完成的百分比。

6.6 表格(JTable)

在界面上将数据以表格的形式展示,可以采用表格控件(JTable)来实现。
表格控件是Swing新增加的组件。主要是为了将数据以表格的形式显示。

6.7 树(JTree)

很多时候需要使用树状控件展示数据,如Windows的文件浏览器就像现行的树状控件。树(JTree)中特定的节点可以由TreePath标识或由其显示行标识。可查看的父类节点都是可以展开的,但是他们可以显示也可以不显示。显示节点必须是可以查看的,并且位于显示区域。

7 拓展训练

7.1 设置闪烁的标题栏

【Timer控件】
在银行,股票,比赛系统中经常出现同时处理并显示业务数据的情况,每个窗口和窗口中的数据分类和重要性并不相通。当有的信息重要性很高,必须以醒目的方式提醒读者注意的时候,可以采用闪烁的标题栏来动态突出某窗口信息的重要性。
【例】在TimerFlashBar类的主方法中创建Timer控件,并在空间中实现窗口闪烁的效果。该效果一直循环,每隔1秒闪烁一次

package swing;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.Timer;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;

public class TimerFlashBar  extends JFrame{
//
//	private static final long serialVersionUID 

	private JPanel contentPane;
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() { //把事件添加到AWT的事件处理线程中
			public void run() {
				try {
					TimerFlashBar frame = new TimerFlashBar();
					frame.setVisible(true);
				}catch(Exception e) {
					e.printStackTrace();
				}
			}
			
		});
	}
	public TimerFlashBar() {
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowOpened(WindowEvent e) {
				do_this_windowOpened(e);
			} 
		});
	setTitle("设置闪烁的标题栏");
	setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	setBounds(100,100,273,130);
	contentPane = new JPanel();
	contentPane.setBorder(new EmptyBorder(5,5,5,5));
	contentPane.setLayout(new BorderLayout(0,0));
	setContentPane(contentPane);
	JLabel label = new JLabel("系统内存紧缺,请立即保存数据");
	label.setHorizontalAlignment(SwingConstants.CENTER);
	}
	protected void do_this_windowOpened(WindowEvent e) {
		Timer timer = new Timer(500,new ActionListener() {
			String title = getTitle();
			public void actionPerformed(ActionEvent e) {
				if(getTitle().isEmpty()) {
					setTitle(title);
				}else {
					setTitle("");
				}
			}
		});
		timer.start();
	}
}

在这里插入图片描述

7.2 建立简单的时钟布局

【布局管理器】
Java提供了流布局、边框布局、网格布局等多种布局方式,其实我们也可以自定义一个布局管理器

package swing;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;

public class UseCloakLayout implements LayoutManager {
	public void addLayoutComponent(String name,Component comp) {
	}
	public void layoutContainer(Container parent) {
		double centerX = parent.getBounds().getCenterX();
		double centerY = parent.getBounds().getCenterY();
		Insets insets = parent.getInsets();
		double horizon = centerX - insets.left;
		double vertical = centerY - insets.top;
		double radius = horizon > vertical ? vertical:horizon;//设置时钟半径
		int count = parent.getComponentCount();//获得控件个数
		for(int i = 0;i<count;i++) {
			Component component = parent.getComponent(i);
			if(component.isVisible()) {
				Dimension size = component.getPreferredSize();
				double angle = 2 * Math.PI*i/count;//获得角度大小
				double x = centerX + radius*Math.sin(angle);
				double y = centerY - radius*Math.cos(angle);
				//重新设置控件的位置和大小
				component.setBounds((int)x-size.width/2,(int)y-size.height/2, size.width, size.height);
			}
		}
	}
	//给定指定容器所包含的控件,计算该容器的最小大小维度数
	@Override
	public Dimension minimumLayoutSize(Container parent) {
		// TODO Auto-generated method stub
		return parent.getMinimumSize();
	}
	@Override
	public Dimension preferredLayoutSize(Container parent) {
		// TODO Auto-generated method stub
		return parent.getPreferredSize();
	}
	@Override
	public void removeLayoutComponent(Component comp) {
		// TODO Auto-generated method stub
	}
	
	
}

package swing;

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;

public class CloakLayoutTest extends JFrame{
	private JPanel contentPane;
	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
		}catch(Throwable e) {
			e.printStackTrace();
		}
		EventQueue.invokeLater(new Runnable() {

			@Override
			public void run() {
				try {
					ClockLayoutTest frame = new ClockLayoutTest();
					frame.setVisible(true);
				}catch(Exception e) {
					e.printStackTrace();
				}
				
			}
			
		});
	}
	
	public CloakLayoutTest() {
		setTitle("建立时钟布局");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100,100,450,300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5,5,5,5));
		contentPane.setLayout(new BorderLayout(0,0));
		setContentPane(contentPane);
		setLayout(new ClockLayoutTest());
		for(int i = 0;i<12;i++) {
			if(i<10) {
				add(new JButton(""+i));
			}else {
				add(new JButton(""+i));
			}
		}

	}


}

7.3简单投票系统

【多个组件的使用】
在日常生活中,我们经常会遇到进行投票的情况。本例实现一个简单的投票计数软件

在这里插入图片描述

package swing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;

public class VoteCount extends JFrame{


		private JPanel contentPane;
		
		//设置4个复选框
		private JCheckBox checkBox1;
		private JCheckBox checkBox2;
		private JCheckBox checkBox3;
		private JCheckBox checkBox4;
		
		//设置4个标签
		private JLabel label1;
		private JLabel label2;
		private JLabel label3;
		private JLabel label4;
		
		//设置4个进度条
		private JProgressBar progressBar1;
		private JProgressBar progressBar2;
		private JProgressBar progressBar3;
		private JProgressBar progressBar4;
		
		public static void main(String[] args) {	
		
			try {
				UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
			}catch(Throwable e){
				e.printStackTrace();
			}
			
			EventQueue.invokeLater(new Runnable() {
				public void run() {
					try {
						VoteCount frame = new VoteCount();
						frame.setVisible(true);
					}catch(Exception e) {
						e.printStackTrace();
					}
				}
			});
	}
		public VoteCount() {
			setTitle("简单投票系统");
			setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			setBounds(100,100,450,300);
			contentPane = new JPanel();
			contentPane.setBorder(new EmptyBorder(5,5,5,5));
			setContentPane(contentPane);
			contentPane.setLayout(new BorderLayout(0,0));
			JPanel buttonPanel = new JPanel();
			contentPane.add(buttonPanel,BorderLayout.SOUTH);
			JButton submitButton = new JButton("提交");
			
			submitButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					do_submitButton_actionPerformed(e);
				}
			});
	
			buttonPanel.add(submitButton);
			JButton refreshButton = new JButton("刷新");
			refreshButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					do_refreshButton_actionPerformed(e);
				}
			});
	
			buttonPanel.add(refreshButton);
			JPanel panel = new JPanel();
			panel.setBorder(new TitledBorder(new LineBorder(new Color(0,0,0)),"我最喜爱的水果"
					,TitledBorder.LEADING,TitledBorder.TOP,null,new Color(59,59,59)));
			
			contentPane.add(panel,BorderLayout.CENTER);
			panel.setLayout(new GridLayout(4,1,15,15));
			//第一条记录
			JPanel panel1 = new JPanel();
			panel.add(panel1);
			panel1.setLayout(new BorderLayout(0,0));
			checkBox1 = new JCheckBox("苹果");
			panel1.add(checkBox1,BorderLayout.WEST);
			label1 = new JLabel("0票");
			panel1.add(label1,BorderLayout.EAST);
			progressBar1 = new JProgressBar();
			progressBar1.setStringPainted(true);
			panel1.add(progressBar1,BorderLayout.CENTER);
			
			//第二条记录
			JPanel panel2 = new JPanel();
			panel.add(panel2);
			panel2.setLayout(new BorderLayout(0,0));
			checkBox2 = new JCheckBox("香蕉");
			panel2.add(checkBox2,BorderLayout.WEST);
			label2 = new JLabel("0票");
			panel2.add(label2,BorderLayout.EAST);
			progressBar2 = new JProgressBar();
			progressBar2.setStringPainted(true);
			panel2.add(progressBar2,BorderLayout.CENTER);
			
			
			//第三条记录
			JPanel panel3 = new JPanel();
			panel.add(panel3);
			panel3.setLayout(new BorderLayout(0,0));
			checkBox3 = new JCheckBox("梨");
			panel3.add(checkBox3,BorderLayout.WEST);
			label3 = new JLabel("0票");
			panel3.add(label3,BorderLayout.EAST);
			progressBar3 = new JProgressBar();
			progressBar3.setStringPainted(true);
			panel3.add(progressBar3,BorderLayout.CENTER);
			
			
			//第四条记录
			JPanel panel4 = new JPanel();
			panel.add(panel4);
			panel4.setLayout(new BorderLayout(0,0));
			checkBox4 = new JCheckBox("桃子");
			panel4.add(checkBox4,BorderLayout.WEST);
			label4 = new JLabel("0票");
			panel4.add(label4,BorderLayout.EAST);
			progressBar4 = new JProgressBar();
			progressBar4.setStringPainted(true);
			panel4.add(progressBar4,BorderLayout.CENTER);
			
		}

		protected void do_submitButton_actionPerformed(ActionEvent e) {
			
			String text1 = label1.getText(); //获得标签文本
			int number1 = Integer.parseInt(text1.substring(0,text1.length()-1));//获得票数
			
			String text2 = label1.getText(); //获得标签文本
			int number2 = Integer.parseInt(text1.substring(0,text1.length()-1));//获得票数
			
			String text3 = label1.getText(); //获得标签文本
			int number3 = Integer.parseInt(text1.substring(0,text1.length()-1));//获得票数
			
			String text4 = label1.getText(); //获得标签文本
			int number4 = Integer.parseInt(text1.substring(0,text1.length()-1));//获得票数
			
			
			if(checkBox1.isSelected()) { //如果被选中
				number1++;				//票数+1
				label1.setText(number1+"票");//更新标签
			}
			
			if(checkBox2.isSelected()) {
				number2++;
				label2.setText(number2+"票");
			}
			
			if(checkBox3.isSelected()) {
				number3++;
				label3.setText(number3+"票");
			}
			
			if(checkBox4.isSelected()) {
				number4++;
				label4.setText(number4+"票");
			}
			
			//计算总票数
			double total = number1 + number2 + number3 +number4;
			
			progressBar1.setString(number1*100/total+"%"); //在进度条上显示票数
			progressBar1.setValue(number1);
			
			progressBar2.setString(number2*100/total+"%"); //在进度条上显示票数
			progressBar2.setValue(number2);
			
			progressBar3.setString(number3*100/total+"%"); //在进度条上显示票数
			progressBar3.setValue(number3);
			
			progressBar4.setString(number4*100/total+"%"); //在进度条上显示票数
			progressBar4.setValue(number4);
			
			
		}
		
		
		protected void do_refreshButton_actionPerformed(ActionEvent e) {
			//建立动作事件的响应
			checkBox1.setSelected(false);
			checkBox2.setSelected(false);
			checkBox3.setSelected(false);
			checkBox4.setSelected(false);
		}
		

}

7.4 包含图片的弹出菜单

【JPopMenu的使用】
Windows应用软件单击鼠标右键,会出现一个弹出菜单,菜单可以进行排列桌面图片、创建文件或文件夹等操作。本例演示如何利用Swing创建包含图片的弹出菜单

package swing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;

class PopupMenuImage extends Frame{
	
	private JPanel contentPane;
	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
		}catch(Throwable e) {
			e.printStackTrace();
		}
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					PopupMenuImage frame = new PopupMenuImage();
					frame.setVisible(true);
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		});
	}
	
	public PopupMenuImage() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100,100,300,200);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5,5,5,5));
		
		JPopupMenu popupMenu = new JPopupMenu();
		
		contentPane.setComponentPopupMenu(popupMenu);
		
		JMenuItem cut = new JMenuItem("剪切");
		cut.setIcon(new ImageIcon(PopupMenuImage.class.getResource("./cut.jpg")));
		cut.addActionListener(listener);
		popupMenu.add(cut);
		
		JMenuItem copy = new JMenuItem("拷贝");
		copy.setIcon(new ImageIcon(PopupMenuImage.class.getResource("./cpoy.jpg")));
		copy.addActionListener(listener);
		popupMenu.add(copy);
		
		JMenuItem paste = new JMenuItem("粘贴");
		paste.setIcon(new ImageIcon(PopupMenuImage.class.getResource("./paste.jpg")));
		paste.addActionListener(listener);
		popupMenu.add(paste);
		
		contentPane.setLayout(new BorderLayout(0,0));
		setContentPane(contentPane);
		label = new JLabel("单击鼠标右键弹出菜单");
		contentPane.add(label,BorderLayout.NORTH);
	}
	

private void setDefaultCloseOperation(int exitOnClose) {
		// TODO Auto-generated method stub
		
	}

private void setContentPane(JPanel contentPane2) {
		// TODO Auto-generated method stub
		
	}


private ActionListener listener = new ActionListener() {
	public void actionPerformed(ActionEvent e) {
		label.setText(e.getActionCommand());
	}
	
};
private JLabel label;
	

}

7.5 震动效果提示信息

在这里插入图片描述

package swing;

import javax.swing.Timer;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JDialog;
import javax.swing.JOptionPane;

public class ShakeEffect {

    private JDialog dialog;
    private Point start;
    private Timer shakeTimer;

    public ShakeEffect(JDialog dialog) {
        this.dialog = dialog;
    }
    public void startShake() { //开始震动方法
        final long startTime = System.currentTimeMillis();//获得程序运行起始时间
        start = dialog.getLocation();
        shakeTimer = new Timer(10,new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                long elapsed = System.currentTimeMillis() - startTime;
                Random random = new Random(elapsed);
                int change = random.nextInt(50);
                dialog.setLocation(start.x +change,start.y+change);//随机改变坐标
                if(elapsed >=1000) {
                    stopShake();
                }
            }
        });
        shakeTimer.start();

    }

    public void stopShake() {
        shakeTimer.stop();
        dialog.setLocation(start);
        dialog.repaint();
    }

    public static void main(String[] args) {

        JOptionPane pane = new JOptionPane("特别注意",JOptionPane.WARNING_MESSAGE);
        JDialog d = pane.createDialog(null,"震动效果对话框");//获得对话框对象
        ShakeEffect sd = new ShakeEffect(d);
        d.pack();
        d.setModal(false);
        d.setVisible(true);
        sd.startShake();



    }


}

8 答疑解惑

swing是一个用于开发Java应用程序图形界面的开发工具包,以抽象窗口工具包(AWT)为基础使跨平台应用程序可以使用任何可插拔的外观风格。
一般的桌面应用,使用Java Swing是绰绰有余的。但是大型网站、ERP等大型项目不适合使用Swing。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/767789.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux线程:编织并发的梦幻世界

目录 &#x1f6a9;引言 &#x1f6a9;听故事&#xff0c;引概念 &#x1f6a9;生产者消费者模型 &#x1f680;再次理解生产消费模型 &#x1f680;挖掘特点 &#x1f6a9;条件变量 &#x1f680;条件变量常用接口 &#x1f680;条件变量的原理 &#x1f6a9;引言 上一篇…

学习LLM的随笔

1、信息量、信息熵、交叉熵和困惑度 &#xff08;1&#xff09;信息熵&#xff1a;信息熵中使用 l o g 2 ( p ( x ) ) log_2(p(x)) log2​(p(x)) 来表示对 x x x 编码需要的编码长度。由于不同事件发生的概率不同&#xff0c;我们不能简单地将这些信息量相加&#xff0c;而应…

Day01-02-gitlab

Day01-02-gitlab 1. 什么是gitlab2. Gitlab vs Github/Gitee3. Gitlab 应用场景4. 架构5. Gitlab 快速上手指南5.0 安装要求5.1 安装Gitlab组件5.3 配置访问url5.6 初始化5.8 登录与查看5.9 汉化5.10 设置密码5.11 目录结构5.12 删除5.13 500 vs 5025.14 重置密码 6. Gitlab用户…

springboot美术馆售票管理系统-计算机毕业设计源码17485

目录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 2.2.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 系统总体设…

PMP报考条件是什么?很多人都没读懂...

最近正值8月份考试报名期&#xff0c;想计划考8月份考试的宝子可以准备起来了&#xff0c;下面是报名时间和考试安排 8月考试时间安排&#xff1a; &#x1f449;报名时间在7.9日—12日 &#x1f449;考试时间在8.31日&#xff08;周六&#xff09; 一、PMP报名条件是什么&am…

vue3中 slot使用

默认插槽&#xff1a; 这是最基本的插槽类型&#xff0c;当没有指定 name 属性时&#xff0c;插槽是默认插槽。 子组件&#xff1a; <template><div class"child"><h2>子组件内容</h2><slot></slot> <!-- 默认插槽&#x…

反射快速入门

反射就是通过字节码文件获取类的成员变量、构造方法和成员方法的所有信息。 利用反射&#xff0c;我们可以获取成员变量的修饰符、名字、类型、取值。我们可以获取构造方法的名字、形参&#xff0c;并利用通过反射获取的构造方法创建对象。我们可以获取成员方法的修饰符、名字、…

LeetCode 子集

原题链接78. 子集 - 力扣&#xff08;LeetCode&#xff09; 这是一道暴力搜索问题参考大佬们的题解&#xff0c;对这类题目做出一下总结 1.确定递归参数变量 2.递归结束条件 3.做出选择&#xff0c;递归调用进入下一层 4.回溯&#xff0c;返回到递归前的状态 要完成前面这…

2024Datawhale-AI夏令营——机器学习挑战赛——学习笔记

#ai夏令营#datawhale#夏令营 Day1:入门级demo运行 这个其实比较简单&#xff0c;按照操作来做就行了&#xff0c;特征工程和调参暂时都没有做&#xff0c;后续的才是重头戏。

你想活出怎样的人生?

hi~好久不见&#xff0c;距离上次发文隔了有段时间了&#xff0c;这段时间&#xff0c;我是裸辞去感受了一下前端市场的水深火热&#xff0c;那么这次咱们不聊技术&#xff0c;就说一说最近这段时间的经历和一些感触吧。 先说一下自己的个人情况&#xff0c;目前做前端四年&am…

时钟服务器方案选型推荐:ATGM332D-5T和ATGM331C-5T

ATGM331C-5T系列模块同样是具有高灵敏度、低功耗、低成本等优势&#xff0c;适用于电力授时设备、时钟服务器、守时设备&#xff0c;可以直接替换Ublox LEA T系列模块。 性能指标&#xff1a; 从下面的图来看&#xff0c;ATGM331C-5T系列比ATGM332D-5T系列性能更好&#xff0c;…

大模型对汽车行业意味着什么?_汽车企业大模型

引 言 大模型是一种利用海量数据进行训练的深度神经网络模型&#xff0c;其特点是拥有庞大的参数规模和复杂的计算结构。通过在大规模数据集上进行训练&#xff0c;大模型能够学习到丰富的模式和特征&#xff0c;从而具备强大的泛化能力&#xff0c;可以对未知数据做出准确的预…

轻松省电!教你苹果手机自动调节亮度怎么设置

在日常使用手机的过程中&#xff0c;屏幕亮度是影响电池续航的关键因素之一。苹果手机提供的自动调节亮度功能&#xff0c;可以根据环境光线自动调整屏幕亮度&#xff0c;从而提供最佳的视觉体验并有效延长电池使用时间。想知道苹果手机自动调节亮度怎么设置吗&#xff1f; 本…

如何使用巴比达免费内网穿透服务

#灵感# 访问内部网络资源变得越来越重要。无论是远程办公、远程监控设备还是远程管理服务器&#xff0c;内网穿透技术都提供了一种安全、便捷的解决方案。巴比达&#xff08;Babada&#xff09;作为一种免费的内网穿透服务&#xff0c;为用户提供了快速、安全地访问其内部网络中…

AI人才争夺战:巨头眼中的产品经理必备技能

前言 在人工智能的浪潮下&#xff0c;BAT等一线互联网企业纷纷加码布局&#xff0c;对AI领域的人才需求空前高涨。然而&#xff0c;要在众多求职者中脱颖而出&#xff0c;成为企业眼中的人才&#xff0c;不仅需要深厚的产品功底&#xff0c;更要具备对AI的深刻理解和应用能力。…

JAVASE进阶day03(lamda表达式 ,内部类)

内部类 1.内部类的基本使用 package com.lu.day03;public class Student {private int b 12;public class A{private int b 11;public void show(){int b 10;System.out.println("我是A");System.out.println(b);System.out.println(this.b);System.out.println(…

开源即正义,3D软件Blender设计指南

在当今数字化时代&#xff0c;开源软件的崛起不仅代表着技术的发展&#xff0c;更象征着一种信息自由和技术民主的理念。其本质是集众人之智&#xff0c;共同去完善一个软件&#xff0c;最终使双方互惠共赢。具体来说&#xff0c;开源的价值&#xff0c;在于打破资源垄断&#…

PIN对PIN替代T J A 1 0 2 8,LIN芯片

内部集成高压 LDO&#xff08;耐压 40V&#xff09; 稳压源&#xff0c;可为外部 ECU微控制器或相关外设提供稳定的 5V/3.3V 电源&#xff0c;输出电流可达70mA&#xff1b; 可在 5.5V ~ 28V 电压范围内工作&#xff0c;支持 12V 应用。在休眠模式下可实现极低电流消耗&#x…

Java集合整理笔记

目录 1.集合基础概念 1.1 集合 1.2 单例集合 1.2.1 List系列 1、ArrayList 2、LinkedList 3、Voctor​编辑 1.2.2 Set系列 1、HashSet 集合 2、LinkedHashSet 集合 3、TreeSet集合 1.3 双例集合 1.3.1 HashMap 1.3.2 LinkedHashMap 1.3.3 TreeMap 1.4 快速失败…

python pdfplumber优化表格提取

样例pdf 直接使用文本提取效果&#xff1a; 使用表格提取 根据提取的文本信息是没办法获取到表格数据的&#xff0c;太乱了。尤其是 3 4列。 解决&#xff1a; 自行画线&#xff0c;根据画线进行提取。 效果&#xff1a; 思路&#xff1a; 1.根据表头进行画竖线 2.根据行坐…