Java Swing-使用线程
我制作了一个简单的点击测试应用程序(你可能在网上看到过一些,你有一个大按钮。一旦你点击它,10秒计时器就会启动,目标是点击按钮的次数最多)。我认为这是一个练习Java Swing-使用线程,java,multithreading,swing,Java,Multithreading,Swing,我制作了一个简单的点击测试应用程序(你可能在网上看到过一些,你有一个大按钮。一旦你点击它,10秒计时器就会启动,目标是点击按钮的次数最多)。我认为这是一个练习SwingAPI和基本线程的好方法。这只是一些基本的东西,我知道我可以使用API作为计时器之类的东西,但现在让我们保持简单 问题似乎是我无法在setTime()方法中修改JLabel,该方法是从计时器类中的线程调用的 这是主类类: package com.tremblayalex.clicktest; import java.awt.Bo
Swing
API
和基本线程
的好方法。这只是一些基本的东西,我知道我可以使用API
作为计时器之类的东西,但现在让我们保持简单
问题似乎是我无法在setTime()
方法中修改JLabel
,该方法是从计时器类中的线程调用的
这是主类
类
:
package com.tremblayalex.clicktest;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main extends JFrame
{
private static final long serialVersionUID = 1L;
// Initialize Variables
private final JPanel contentPane = new JPanel();
private JLabel topText = new JLabel();
private JButton btnClick = new JButton();
private int clicks = 0;
private boolean isStarted = false;
public static void main(String[] args)
{
Main m = new Main();
m.setVisible(true);
}
public Main()
{
if (!isStarted)
{
initComponents();
registerEvents();
}
}
///////////////////////////////////////////////////////////////////////////////
// Initialize Components
///////////////////////////////////////////////////////////////////////////////
private void initComponents()
{
// JFrame Settings
setTitle("Input Box");
setSize(1000, 400);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
add(contentPane);
// Content Pane (BorderLayout)
contentPane.setLayout(new BorderLayout());
contentPane.add(topText, BorderLayout.NORTH);
contentPane.add(btnClick, BorderLayout.CENTER);
// Top Text
topText.setFont(new Font("Arial", Font.PLAIN, 16));
topText.setText("Click to Start");
// Button Click
btnClick.setFont(new Font("Arial", Font.BOLD, 18));
btnClick.setText("CLICK TO START");
}
///////////////////////////////////////////////////////////////////////////////
// Register Events
///////////////////////////////////////////////////////////////////////////////
private void registerEvents()
{
btnClick.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if (isStarted == false)
{
isStarted = true;
new Thread(new Timer()).start();
}
clicks++;
btnClick.setText("[Clicks] " + clicks);
}
});
}
///////////////////////////////////////////////////////////////////////////////
// Getters and Setters
///////////////////////////////////////////////////////////////////////////////
public void setTime(double time)
{
System.out.println(time);
topText.setText("Time: " + time);
if (time >= 10)
{
if (clicks < 50)
{
topText.setText("Your average CPS is " + (clicks / 10) + "." + " Try to do better next time!");
} else if (clicks >= 50 || clicks < 100){
topText.setText("Your average CPS is " + (clicks / 10) + "." + " You are in the average!");
} else if (clicks >= 100 || clicks < 150){
topText.setText("Your average CPS is " + (clicks / 10) + "." + " You click very fast!");
} else if (clicks >= 150 || clicks < 250){
topText.setText("Your average CPS is " + (clicks / 10) + "." + " Clicking is your destiny!");
} else if (clicks >= 250){
topText.setText("Your average CPS is " + (clicks / 10) + "." + " Hack? :D");
} else {
topText.setText("Your average CPS is " + (clicks / 10) + "." + " Internal Error.");
}
isStarted = false;
btnClick.setText("CLICK TO RESTART");
}
}
}
package com.tremblayalex.clicktest;
public class Timer implements Runnable
{
private final Main main = new Main();
public void run()
{
for (double time = 0; time <= 10; time += 0.1)
{
main.setTime(time);
try {
Thread.sleep(100);
} catch (InterruptedException e)
{}
}
}
}
编辑:
感谢您的帮助,我使用定时器制作了一个新版本:
package com.tremblayalex.clicktest;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main extends JFrame
{
private static final long serialVersionUID = 1L;
// Initialize Variables
private final JPanel contentPane = new JPanel();
private JLabel topText = new JLabel();
private JButton btnClick = new JButton();
private JButton btnRestart = new JButton();
private double clicks = 0;
private double time;
private boolean isStarted = false;
private Timer timer = new Timer(100, new ActionListener()
{
@Override
public void actionPerformed(ActionEvent paramActionEvent)
{
if (time < 100)
{
time++;
topText.setText("Time: " + (time / 10));
}
else {
if (clicks < 50)
{
topText.setText("Your average CPS is " + (clicks / 10) + " Try to do better next time!");
} else if (clicks >= 50 && clicks < 100){
topText.setText("Your average CPS is " + (clicks / 10) + " You are in the average!");
} else if (clicks >= 100 && clicks < 150){
topText.setText("Your average CPS is " + (clicks / 10) + " You click very fast!");
} else if (clicks >= 150 && clicks < 250){
topText.setText("Your average CPS is " + (clicks / 10) + " Clicking is your destiny!");
} else if (clicks >= 250){
topText.setText("Your average CPS is " + (clicks / 10) + " Hack? :D");
} else {
topText.setText("Your average CPS is " + (clicks / 10) + " Internal Error.");
}
timer.stop();
isStarted = false;
btnClick.setEnabled(false);
btnRestart.setEnabled(true);
}
}
});
public static void main(String[] args)
{
Main m = new Main();
m.setVisible(true);
}
public Main()
{
initComponents();
registerEvents();
}
///////////////////////////////////////////////////////////////////////////////
// Initialize Components
///////////////////////////////////////////////////////////////////////////////
private void initComponents()
{
// JFrame Settings
setTitle("Click Test");
setSize(1000, 400);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
add(contentPane);
// Content Pane (BorderLayout)
contentPane.setLayout(new BorderLayout());
contentPane.add(topText, BorderLayout.NORTH);
contentPane.add(btnClick, BorderLayout.CENTER);
contentPane.add(btnRestart, BorderLayout.SOUTH);
// Top Text
topText.setFont(new Font("Arial", Font.PLAIN, 16));
topText.setText("Click to Start");
// Button Click
btnClick.setFont(new Font("Arial", Font.BOLD, 18));
btnClick.setText("CLICK TO START");
// Button Restart
btnRestart.setFont(new Font("Arial", Font.PLAIN, 15));
btnRestart.setText("Restart");
btnRestart.setEnabled(false);
}
///////////////////////////////////////////////////////////////////////////////
// Register Events
///////////////////////////////////////////////////////////////////////////////
private void registerEvents()
{
btnClick.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if (isStarted == false)
{
isStarted = true;
clicks = 0;
time = 0;
topText.setText("Time: " + time);
timer.start();
}
clicks++;
btnClick.setText("[Clicks] " + (int)clicks);
}
});
btnRestart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
btnClick.setEnabled(true);
btnClick.setText("CLICK TO RESTART");
btnRestart.setEnabled(false);
}
});
}
}
package com.tremblayalex.clicktest;
导入java.awt.BorderLayout;
导入java.awt.Font;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
导入javax.swing.Timer;
公共类主框架
{
私有静态最终长serialVersionUID=1L;
//初始化变量
private final JPanel contentPane=new JPanel();
private JLabel topText=new JLabel();
private JButton btnClick=new JButton();
private JButton btnRestart=new JButton();
私人双击=0;
私人双倍时间;
私有布尔值isStarted=false;
私有计时器=新计时器(100,新ActionListener()
{
@凌驾
已执行的公共无效操作(ActionEvent paramActionEvent)
{
如果(时间<100)
{
时间++;
setText(“时间:”+(Time/10));
}
否则{
如果(单击次数<50次)
{
setText(“您的平均CPS是”+(点击/10)+“下次尝试做得更好!”);
}否则如果(单击次数>=50次和单击次数<100次(&C){
setText(“你的平均点击次数是”+(点击次数/10)+“你处于平均水平!”);
}否则,如果(单击次数>=100&&clicks<150){
setText(“你的平均点击次数是”+(点击/10)+“你点击得很快!”);
}否则,如果(单击次数>=150和单击次数<250){
setText(“你的平均点击次数是”+(点击/10)+“点击就是你的命运!”);
}否则如果(单击次数>=250){
setText(“您的平均CPS为“+(点击/10)+”黑客?:D”);
}否则{
setText(“您的平均CPS为“+(点击/10)+“内部错误”);
}
timer.stop();
isStarted=false;
b单击.setEnabled(false);
btnRestart.setEnabled(true);
}
}
});
公共静态void main(字符串[]args)
{
Main m=新的Main();
m、 setVisible(真);
}
公用干管()
{
初始化组件();
registerEvents();
}
///////////////////////////////////////////////////////////////////////////////
//初始化组件
///////////////////////////////////////////////////////////////////////////////
私有组件()
{
//JFrame设置
设置标题(“点击测试”);
设置大小(1000400);
可设置大小(假);
setDefaultCloseOperation(关闭时退出);
setLocationRelativeTo(空);
添加(内容窗格);
//内容窗格(边框布局)
setLayout(新的BorderLayout());
添加(topText,BorderLayout.NORTH);
添加(b单击,BorderLayout.CENTER);
添加(btnRestart,BorderLayout.SOUTH);
//顶部文本
setFont(新字体(“Arial”,Font.PLAIN,16));
setText(“单击开始”);
//按钮点击
btnClick.setFont(新字体(“Arial”,Font.BOLD,18));
btnClick.setText(“单击开始”);
//按钮重启
setFont(新字体(“Arial”,Font.PLAIN,15));
btnRestart.setText(“重启”);
btnRestart.setEnabled(false);
}
///////////////////////////////////////////////////////////////////////////////
//注册事件
///////////////////////////////////////////////////////////////////////////////
私有无效注册表事件()
{
btnClick.addActionListener(新建ActionListener()
{
已执行的公共无效操作(操作事件e)
{
如果(isStarted==false)
{
IsStart=true;
点击次数=0;
时间=0;
setText(“时间:+Time”);
timer.start();
}
点击++;
btnClick.setText(“[单击]”+(int)单击);
}
});
btnRestart.addActionListener(新的ActionListener()
{
已执行的公共无效操作(操作事件e)
{
btnClick.setEnabled(true);
btnClick.setText(“单击以重新启动”);
btnRestart.setEnabled(false);
}
});
}
}
此处不需要直接使用线程,只需使用一个线程即可。它更干净、更安全。基本上,尤其是作为新手,永远不要调用Thread.sleep()或Thread.yield()。尤其是在使用和时千万不要睡觉。@markspace:不,这里绝对不是java.util.Timer
,因为这是一个Swing应用程序。实用程序计时器几乎肯定会导致间歇性线程异常。如果结果不需要在EDT上运行,java.util.Timer将正常工作。如果他打算做其他事情,比如测试一个文件,那没关系。