跨类使用方法?

时间:2016-02-23 00:45:45

标签: java swing timer jbutton

我有两个类,一个是在特定时间打印命令的计时器,另一个是包含所述计时器的启动按钮的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

}
}

3 个答案:

答案 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

因此,我们创建了ControlsPaneActionListener的实例。我们注册ControlsPaneTimeKeeper,根据start生成的事件调用stop的{​​{1}}或ControlsPane方法,然后我们将两个面板添加到屏幕上......

这是一个非常宽松的例子Model-View-ControllerObserver Pattern

您可以查看How to Use Buttons, Check Boxes, and Radio ButtonsHow 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进行操作。