简体   繁体   English

Java Swing计时器不清晰

[英]Java Swing Timer Not Clear

I have been having some problems with using the Timer function of Java swing. 使用Java swing的Timer函数时遇到了一些问题。 I am fairly new to programming with Java, so any help is greatly appreciated. 我对使用Java编程还很陌生,因此非常感谢您的帮助。 I have looked over many other Timer questions on this site but none of them have answered my question. 我在该网站上查看了许多其他计时器问题,但没有一个回答我的问题。 I have made a GUI that allows you to play rock paper scissors, where you can choose from clicking three buttons. 我制作了一个GUI,可用来播放剪刀石头布,您可以在其中单击三个按钮进行选择。 I want my program to sleep for around 1 second after you click the button, and again after it displays a message. 我希望我的程序在单击按钮后休眠1秒钟左右,然后在它显示一条消息后再次休眠。 After I realized Thread.sleep() wouldn't work for my GUI, I tried to implement a timer. 当我意识到Thread.sleep()对我的GUI无效时,我尝试实现一个计时器。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*; 
import javax.swing.border.Border;
import java.io.*;

public class rps { 
//ROCK PAPER SCISSORS
static JLabel middle = new JLabel();
static JLabel them = new JLabel();
static JLabel yourWins = new JLabel();
static JLabel theirWins = new JLabel();
static JPanel yourPanel = new JPanel();
static JPanel middlePanel = new JPanel();
static JLabel blank1 = new JLabel();
static JLabel blank2 = new JLabel();
static JButton rock = new JButton("Rock");
static JButton paper = new JButton("Paper");
static JButton scissors = new JButton("Scissors");
static int yw = 0;
static int tw = 0;
static ButtonHandler listener = new ButtonHandler();

public static void main(String[] args) { 

    //Create the frame
    JFrame frame = new JFrame("Rock Paper Scissors");
    frame.setSize(500, 500); //Setting the size of the frame

    middle.setFont(new Font("Serif", Font.PLAIN, 30)); 
    middle.setHorizontalAlignment(SwingConstants.CENTER);
    them.setFont(new Font("Serif", Font.PLAIN, 15));
    them.setHorizontalAlignment(SwingConstants.CENTER);
    yourWins.setHorizontalAlignment(SwingConstants.CENTER);
    theirWins.setHorizontalAlignment(SwingConstants.CENTER);

    //Creating panels
    JPanel bigPanel = new JPanel();

    Border border = BorderFactory.createLineBorder(Color.BLACK, 1); 
    Border wlb = BorderFactory.createLineBorder(Color.RED, 1); 
    them.setBorder(border);
    yourPanel.setBorder(border);
    bigPanel.setBorder(border);
    yourWins.setBorder(wlb);
    theirWins.setBorder(wlb);
    middlePanel.setBorder(border);

    //Creating grid layouts 
    GridLayout yourGrid = new GridLayout(1,3,10,10); 
    GridLayout theirGrid = new GridLayout(1,1); //One row, one column
    GridLayout middleGrid = new GridLayout(5,1);
    GridLayout bigGrid = new GridLayout(3,1);//Two rows, one column

    //Setting the layouts of each panel to the grid layouts created above
    yourPanel.setLayout(yourGrid); //Adding layout to buttons panel
    them.setLayout(theirGrid); //Adding layout to label panel
    middlePanel.setLayout(middleGrid); 
    bigPanel.setLayout(bigGrid);

    //Adding r/p/s to your grid.
    yourPanel.add(rock);
    yourPanel.add(paper);
    yourPanel.add(scissors);

    //Adding w/l rations to middlegrid.
    middlePanel.add(theirWins);
    middlePanel.add(blank1);
    middlePanel.add(middle);
    middlePanel.add(blank2);
    middlePanel.add(yourWins);

    //Attaching the listener to all the buttons
    rock.addActionListener(listener);
    paper.addActionListener(listener);
    scissors.addActionListener(listener);

    bigPanel.add(them);
    bigPanel.add(middlePanel);
    bigPanel.add(yourPanel); 

    //Shows the score at 0-0.
    yourWins.setText("Your wins: " + yw);
    theirWins.setText("Their wins: " + tw);

    frame.getContentPane().add(bigPanel); //panel to frame 
    frame.setVisible(true); // Shows frame on screen
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

//Class represents what do when a button is pressed
private static class ButtonHandler implements ActionListener { 
    public void actionPerformed (ActionEvent e) {
        Timer timer = new Timer(1000, this);

        String tc = random();
        them.setText("They chose: " + tc + "!");
        if (e.getSource() == rock) {
            whoWins("rock", tc);
        } else if (e.getSource() == paper) {
            whoWins("paper", tc);
        } else if (e.getSource() == scissors) {
            whoWins("scissors", tc);
        }
        yourWins.setText("Your wins: " + yw);
        theirWins.setText("Their wins: " + tw);

        timer.setRepeats(false);
        timer.start();
    }
} 

public static String random() {
    int random = (int) (Math.random() * 3);
    if (random == 0) {
        return "Rock";
    } else if (random == 1) {
        return "Paper";
    } else if (random == 2) {
        return "Scissors";
    }
    return "";
}

public static void whoWins(String yc, String tc) {
    if (yc.equals("rock")) {
        if (tc.equals("Rock")) {
            middle.setText("It's a tie!");            
        } else if (tc.equals("Paper")) {
            middle.setText("You lose!");
            tw++;
        } else if (tc.equals("Scissors")) {
            middle.setText("You win!");
            yw++;
        }
    } else if (yc.equals("paper")) {
        if (tc.equals("Rock")) {
            middle.setText("You win!");
            yw++;
        } else if (tc.equals("Paper")) {
            middle.setText("It's a tie!");
        } else if (tc.equals("Scissors")) {
            middle.setText("You lose!");
            tw++;
        }
    } else if (yc.equals("scissors")) {
        if (tc.equals("Rock")) {
            middle.setText("You lose!");
            tw++;
        } else if (tc.equals("Paper")) {
            middle.setText("You win!");
            yw++;
        } else if (tc.equals("Scissors")) {
            middle.setText("It's a tie!");
        }
    }
}
}

What is actually happening is there is no delay from when I press the button to a message displaying, because clearly I am not using the timer correctly. 实际发生的事情是从按下按钮到显示消息没有延迟,因为显然我没有正确使用计时器。 I would like the timer to just run once, and after it runs the code will execute. 我希望计时器仅运行一次,然后运行该代码即可执行。 However, when I click a button the timer will run on repeat although setRepeats is false. 但是,当我单击按钮时,尽管setRepeats为false,计时器仍将重复运行。 Therefore, the message I want to display, instead of being delayed, is displayed instantaneously but then goes on a loop and keeps displaying a message (the message is random) until I shut off the program. 因此,我要显示的消息会立即显示,而不是被延迟,但会立即显示,但随后会循环并继续显示消息(消息是随机的),直到我关闭程序为止。 If I click the button again, it will double the tempo of the timer it seems, and the messages display twice as fast and so on and so forth. 如果再次单击该按钮,它将使计时器的速度翻倍,并且消息显示的速度快两倍,依此类推。

them.setText("They chose: " + tc + "!");

This is the message that is displayed on repeat, with the variable tc changing every time. 这是重复显示的消息,变量tc每次都会更改。 The timer seems to just be displaying this message every timer interval (1s). 计时器似乎只是在每个计时器间隔(1s)中显示此消息。

Any help would be greatly appreciated. 任何帮助将不胜感激。

EDIT: 编辑:

So I added this section : 所以我添加了本节:

private static class ButtonHandler implements ActionListener { 
    public void actionPerformed (ActionEvent e) {
        // I'd be disabling the buttons here to prevent
        // the user from trying to trigger another 
        // update...

        // This is an instance field which is used by your
        // listener

        Timer timer = new Timer(1000, listenert);
        timer.setRepeats(false);
        timer.start();
    }
}
private static class timer implements ActionListener {
    public void actionPerformed (ActionEvent e) {
        String tc = random(); //A method that chooses a random word.
        them.setText("They chose: " + tc + "!"); 
        if (e.getSource() == rock) {
            whoWins("rock", tc); //whoWins is a method that will display a message.
        } else if (e.getSource() == paper) {
            whoWins("paper", tc);
        } else if (e.getSource() == scissors) {
            whoWins("scissors", tc);
        }
        yourWins.setText("Your wins: " + yw);
        theirWins.setText("Their wins: " + tw);

        // Start another Timer here that waits 1 second
        // and re-enables the other buttons...
    }
}

so what I believe happens now is when I click a button, the buttonhandler listener starts the timer which is attached to the timer listener (named listenert) which will run the code in the actionPerformed of the timer class. 因此,我现在所相信的是,当我单击按钮时,buttonhandler侦听器将启动计时器,该计时器将连接到计时器侦听器(名为listenert),该计时器将在计时器类的actionPerformed中运行代码。 however the sleep function still is not working 但是睡眠功能仍然不起作用

EDIT 2.5: 编辑2.5:

