3

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
mKorbel
  • 109,525
  • 20
  • 134
  • 319
wannabeprogrammer
  • 125
  • 1
  • 3
  • 9
  • I would like people to take a look at the QuestionPanel. I'm trying to make the timer countdown while the progress bar is also going down. When the timer hits 0 (after starting at 5), another panel is suppose to be shown. Another problem is that the timer starts before I even get to that panel; I want to be able to control when the timer starts. – wannabeprogrammer May 09 '11 at 02:34
  • 2
    Holy wall of text, Batman! I would try condensing the issue down to as small of an example as you can make it. – corsiKa May 09 '11 at 02:38
  • i tried to condense it but if i condense it...it will be harder for people to understand exactly what im talking about XD – wannabeprogrammer May 09 '11 at 02:43
  • 2
    I strongly second TFRM's suggestion. That's just way too much code. You will have to put in some effort to make it both smaller and understandable, but it's effort well spent. Otherwise many will have better things to do with their Sunday evenings than read a 3 volume book of code. – Hovercraft Full Of Eels May 09 '11 at 02:48
  • 2
    @thynoob: I have 5 letters for you [SSCCE](http://pscode.org/sscce.html). Prepare an SSCCE and it is likely the problem (as well as the solution) will become clear as you do it. If that does not happen, at least you will have a short piece of code that other people are likely to look at more closely. As it is, you are asking us to trawl through almost 450 lines of code looking for the error. Your request will most likely be ignored. @HFOE thanks for formatting the code. – Andrew Thompson May 09 '11 at 03:06
  • 1
    Your program would benefit by your doing this as well since it could help you in your goal to separate out program logic from the GUI code. Also, you'll want to get rid of all that absolute positioning and sizing and instead use layout managers, especially if you want folks with different sized monitors and screen resolutions to be able to see your gui. I can't see it fully on mine for instance. – Hovercraft Full Of Eels May 09 '11 at 03:07
  • i have shortened the code...hope that helps :D – wannabeprogrammer May 09 '11 at 03:16

3 Answers3

12

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.

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();
            }
        });
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 2
    @thynoob: Andrews code is more than just short, it also is compilable, runnable, and testable. Since it is brief, we can understand it quickly. Since it compiles and runs we can all run this code unmodified, alter it, improve it and fix any errors in it in a short period of time. – Hovercraft Full Of Eels May 09 '11 at 03:41
4

From the looks of it, all of this code is within a big Java file? That is a bad idea.

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.

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:

long processed = System.currentTimeMillis() - startTime;
double percent = Math.max(0, 1 - processed / 5000.0);
int width = (int)(590 * percent);
pickypg
  • 22,034
  • 5
  • 72
  • 84
  • 1
    Why not simply use a JProgressBar? – Hovercraft Full Of Eels May 09 '11 at 03:31
  • I imagine this is for an assignment, but otherwise I agree with you. – pickypg May 09 '11 at 03:32
  • i appreciate your input pickypg but is there a way to make the remaing time displayed to start at 5 seconds? – wannabeprogrammer May 09 '11 at 03:49
  • Yes, change the last line that draws the time left string. `double remaining = 5 * percent; g.drawString(String.format("%.2f", remaining), 100, 80);` – pickypg May 09 '11 at 03:58
  • so i replace the last line that u just gave to the last line of the code u first gave me? and then after that i put this into my code using my variables and everything shouold be ok? o__o – wannabeprogrammer May 09 '11 at 04:06
  • @Hovercraft Full Of Eels...pickypg is correct this is an assignment but would one of you please show me how a JProgressBar works? – wannabeprogrammer May 09 '11 at 04:13
  • @thynoob You will have to do some leg work for yourself. But, for JProgressBar help, use the [tutorial](http://download.oracle.com/javase/tutorial/uiswing/components/progress.html). – pickypg May 09 '11 at 04:15
2

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.

Ryan
  • 712
  • 7
  • 21