栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java学习笔记(事件驱动程序设计)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java学习笔记(事件驱动程序设计)

Java学习笔记(事件驱动程序设计)
    • 学习说明
    • 第十六章 事件驱动程序设计
      • 事件和事件源的概念
      • 监听器、注册以及处理事件
      • 内部类的使用
      • 匿名类监听器
      • 定义监听器的另一种方式
      • 框架代码(精简版)
      • 计算贷款率的小程序
      • 窗口事件
      • 监听接口适配器
      • 鼠标事件
      • 按键事件
      • 使用Timer类的动画

学习说明
要点:
	事件源的概念介绍
	监听器的添加(注册)
	内部类的介绍
	匿名监听器的使用
	窗口事件的监听
	鼠标事件的监听
	使用Timer(定时器)类完成简单功能


学习资料为:《Java语言程序设计》梁勇
第十六章 事件驱动程序设计 事件和事件源的概念
事件的触发会由许多内容引起,下面列举一些常用的:
    点击按钮
    在文本域内按回车
    选定一个新项
    选定(多)项
    点击复选框
    点击单选按钮
    选定菜单栏
    移动滚动条
    窗口打开、关闭、最小化、还原
    按住、释放、点击鼠标
    移动、拖动鼠标(这好像有点抽象,拖动指按下键(左键或右键)再进行移动)
    按下键盘
    从容器中添加或删除组件
    组件移动、改变大小、隐藏、显示
    组件获得或失去焦点
监听器、注册以及处理事件
事件类(处理器)、监听器接口、监听器方法间的关系

ActionEvent     监听器接口都是对应的事件类将Event改为Listener
ItemEvent
MouseEvent
KeyEvent
WindowEvent
ContainerEvent
ComponentEvent
FocusEvent
AdjustmentEvent
ChangeEvent
ListSelectionEvent

对应的监听器方法较多,我就不一一列举了,都是采用英文命名,意思很容易猜出来

获得事件的源对象、发生时间,采用
    getSource
    getWhen(返回的是一个时间戳)
    getActionCommand(返回动作相关的命令字符串)


下面进行实例讲解
绘制了一个圆,按钮调整圆的大小
// 采用内部类进行书写,似乎也不是太复杂
public class ControlCircle extends JFrame {
	private JButton jbtnEnlarge = new JButton("Englarge");
	private JButton jbtnShrink = new JButton("Shrink");
	private CirclePanel circlePanel = new CirclePanel();
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new ControlCircle();

	    frame.setTitle("Test Control Circle");
	    frame.setSize(500, 400);
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.setVisible(true);
	}
	
	public ControlCircle() {
		// TODO Auto-generated constructor stub
		JPanel panel = new JPanel();
		
		panel.add(jbtnEnlarge);
		panel.add(jbtnShrink);
		
		this.add(circlePanel, BorderLayout.CENTER);
		this.add(panel, BorderLayout.SOUTH);
		
        // 绑定监听事件,感觉有些复杂,每个事件都创建一个类,这得多少类哦
		jbtnEnlarge.addActionListener(new EnlargeListener());
		jbtnShrink.addActionListener(new ShrinkListener());
	}
	
    // 添加监听器的实现类,必须要实现里面的那个方法
	class EnlargeListener implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			circlePanel.enlarge();
		}
	}
	
	class ShrinkListener implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			circlePanel.shrink();
		}
	}
	
	class CirclePanel extends JPanel{
		private int radius = 50;
		
        // 这里写了具体的操作方法
		public void enlarge() {
			radius += 20;
			repaint();
		}
		
		public void shrink() {
			if(radius > 20) {
				radius -= 20;
				repaint();
			}
		}
		
		protected void paintComponent(Graphics graphics) {
			super.paintComponent(graphics);
			graphics.drawOval(getWidth() / 2 - radius, getHeight() / 2 - radius, 2 * radius, 2 * radius);
		}
	}
}
内部类的使用
使程序看上去类少一些,便于维护
单个的内部类一般只与它的外部类进行交互,所以就写成了内部类
下面结合实例讲解:
// 在自己类内访问
public class Test {
	private InnerA innerA = new InnerA();   // 创建实例
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Test();
	}
	
	public Test() {
		// TODO Auto-generated constructor stub
		System.out.println(innerA.add());   // 构造函数内可以访问非静态成员
		System.out.println(innerA.sub());
	}
	
	class InnerA{
		int num1 = 2;
		int num2 = 3;
		
		public int add() {
			return num1 + num2;
		}
		
		public int sub() {
			return num1 - num2;
		}
	}
}
// 这个内部类会被编译成 Test$InnerA.class