 private static class ButtonHandler implements ActionListener { 
    public void actionPerformed (ActionEvent e) {
        final JButton button = (JButton)e.getSource();
        Timer timer = new Timer(1000, new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        String tc = random();
                        them.setText("They chose: " + tc + "!");
                        if (button == rock) {
                            whoWins("rock", tc);
                        } else if (button == paper) {
                            whoWins("paper", tc);
                        } else if (button == scissors) {
                            whoWins("scissors", tc);
                        }
                        yourWins.setText("Your wins: " + yw);
                        theirWins.setText("Their wins: " + tw);
                    }
                });
        timer.setRepeats(false);
        timer.start();     

    }
} 

that is what I have so far, I just need to add antoher sleep after them.setText("They chose: " + tc + "!"); 到目前为止,我只需要在它们之后添加另一个睡眠即可。setText(“他们选择了:” + tc +“!”); where would I put a timer.restart() if any? 如果有的话,我该在哪里放置timer.restart()? the timer.start() is at the end of the method which I don't quite understand. timer.start()位于我不太了解的方法的末尾。

So, the ActionListener you supply to the Timer is notified when the timer "ticks", so you ButtonHandler actionPerformed should look more like... 因此,当计时器“滴答”时,将通知您提供给TimerActionListener ,因此ButtonHandler actionPerformed应该看起来更像...

