我有两个类,一个是在特定时间打印命令的计时器,另一个是包含所述计时器的启动按钮的GUI。 我正在尝试在GUI中获取启动/停止按钮,以便能够使用timer.start();和timer.stop(); TimeKeeper类中使用的方法。
我在这个网站上搜索并阅读了很多Oracle文档,但我仍然不清楚这在我的情况下是如何工作的。
这是完整的计时器类:
package tests;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class TimeKeeper extends JFrame
{
private Timer timer;
private int delay = 1000; // every 1 second
private static final long serialVersionUID = 1L;
private int counter = 0;
private int[] times = {};
private String[] commands = {};
public TimeKeeper()
{
ActionListener action = new ActionListener()
{
@Override
public void actionPerformed(ActionEvent event)
{
System.out.println(counter);
counter = counter+1;
if (counter == times[0]) {
new SayText();
SayText.say(commands[0]);
}
if (counter == times[1]){
SayText.say(commands[1]);
}
else
{
timer.stop();
}
}
};
timer = new Timer(delay, action);
timer.setInitialDelay(0);
timer.start(); //MOVE THIS TO START BUTTON IN OTHER CLASS
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new TimeKeeper();
}
});
}
}
这是GUI类的简短版本
//package name
//imports
public class TwoPlayer {
//variable initializations
public TwoPlayer(){
//mainFrame specs
//Jlabel
//Some JFields
JButton button1 = new JButton("Start/Stop");
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
//Another button
//Another button
//Another button
//JPanel creation
//add components to mainframe
}
}
答案 0 :(得分:2)
我会说你的设计缺乏一点点哦,好吧,设计。
让我们退后一步,TwoPlayer
类有权修改TimeKeeper
类吗?实际上,没有,这不是它的责任。目前,它想要做的就是让计时器启动和停止。它并不关心如何
同样,所有TimeKeeper
班级关心的是管理Timer
。
这是为什么你不应该从JFrame
延伸的好例子,它将你锁定在一个单一的用例中,这使得它几乎无法扩展或扩展功能。
那么,答案是什么?那么,让我们退一步,看看你如何重新设计这个......
TimeKeeper
负责管理Timer
,为此,我们需要为其他类提供启动和停止此Timer
的能力(可能还需要其他功能,但我坚持基础)。此外,它应该从更灵活的东西扩展,可能JPanel
,这将使您在需要时更容易重复使用和扩展。
public class TimeKeeper extends JPanel {
private Timer timer;
private int delay = 1000; // every 1 second
private int counter = 0;
private int[] times = {};
private String[] commands = {};
public TimeKeeper() {
ActionListener action = new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
System.out.println(counter);
counter = counter + 1;
if (counter == times[0]) {
//new SayText();
//SayText.say(commands[0]);
}
if (counter == times[1]) {
//SayText.say(commands[1]);
} else {
timer.stop();
}
}
};
timer = new Timer(delay, action);
timer.setInitialDelay(0);
}
public void start() {
timer.start();
}
public void stop() {
timer.stop();
}
}
现在,我们需要让玩家与TimeKeeper
进行交互,为此,我们需要一个开始/停止按钮。您可以使用JToggleButton
或以其他方式管理单个按钮的状态,但为简单起见,我使用了两个...
public static class ControlsPane extends JPanel {
public static final String START_COMMAND = "Start";
public static final String STOP_COMMAND = "Stop";
private JButton start;
private JButton stop;
public ControlsPane() {
start = new JButton(START_COMMAND);
stop = new JButton(STOP_COMMAND);
setLayout(new GridBagLayout());
add(start);
add(stop);
}
public void addActionListener(ActionListener listener) {
start.addActionListener(listener);
stop.addActionListener(listener);
}
public void removeActionListener(ActionListener listener) {
start.removeActionListener(listener);
stop.removeActionListener(listener);
}
}
现在,所有这个类都提供了两个按钮(在面板上)以及添加/删除ActionListener
的功能,当单击其中一个或另一个按钮时,该TimeKeeper
会被通知。
请注意,此类没有与TimeKeeper timeKeeper = new TimeKeeper();
ControlsPane controlsPane = new ControlsPane();
controlsPane.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ControlsPane.START_COMMAND:
timeKeeper.start();
break;
case ControlsPane.STOP_COMMAND:
timeKeeper.stop();
break;
}
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(timeKeeper);
frame.add(controlsPane, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
进行交互的实际方法,当按下一个或另一个按钮时,生成通知的全部责任是,实际做某事的责任在于与其他人一起< / p>
让我们把它放在一起......
TimeKeeper
因此,我们创建了ControlsPane
和ActionListener
的实例。我们注册ControlsPane
到TimeKeeper
,根据start
生成的事件调用stop
的{{1}}或ControlsPane
方法,然后我们将两个面板添加到屏幕上......
这是一个非常宽松的例子Model-View-Controller和 Observer Pattern
您可以查看How to Use Buttons, Check Boxes, and Radio Buttons和How to Write an Action Listeners了解详情
答案 1 :(得分:1)
为了保持禁用状态,我有一个接口,至少有一个停止和启动方法,在Timekeeper类上实现接口,实现独立的方法来执行timer.start()/ timer.start ()然后将Timekeeper实例作为接口传递给GUI。相当直接,真的,但是GUI类可以采取任何你想要实现启动/停止功能。
答案 2 :(得分:1)
使用方法的基本方法是使用类似
的语句创建类的实例Timekeeper timekeeper = new Timekeeper();
在某些课程中(如TwoPlayer
)。然后,在该变量的范围内,您可以调用方法&#34; on&#34;您创建的实例,如
// ...
timekeeper.start();
// ... other code in here
timekeeper.stop();
此外,由于我发现您在计时器类中实现了ActionListener,因此可以将Timekeeper实例传递给按钮的setActionListener()
方法。
JButton button = new JButton("start timer");
button.setActionListener(timekeeper);
然后单击该按钮将调用该Timekeeper实例上的actionPerformed()
方法。
请注意,计时器类因为它实现了ActionListener,因此部分是GUI类。这只是意味着你只能在一个有意义的地方使用那个类,让它通过Swing Action进行操作。