// 别的外部类访问内部类
// 别的外部类又访问了,不推荐,这样就违背了内部类的本意了
public class TestInnerClass {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Test test = new Test();     // 需要先创建一个实例

        // 再通过 实例对象.new 类名 创建对象
		Test.InnerA innerA = test.new InnerA();
		
		System.out.println(innerA.add());
		System.out.println(innerA.sub());
	}
}

// 如果内部类是静态的,则会更简单一些
匿名类监听器
采用匿名的内部类,进一步简化书写
匿名内部类会被编译成 Test$n.class (如果外部类的类名是Test的话)

匿名类的特点:
    需要扩展父类或实现接口,但不能有显示的extends和implements子句
    必须实现父类或接口中所有的抽象方法
    总是使用父类的无参构造函数来创建实例(如果是接口的话,则采用Object的无参构造函数Object())
// 采用匿名内部类和 pack 函数进行打包,还蛮简单的
public class Test extends JFrame {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new Test();

	    frame.setTitle("Test mouseListenerDemo");
	    frame.setSize(500, 400);
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.pack();   // 这个是让窗体最小化的,样子还挺好看的
	    frame.setVisible(true);
	}
	
	public Test() {
		// TODO Auto-generated constructor stub
		JButton jbtnNew = new JButton("New");
		JButton jbtnOpen = new JButton("Open");
		JButton jbtnSave = new JButton("Save");
		JButton jbtnPrint = new JButton("Print");
		
		JPanel jpanel = new JPanel();
		jpanel.add(jbtnNew);
		jpanel.add(jbtnOpen);
		jpanel.add(jbtnSave);
		jpanel.add(jbtnPrint);
		
		this.add(jpanel);
		
        // 匿名内部类,其实也蛮简单的,这样书写虽然长了一些,但总体还挺好看的
		jbtnNew.addActionListener(
			new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					// TODO Auto-generated method stub
					System.out.println("Process New");
				}
			}
		);
		
		jbtnOpen.addActionListener(
				new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						// TODO Auto-generated method stub
						System.out.println("Process Open");
					}
				}
		);
		
		jbtnSave.addActionListener(
				new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						// TODO Auto-generated method stub
						System.out.println("Process Save");
					}
				}
		);
		
		jbtnPrint.addActionListener(
				new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						// TODO Auto-generated method stub
						System.out.println("Process Print");
					}
				}
		);
	}
}
定义监听器的另一种方式
采取按钮名称(这里以上面的例子为例接着讲解)进行分辨,实行操作,逻辑写在一个类里面
public class Test extends JFrame {
	JButton jbtnNew = new JButton("New");
	JButton jbtnOpen = new JButton("Open");
	JButton jbtnSave = new JButton("Save");
	JButton jbtnPrint = new JButton("Print");
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new Test();