public void actionPerformed (ActionEvent e) {
    // I'd be disabling the buttons here to prevent
    // the user from trying to trigger another 
    // update...

    // This is an instance field which is used by your
    // listener
    choice = e.getSource();

    Timer timer = new Timer(1000, listener);
    timer.setRepeats(false);
    timer.start();
}

And your listener should look more like 您的listener应该看起来更像

public void actionPerformed (ActionEvent e) {
    String tc = random(); //A method that chooses a random word.
    them.setText("They chose: " + tc + "!"); 
    if (choice == rock) {
        whoWins("rock", tc); //whoWins is a method that will display a message.
    } else if (choice == paper) {
        whoWins("paper", tc);
    } else if (choice == scissors) {
        whoWins("scissors", tc);
    }
    yourWins.setText("Your wins: " + yw);
    theirWins.setText("Their wins: " + tw);

    // Start another Timer here that waits 1 second
    // and re-enables the other buttons...
}

For example... 例如...

You may consider taking a look at How to use Swing Timers for more details 您可以考虑查看如何使用Swing计时器以了解更多详细信息

Updated 更新

Start with a simple example... public class TestPane extends JPanel { 从一个简单的示例开始...公共类TestPane扩展了JPanel {

    private JLabel label;
    private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

    public TestPane() {
        setLayout(new GridBagLayout());
        label = new JLabel();
        add(label);
        tick();

        Timer timer = new Timer(500, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                tick();
            }
        });
        timer.start();
    }

    protected void tick() {

        label.setText(sdf.format(new Date()));

    }
}

This just calls the tick method every half second to update the time on the JLabel ... 这只是每半秒调用一次tick方法以更新JLabel上的时间...

firstly import the following ; 首先导入以下内容;

import java.awt.event.ActionEvent ;

import java.awt.event.ActionListener ;

import javax.swing.Timer ; 

then initialize the timer at the end of the form like this ; 然后像这样在表单的末尾初始化计时器; public static void main(String args[]) { 公共静态void main(String args []){

 java.awt.EventQueue.invokeLater(new Runnable() {        
            public void run() {       
            new mainprogramme().setVisible(true);    
        }    

}); });

}    
    private Timer timer ;

then after initializing the timer add a public class like following; 然后在初始化计时器之后,添加一个公共类,如下所示;

public class progress implements ActionListener { public void actionPerformed(ActionEvent evt){ 公共类的进度实现了ActionListener {public void actionPerformed(ActionEvent evt){

int n = 0 ;
if (n<100){
    n++ ;
    System.out.println(n) ;
}else{
    timer.stop() ;
}
}
}

after you do this go to the j Frame>right click and select>Events>window>window Opened and type the following ; 完成此操作后,转到j框架>右键单击并选择>事件>窗口>打开的窗口,然后键入以下内容;

private void formWindowOpened(java.awt.event.WindowEvent evt) {                                  
        timer = new Timer(100,new progress()) ;

and after you do all this take a button name it as anything and type the following in its void like following ; 在完成所有这些操作之后,将按钮命名为任何名称,然后在其空白处输入following,如下所示;

 timer.start();

AND THAT'S IT CODE IT AND THEN REPLY ME... 这就是代码,然后回复我...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM