java 如何让计时器和进度条一起倒计时?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5931933/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make Timer countdown along with progress bar?
提问by wannabeprogrammer
How can I make it so that the progress bar slowly goes down with the time limit?
我怎样才能让进度条随着时间限制慢慢下降?
class GamePanel extends JPanel implements MouseListener, ActionListener
{
private JButton quit;
private JButton q;
private Font loadFont;
public GamePanel()
{
setBackground(Color.blue); // sets background color
this.setLayout(null);
quit = new JButton("Quit");
quit.addActionListener(this);
quit.setBounds(550, 700, 100, 30);
this.add(quit);
q = new JButton("Questions");
q.addActionListener(this);
q.setBounds(100, 100, 120, 30);
this.add(q);
loadFont = new Font("Serif", Font.PLAIN, 30);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.black);
g.fillRect(80, 100, 610, 560);
g.setColor(Color.white);
g.fillRect(90, 110, 110, 100);// 1st column
g.fillRect(90, 220, 110, 100);//
g.fillRect(90, 330, 110, 100);//
g.fillRect(90, 440, 110, 100);//
g.fillRect(90, 550, 110, 100);//
g.fillRect(210, 110, 110, 100);// 2nd column
g.fillRect(210, 220, 110, 100);//
g.fillRect(210, 330, 110, 100);//
g.fillRect(210, 440, 110, 100);//
g.fillRect(210, 550, 110, 100);//
g.fillRect(330, 110, 110, 100);// 3rd column
g.fillRect(330, 220, 110, 100);//
g.fillRect(330, 330, 110, 100);//
g.fillRect(330, 440, 110, 100);//
g.fillRect(330, 550, 110, 100);//
g.fillRect(450, 110, 110, 100);// 4th column
g.fillRect(450, 220, 110, 100);//
g.fillRect(450, 330, 110, 100);//
g.fillRect(450, 440, 110, 100);//
g.fillRect(450, 550, 110, 100);//
g.fillRect(570, 110, 110, 100);// 5th column
g.fillRect(570, 220, 110, 100);//
g.fillRect(570, 330, 110, 100);//
g.fillRect(570, 440, 110, 100);//
g.fillRect(570, 550, 110, 100);//
g.setColor(Color.green);
g.setFont(loadFont);
g.drawString(input + ":", 100, 710);
}
public void actionPerformed(ActionEvent e)
{
String order = e.getActionCommand();
if(order.equals("Quit"))
cards.show(c, "Introduction");
if(order.equals("Questions"))
cards.show(c, "Questions");
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
class QuestionPanel extends JPanel implements ActionListener
{
private long startTime, elapsedTime;
private Timer timer;
private int countdown;
private Font loadFont;
public QuestionPanel()
{
setBackground(Color.pink); // sets background color
this.setLayout(null); // moved into constructor from ActionPerformed: only change layout in constructor
startTime = 0;
elapsedTime = 0;
countdown = 590;
loadFont = new Font("Segoe Script", Font.BOLD, 20);
if(timer == null)
{// use the biggest value possible that provides your desired time keeping precision (usually no less than 15 on Windows)
timer = new Timer(100, this);
startTime = System.currentTimeMillis(); // gets start time in milliseconds
timer.start();
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillRect(100, 100, 600, 25);
g.setColor(Color.green);
g.fillRect(105, 105, countdown, 15);
g.setColor(Color.black);
g.setFont(loadFont);
g.drawString("" + ((System.currentTimeMillis() - startTime) / 1000.0), 100, 80); // display remaining time
}
public void actionPerformed(ActionEvent e)
{
String command = e.getActionCommand();
elapsedTime = System.currentTimeMillis() - startTime;
if(elapsedTime < (5000))
{
countdown--;
repaint();
}
else
{
timer.stop();
if(timer == null)
{
timer = new Timer(500, this);
timer.start();
}
}
if(elapsedTime >= (5000)) // can't use == here because of limited precision of system clock
cards.show(c, "Correct!");
}
}
class AnswerPanel extends JPanel implements ActionListener
{
private JButton revert;
public AnswerPanel()
{
setBackground(Color.yellow); // sets background color
this.setLayout(null);
revert = new JButton("Back");
revert.addActionListener(this);
revert.setBounds(340, 700, 100, 30);
this.add(revert);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
public void actionPerformed(ActionEvent e)
{
String directive = e.getActionCommand();
if(directive.equals("Back"))
cards.show(c, "Start");
}
}
class FailPanel extends JPanel implements ActionListener
{
private JButton turnaround;
public FailPanel()
{
setBackground(Color.green); // sets background color
this.setLayout(null);
turnaround = new JButton("Back");
turnaround.addActionListener(this);
turnaround.setBounds(340, 700, 100, 30);
this.add(turnaround);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
public void actionPerformed(ActionEvent e)
{
String bidding = e.getActionCommand();
if(bidding.equals("Back"))
cards.show(c, "Start");
}
}
}// end of the entire program
回答by Andrew Thompson
Sorry, I still could not find the motivation to actually read your code, but just threw together this example based on the question. See if it gives you some ideas.
抱歉,我仍然找不到真正阅读您的代码的动机,但只是根据问题将这个示例放在一起。看看它是否给你一些想法。
Note that it is an SSCCE and uses just 40 lines of code in all.
请注意,它是一个 SSCCE,总共只使用了 40 行代码。
import java.awt.event.*;
import javax.swing.*;
class CountDownProgressBar {
Timer timer;
JProgressBar progressBar;
CountDownProgressBar() {
progressBar = new JProgressBar(JProgressBar.VERTICAL, 0, 10);
progressBar.setValue(10);
ActionListener listener = new ActionListener() {
int counter = 10;
public void actionPerformed(ActionEvent ae) {
counter--;
progressBar.setValue(counter);
if (counter<1) {
JOptionPane.showMessageDialog(null, "Kaboom!");
timer.stop();
}
}
};
timer = new Timer(1000, listener);
timer.start();
JOptionPane.showMessageDialog(null, progressBar);
}
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
CountDownProgressBar cdpb = new CountDownProgressBar();
}
});
}
}
回答by pickypg
From the looks of it, all of this code is within a big Java file? That is a bad idea.
从它的外观来看,所有这些代码都在一个大的 Java 文件中?那是个坏主意。
You should have a good reason to define a class as an inner class, and from the looks of it, you do not have one for QuestionPanel and others.
您应该有充分的理由将类定义为内部类,从它的外观来看,您没有用于 QuestionPanel 和其他类的类。
As for the problem, your paintComponent
method is called every time your counter is updated, which is right now roughly once every 0.1 seconds, yet you only tick by 1 pixel on each update, so by the end of 5 seconds, you've cut off 10*5 pixels (50). What you should do is update the progress bar by a different mechanism, such as a calculating the current time processed:
至于问题,paintComponent
每次更新计数器时都会调用您的方法,现在大约每 0.1 秒一次,但每次更新时您只勾选 1 个像素,因此到 5 秒结束时,您已经切断了10*5 像素 (50)。您应该做的是通过不同的机制更新进度条,例如计算当前处理的时间:
long processed = System.currentTimeMillis() - startTime;
double percent = Math.max(0, 1 - processed / 5000.0);
int width = (int)(590 * percent);
回答by Ryan
That is definitely too much information, and a very broad question. I'd say at most you only need to include the code for the class where the timer is, and the class where the progress bar gets drawn.
这绝对是太多信息,而且是一个非常广泛的问题。我想说最多你只需要包含计时器所在类的代码,以及绘制进度条的类。
From skimming the code, I'm guessing you're using a rectangle to draw the progress bar. Based on that, one way you could go about it would be using a variable to store the width of the bar, and every time the timer ticks, decrease the width of the bar by a set amount. Then just set the width of the rectangle drawn to the value stored in the variable.
通过浏览代码,我猜你正在使用一个矩形来绘制进度条。基于此,您可以采用的一种方法是使用变量来存储条的宽度,并且每次计时器滴答作响时,将条的宽度减小一定量。然后只需将绘制的矩形的宽度设置为存储在变量中的值。