【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。

相关推荐
xiaoyalian28 分钟前
R语言绘图过程中遇到图例的图块中出现字符“a“的解决方法
笔记·r语言·数据可视化
吾日三省吾码1 小时前
JVM 性能调优
java
弗拉唐2 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
Red Red2 小时前
网安基础知识|IDS入侵检测系统|IPS入侵防御系统|堡垒机|VPN|EDR|CC防御|云安全-VDC/VPC|安全服务
网络·笔记·学习·安全·web安全
oi773 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
贰十六3 小时前
笔记:Centos Nginx Jdk Mysql OpenOffce KkFile Minio安装部署
笔记·nginx·centos
少说多做3433 小时前
Android 不同情况下使用 runOnUiThread
android·java
知兀3 小时前
Java的方法、基本和引用数据类型
java·笔记·黑马程序员
蓝黑20203 小时前
IntelliJ IDEA常用快捷键
java·ide·intellij-idea