	    frame.setTitle("Test mouseListenerDemo");
	    frame.setSize(500, 400);
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.pack();
	    frame.setVisible(true);
	}
	
	public Test() {
		// TODO Auto-generated constructor stub
		JPanel jpanel = new JPanel();
		jpanel.add(jbtnNew);
		jpanel.add(jbtnOpen);
		jpanel.add(jbtnSave);
		jpanel.add(jbtnPrint);
		
		this.add(jpanel);
		
		ButtonListener listener = new ButtonListener();
		
        // 不过注册监听器的步骤还是不能少的
		jbtnNew.addActionListener(listener);
		jbtnOpen.addActionListener(listener);
		jbtnSave.addActionListener(listener);
		jbtnPrint.addActionListener(listener);
	}
	
    // 这里统一书写,采用事件源进行分类,主要是它们的逻辑都差不多
	class ButtonListener implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			if(e.getSource() == jbtnNew)
				System.out.println("Process New");
			else if(e.getSource() == jbtnOpen)
				System.out.println("Process Open");
			else if(e.getSource() == jbtnSave)
				System.out.println("Process Save");
			else if(e.getSource() == jbtnPrint)
				System.out.println("Process Print");
		}
	}
}
当然,也可以选择继承JFrame类的同时再实现ActionListener接口
    这里实现接口就需要同时实现actionPerformed方法
// 整体的变化不大,主要就是修改了一下类以及注册监听器的对象
public class Test extends JFrame implements ActionListener {
	JButton jbtnNew = new JButton("New");
	JButton jbtnOpen = new JButton("Open");
	JButton jbtnSave = new JButton("Save");
	JButton jbtnPrint = new JButton("Print");
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new Test();

	    frame.setTitle("Test mouseListenerDemo");
	    frame.setSize(500, 400);
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.pack();
	    frame.setVisible(true);
	}
	
	public Test() {
		// TODO Auto-generated constructor stub
		JPanel jpanel = new JPanel();
		jpanel.add(jbtnNew);
		jpanel.add(jbtnOpen);
		jpanel.add(jbtnSave);
		jpanel.add(jbtnPrint);
		
		this.add(jpanel);
		
        // 这里将监听器对象换成 this,因为实现了接口
		jbtnNew.addActionListener(this);
		jbtnOpen.addActionListener(this);
		jbtnSave.addActionListener(this);
		jbtnPrint.addActionListener(this);
	}
	
    // 实现接口的同时,需要实现方法(感觉这种方法很不错呀,精简有力)
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		if(e.getSource() == jbtnNew)
			System.out.println("Process New");
		else if(e.getSource() == jbtnOpen)
			System.out.println("Process Open");
		else if(e.getSource() == jbtnSave)
			System.out.println("Process Save");
		else if(e.getSource() == jbtnPrint)
			System.out.println("Process Print");
	}
}
框架代码(精简版)
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class Test extends JFrame implements ActionListener {
	// 这里添加组件对象
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new Test();

	    frame.setTitle("Test mouseListenerDemo");   // 下面的部分基本是统一的
	    frame.setSize(500, 400);
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.pack();
	    frame.setVisible(true);
	}
	
	public Test() {
		// TODO Auto-generated constructor stub
		JPanel jpanel = new JPanel();
        // 这里将组件添加到面板
		this.add(jpanel);
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		// 这里书写事件逻辑
	}
}
计算贷款率的小程序
利用到了getText、setText方法,获取元素和设置元素的文本
// 面板(界面)主类
public class LoanCalculator extends JFrame {
	int length = 20;
	
	private JTextField jtfAnnualInterestRate = new JTextField(length);
	private JTextField jtfNumberOfYears = new JTextField(length);
	private JTextField jtfLoanAmount = new JTextField(length);
	private JTextField jtfMonthlyPayment = new JTextField(length);
	private JTextField jtfTotalPayment = new JTextField(length);
	
	private JButton jbtnComputeLoan = new JButton("Compute Payment");
	
	public LoanCalculator() {
		// TODO Auto-generated constructor stub
		JPanel jpanel = new JPanel(new GridLayout(5, 1, 0, 0));
		
		jpanel.add(new JLabel("Annual Interest Rate:"));
		jpanel.add(jtfAnnualInterestRate);
		
		jpanel.add(new JLabel("Number of Years:"));
		jpanel.add(jtfNumberOfYears);
		
		jpanel.add(new JLabel("Loan Amount:"));
		jpanel.add(jtfLoanAmount);
		
		jpanel.add(new JLabel("Monthly Payment:"));
		jpanel.add(jtfMonthlyPayment);
		
		jpanel.add(new JLabel("Total Payment:"));
		jpanel.add(jtfTotalPayment);
		
		jpanel.setBorder(new TitledBorder("Enter loan mount, interest rate, and year"));
		
		
		JPanel jPanel2 = new JPanel(new FlowLayout());
		jPanel2.add(jbtnComputeLoan);
		
		this.add(jpanel, BorderLayout.CENTER);
		this.add(jPanel2, BorderLayout.SOUTH);
		
		jbtnComputeLoan.addActionListener(new ButtonListener());
	}
	
    // 单独把监听类写出来了,放在里面写其实也没问题
	class ButtonListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
            // 采用 getText 获得文本内容
			double interest = Double.parseDouble(jtfAnnualInterestRate.getText());
			int year = Integer.parseInt(jtfNumberOfYears.getText());
			double loanMount = Double.parseDouble(jtfLoanAmount.getText());
			
			Loan loan = new Loan(interest, year, loanMount);
			
            // 采用 setText 更改文本内容
			jtfMonthlyPayment.setText(String.format("%.2f", loan.getMonthlyPayment()));
			jtfTotalPayment.setText(String.format("%.2f", loan.getTotalPayment()));
		}
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		LoanCalculator frame = new LoanCalculator();
		
		frame.pack();
	    frame.setTitle("Test LoanCaculator");
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.setVisible(true);
	}
}

// Loan 类(之前面向对象的时候编写过的)
public class Loan {
	private double annualInterestRate;
	private int numberOfYears;
	private double loanAmount;
	private Date loanDate;

	public Loan() {
		// TODO Auto-generated constructor stub
		this(2.5, 1, 1000);	// 只是用到了构造函数,很一般的类
	}

	public Loan(double annualInterestRate, int numberOfYears, double loanAmount) {
		// TODO Auto-generated constructor stub
		this.annualInterestRate = annualInterestRate;
		this.numberOfYears = numberOfYears;
		this.loanAmount = loanAmount;
		this.loanDate = new Date();
	}

	public double getAnnualInterestRate() {
		return annualInterestRate;
	}

	public int getNumberOfYears() {
		return numberOfYears;
	}

	public double getLoanAmount() {
		return loanAmount;
	}

	public Date getLoanDate() {
		return loanDate;
	}

	public void setNumberOfYears(int numberOfYears) {
		this.numberOfYears = numberOfYears;
	}

	public void setLoanAmount(double loanAmount) {
		this.loanAmount = loanAmount;
	}

	public double getMonthlyPayment() {
		return loanAmount * annualInterestRate / 1200;
	}

	public double getTotalPayment() {
		return getMonthlyPayment() * numberOfYears * 12;
	}
}
窗口事件
事件触发:
    打开、关闭、激活窗口
    变成非活动窗口(意思就是离开了窗口的感觉,需要再次点击才可以返回窗口,然后按键啥的才有效)
    最小化、还原窗口

下面以实例讲解了窗口的各个活动的含义
public class TestWindowEvent extends JFrame {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new TestWindowEvent();
		
		frame.setSize(300, 200);
	    frame.setTitle("Test WindowEvent");
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.setVisible(true);
	}
	
	public TestWindowEvent() {
		// TODO Auto-generated constructor stub
		addWindowListener(new WindowListener() {
			
			@Override
			public void windowOpened(WindowEvent e) {
				// TODO Auto-generated method stub
				System.out.println("Window opened");
			}
			
			@Override
			public void windowIconified(WindowEvent e) {
				// TODO Auto-generated method stub
				System.out.println("Window iconified");
			}
			
			@Override
			public void windowDeiconified(WindowEvent e) {
				// TODO Auto-generated method stub
				System.out.println("Window deiconified");
			}
			
			@Override
			public void windowDeactivated(WindowEvent e) {
				// TODO Auto-generated method stub
				System.out.println("Window deactivated");
			}
			
			@Override
			public void windowClosing(WindowEvent e) {
				// TODO Auto-generated method stub
				System.out.println("Window closing");
			}
			
			@Override
			public void windowClosed(WindowEvent e) {
				// TODO Auto-generated method stub
				System.out.println("Window closed");
			}
			
			@Override
			public void windowActivated(WindowEvent e) {
				// TODO Auto-generated method stub
				System.out.println("Window activated");
			}
		});
	}
}
监听接口适配器
下面以创建匿名监听器为例,使用适配器对只感兴趣的事件进行监听    
public class TestAdapter extends JFrame {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new TestAdapter();
		
		frame.setSize(300, 200);
	    frame.setTitle("Test WindowEvent");
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.setVisible(true);
	}
	
    // 这里采用 WindowAdapter 进行 windowActivated 事件的监听,相当于重写了监听事件,此时 WindowAdapter 不是接口和抽象类,不要求实现那么多抽象方法
	public TestAdapter() {
		// TODO Auto-generated constructor stub
		addWindowListener(new WindowAdapter() {
			public void windowActivated(WindowEvent event) {
				System.out.println("Window activated");
			}
		});
	}
}
鼠标事件
MouseEvent类,继承自InputEvent类,下面为简单常用属性方法:
    InputEvent:
        getWhen
        isAltDown
        isControlDown
        isMetaDown
        isShiftDown
    MouseEvent:
        getButton
        getClickCount
        getPoint
        getX
        getY

它们对应的监听器类:MouseListener、MouseMotionListener
    MouseListener:(点击、按下)
        mousePressed
        mouseReleased
        mouseClicked
        mouseEntered
        mouseExited
    MouseMotionListener:(移动)
        mouseDragged
        mouseMoved

下面结合实例讲解(面板拖动消息为例)
// 绑定了鼠标拖动监听器,每次拖动后即重新绘制画面
public class MoveMessageDemo extends JFrame {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new MoveMessageDemo();
		
		frame.setSize(800, 400);
	    frame.setTitle("Test WindowEvent");
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.setVisible(true);
	}
	
	public MoveMessageDemo() {
		// TODO Auto-generated constructor stub
		MovableMessagePanel panel1 = new MovableMessagePanel("Hello BBYH 2022-05-22");
		panel1.setFont(new Font("Times New Roman", Font.BOLD, 30));
		
		setLayout(new BorderLayout());
		this.add(panel1);
	}
	
	class MovableMessagePanel extends JPanel{
		private String message = "Hello BBYH 2022";
		private int x = 60;
		private int y = 60;
		
		public MovableMessagePanel(String str) {
			// TODO Auto-generated constructor stub
			message = str;
            // 这里绑定的监听器不能写错了
			addMouseMotionListener(new MouseAdapter() {
				public void mouseDragged(MouseEvent event) {
					x = event.getX();
					y = event.getY();
					repaint();
				}
			});
		}
		
		protected void paintComponent(Graphics graphics) {
			super.paintComponent(graphics);
			graphics.drawString(message, x, y);
		}
	}
}
按键事件
KeyEvent类,同样继承自InputEvent类
    KeyEvent:
        getKeyChar
        getKeyCode

对应的监听器:KeyListener
    keyPressed
    keyReleased
    keyTyped

按键常量:
    VK_HOME:Home键(不同电脑位置不太一样,一般都在右上角)
    每个按键常量都是前面是 VK_ 后面加大写的按键名称

下面结合实例进行讲解
public class KeyEventDemo extends JFrame {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new KeyEventDemo();
		
