我有两个类,一个是在特定时间打印命令的计时器,另一个是包含所述计时器的启动按钮的 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
}
}
最佳答案
我想说你的设计缺乏一点,哦,好吧,设计。
让我们退后一步,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);
因此,我们创建了 TimeKeeper
和 ControlsPane
的实例。我们向 ControlsPane
注册一个 ActionListener
,它调用 TimeKeeper
的 start
或 stop
方法基于 ControlsPane
生成的事件,然后我们将两个面板添加到屏幕上...
这是一个非常宽松的示例 Model-View-Controller和 Observer Pattern
您可能想看看How to Use Buttons, Check Boxes, and Radio Buttons和 How to Write an Action Listeners了解更多详情
关于java - 跨类使用方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35566748/