		frame.setSize(800, 400);
	    frame.setTitle("Test WindowEvent");
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.setVisible(true);
	}
	
	public KeyEventDemo() {
		// TODO Auto-generated constructor stub
		KeyboardPanel panel = new KeyboardPanel();
		
		this.add(panel);
        // 让面板获得焦点,不然无法监听到键盘事件
		panel.setFocusable(true);
	}
	
	class KeyboardPanel extends JPanel {
		private int x = 100;
		private int y = 100;
		private char keyChar = 'A';
		
		public KeyboardPanel() {
			// TODO Auto-generated constructor stub
            // 监听键盘事件
			addKeyListener(new KeyAdapter() {
				public void keyPressed(KeyEvent event) {
					switch (event.getKeyCode()) {
					case KeyEvent.VK_DOWN:
						if(y <= getHeight() - 10)   // 防止滑到外面了
							y += 10;
						break;
					case KeyEvent.VK_UP:
						if(y > 10)
							y -= 10;
						break;
					case KeyEvent.VK_LEFT:
						if(x > 10)
							x -= 10;
						break;
					case KeyEvent.VK_RIGHT:
						if(x < getWidth() - 10)
							x += 10;
						break;
					default:
						keyChar = event.getKeyChar();
						break;
					}
					repaint();
				}
			});
		}
		
		protected void paintComponent(Graphics graphics) {
			super.paintComponent(graphics);
			
			graphics.setFont(new Font("Times New Roman", Font.BOLD, 24));
			graphics.drawString(String.valueOf(keyChar), x, y);
		}
	}
}
使用Timer类的动画
类似定时器的功能,按照预定频率触发 ActionEvent 事件

Timer类常用属性及方法:
    构造函数
    AddActionListener
    start
    stop
    setDelay
public class AnimationDemo extends JFrame {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new AnimationDemo();
		
		frame.setSize(400, 300);
	    frame.setTitle("Test WindowEvent");
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.setVisible(true);
	}
	
	public AnimationDemo() {
		// TODO Auto-generated constructor stub
		this.add(new MovingMessagePanel("BBYH"));
	}
	
	class MovingMessagePanel extends JPanel {
		private String message = "Hello BBYH 2022";
		private int xCoordinate = 300;
		private int yCoordinate = 100;
		
		public MovingMessagePanel(String message) {
			// TODO Auto-generated constructor stub
			this.message = message;
			
            // 这里创建定时器
			Timer timer = new Timer(500, new TimerListener());
			timer.start();
		}
		
		protected void paintComponent(Graphics graphics) {
			super.paintComponent(graphics);
			
			if(xCoordinate > getWidth() - 30)
				xCoordinate = -50;
			xCoordinate += 30;
            // 这里设定字体要在前面,不然先绘制再设定就没效果了
			graphics.setFont(new Font("Times New Roman", Font.BOLD, 30));
			graphics.drawString(message, xCoordinate, yCoordinate);
		}
	}
	
    // 这个定时器监听器功能也是很简单的,仅仅是重新绘制
	class TimerListener implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			repaint();
		}
	}
}
所以这里就可以修改之前的时钟,将线程停止变成采用定时器来书写
基本的时钟类(静止的那种)还是和之前一样
// 这里没有采用 MessagePanel 类,所以就只有一个圆盘了,修改起来还是很简单的
public class ClockAnimation extends JFrame {
	private StillClock clock = new StillClock();
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new ClockAnimation();
		
		frame.setSize(400, 300);
	    frame.setTitle("Test WindowEvent");
	    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setLocationRelativeTo(null);
	    frame.setVisible(true);
	}
	
	public ClockAnimation() {
		// TODO Auto-generated constructor stub
		add(clock);
		
		Timer timer = new Timer(1000, new TimerListener());
		timer.start();
	}
	
	class TimerListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			clock.setCurrentTime();
			repaint();
		}
	}
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/924414.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号