Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 delay problem using list...
Index -> Programming, Java -> Java Help
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
tianxiao




PostPosted: Mon May 17, 2010 10:39 am   Post subject: delay problem using list...

My teacher can't even figure this out. We're making a dice game. and we have a listbox where the number of rolls will show up as a list until the computer guesses the right number.
Eg. if the number is 1, and the computer is generating a random number and it generates a 1 on the fourth roll
it should show
Roll 1: 2
Roll 2: 4
Roll 3: 5
Roll 4: 1
How can we have an even delay between each line displayed? I tried thread.sleep but that only delays it at the beginning...
Sponsor
Sponsor
Sponsor
sponsor
TheGuardian001




PostPosted: Mon May 17, 2010 10:47 am   Post subject: Re: delay problem using list...

Have you tried multiple Thread.sleeps / is your Thread.sleep included in the dicerolling loop?

I dunno, this is kind of a difficult problem to solve without seeing how your program actually works...
tianxiao




PostPosted: Mon May 17, 2010 10:54 am   Post subject: Re: delay problem using list...

private static class ButtonHandler implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
//Which button was pressed?
if (e.getSource () == btnDice)
{
diceRoll = (int) (Math.random () * 6 + 1);
rollnum.setText ("" + diceRoll);
btnDice.setEnabled (false);
rollnum.setEnabled (false);
}
else if (e.getSource () == btnB)
{
comprollnum.setEnabled (false);
do
{
compdiceRoll = (int) (Math.random () * 6 + 1);


counter++;
try {
Thread.sleep(300);
}
catch (InterruptedException f) {
}
listModel.addElement ("Roll " + counter + ": " + compdiceRoll);


}
while (compdiceRoll != diceRoll);

so the thread.sleep didn't work.... it only delays in the beginning...
comprollnum is a txtbox beside the block of black words

listModel is the list
btnDice is the button with dice image
diceroll and compdiceroll is just a variable
btnB is the computer Roll button



dicegame1.bmp
 Description:
 Filesize:  293.61 KB
 Viewed:  57 Time(s)

dicegame1.bmp


DemonWasp




PostPosted: Mon May 17, 2010 11:05 am   Post subject: RE:delay problem using list...

Are you sure that the Thread.sleep isn't occuring? Remember that 300ms is just under a third of a second - a time short enough to look relatively instant to human eyes. Try upping it to 5000 (5 seconds) and see if you notice a difference.

If there's no difference, then put the following inside your catch{} block:
code:

f.printStackTrace();
tianxiao




PostPosted: Mon May 17, 2010 11:14 am   Post subject: RE:delay problem using list...

no I do notice the delay. It's just that It occurs in the beginning and then the rest of the roll just displays all at once....
DemonWasp




PostPosted: Mon May 17, 2010 12:01 pm   Post subject: RE:delay problem using list...

Ah, of course. You're inserting new lines into the List, but it's not repainting them. Call repaint() on the list after every insert-new-element.

You can find the Java 1.6 API documentation on that method here.
tianxiao




PostPosted: Tue May 18, 2010 10:02 am   Post subject: RE:delay problem using list...

How do you repaint a list??... I just started java... I can't figure this out... I've searched through help files already
DemonWasp




PostPosted: Tue May 18, 2010 10:09 am   Post subject: RE:delay problem using list...

Look closely at the link on the second line of my previous post. There is a repaint() method in the List object. Add this line after you've added the new element to force the List to redraw itself to show the new element:

code:
listModel.repaint();


The reason that this is necessary is because the List will "buffer" new items by default so that it can add them faster, without needing to perform a very costly (slow) redraw operation for each one. They will only become visible when the List is forced to redraw itself onto the screen, which is why you don't see the updates until substantially later.

By forcing it to redraw after each entry, you get the updated view you're expecting.
Sponsor
Sponsor
Sponsor
sponsor
tianxiao




PostPosted: Tue May 18, 2010 10:12 am   Post subject: RE:delay problem using list...

it tells me no method named "repaint" was found in type "javax.swing.DefaultListModel"......
DemonWasp




PostPosted: Tue May 18, 2010 10:42 am   Post subject: RE:delay problem using list...

Sorry, my mistake, I thought you were using AWT, not Swing. As it turns out, the change is relatively minor.

The following isn't in your listed code, so I could be mistaken, but:

- You're getting listModel, a javax.swing.DefaultListModel, from the actual JList somewhere.
- JList has a repaint() method.

So call repaint() on the JList instead.
tianxiao




PostPosted: Tue May 18, 2010 10:59 am   Post subject: RE:delay problem using list...

my bad. srry
static DefaultListModel listModel = new DefaultListModel ();
static JList listItems = new JList (listModel);
I had this at the beginning.
I tried listItems.repaint () but it didn't work...

else if (e.getSource () == btnB)
{
comprollnum.setEnabled (false);
btnB.setEnabled (false);
do
{
compdiceRoll = (int) (Math.random () * 6 + 1);


counter++;

try
{
Thread.sleep (200);
}
catch (InterruptedException ie)
{
}

listModel.addElement ("Roll " + counter + ": " + compdiceRoll);


listItems.repaint ();

}



while (compdiceRoll != diceRoll);

this is my new code. but it's still only delaying at the beginning
tianxiao




PostPosted: Tue May 18, 2010 11:05 am   Post subject: Re: delay problem using list...

This is my full program.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.*;

public class DiceGame2
{
static JLabel lblOne = new JLabel ("Click on the dice to roll.");
static JLabel lblTwo = new JLabel ("<HTML> Enter how many times <BR> you think the computer will <BR> take to reach your number.");
static JLabel lblThree = new JLabel ("Final Results:");
static JLabel lblFour = new JLabel (" ");
static JButton btnDice = new JButton (new ImageIcon ("dice.jpg"));
static JButton btnB = new JButton ("Computer Rolls");
static JRadioButton radC = new JRadioButton ("Play Again");
static JRadioButton radD = new JRadioButton ("Quit the Game");
static JTextField rollnum = new JTextField ("");
static JTextField comprollnum = new JTextField ("");
static DefaultListModel listModel = new DefaultListModel ();
static JList listItems = new JList (listModel);
static ButtonGroup group = new ButtonGroup ();
static int diceRoll = 0;
static int compdiceRoll = 0;
static int counter = 0;
static int blah = 0;
private static void guiApp ()
{
ButtonHandler onClick = new ButtonHandler ();
//Create the window "frame"
JFrame frame = new JFrame ("DiceGame");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane ();

contentPane.setLayout (new BoxLayout (contentPane, BoxLayout.PAGE_AXIS));
rollnum.setPreferredSize (new Dimension (20, 20));
comprollnum.setPreferredSize (new Dimension (20, 20));
btnDice.setPreferredSize (new Dimension (126, 99));
btnDice.addActionListener (onClick);
btnB.setBackground (Color.MAGENTA);
btnB.addActionListener (onClick);
radC.setBackground (Color.CYAN);
radC.addActionListener (onClick);
radD.setBackground (Color.CYAN);
radD.addActionListener (onClick);
lblFour.setForeground (Color.RED);
rollnum.setBackground (Color.YELLOW);
btnB.setEnabled (false);
rollnum.setEnabled (false);
comprollnum.setEnabled (false);
radC.setEnabled (false);
comprollnum.addActionListener (onClick);

JPanel panel = new JPanel ();
panel.setLayout (new FlowLayout ());

Font lblOneFont = new Font ("Ariel", Font.BOLD, 12);
lblOne.setFont (lblOneFont);


listItems.setVisibleRowCount (4);
listItems.setFixedCellWidth (140);
listItems.setSelectionMode (ListSelectionModel.SINGLE_SELECTION);
JScrollPane itemScroll = new JScrollPane (listItems);

group.add (radC);
group.add (radD);


JPanel topPanel = new JPanel ();
JPanel middlePanel = new JPanel ();
JPanel bottomPanel = new JPanel ();

bottomPanel.setLayout (new BoxLayout (bottomPanel, BoxLayout.PAGE_AXIS));

middlePanel.add (lblOne);
middlePanel.add (btnDice);
middlePanel.add (rollnum);
middlePanel.add (lblTwo);
middlePanel.add (comprollnum);
middlePanel.add (btnB);
middlePanel.add (itemScroll);
middlePanel.add (lblThree);
middlePanel.add (lblFour);

middlePanel.add (radC);
middlePanel.add (radD);
middlePanel.setBackground (Color.CYAN);

contentPane.add (middlePanel);

frame.setBounds (300, 200, 200, 500);
frame.setVisible (true);
}


private static class ButtonHandler implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
//Which button was pressed?
if (e.getSource () == btnDice)
{
diceRoll = (int) (Math.random () * 6 + 1);
rollnum.setText ("" + diceRoll);
btnDice.setEnabled (false);
rollnum.setEnabled (false);
comprollnum.setEnabled (true);
btnB.setEnabled (true);
}
else if (e.getSource () == btnB)
{
comprollnum.setEnabled (false);
btnB.setEnabled (false);
do
{
compdiceRoll = (int) (Math.random () * 6 + 1);


counter++;

listModel.addElement ("Roll " + counter + ": " + compdiceRoll);

try
{
Thread.sleep (200);
}
catch (InterruptedException ie)
{
}
listItems.repaint ();

}



while (compdiceRoll != diceRoll);

String newstring = comprollnum.getText ();
String intStr = String.valueOf (counter);
if (counter == 1)

if ((newstring.equals (intStr)))
lblFour.setText ("<HTML> You win! The compter took <BR>" + counter + " roll to reach your roll of " + diceRoll + ".");
else
lblFour.setText ("<HTML> You lost! The compter took <BR>" + counter + " roll to reach your roll of " + diceRoll + ".");

else if (counter > 1)

if ((newstring.equals (intStr)))
lblFour.setText ("<HTML> You win! The compter took <BR>" + counter + " rolls to reach your roll of " + diceRoll + ".");
else
lblFour.setText ("<HTML> You lost! The compter took <BR>" + counter + " rolls to reach your roll of " + diceRoll + ".");
radC.setEnabled (true);

}
else if (e.getSource () == radC)
{
radC.setEnabled (false);
btnB.setEnabled (false);

comprollnum.setEnabled (false);
radC.setEnabled (false);
btnDice.setEnabled (true);

listModel.clear ();
rollnum.setText ("");
comprollnum.setText ("");
counter = 0;
}

else if (e.getSource () == radD)
{
int answer = JOptionPane.showConfirmDialog (null, "Goodbye.", "Exiting", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE);
if (answer == JOptionPane.YES_OPTION)
System.exit (0);
}







}
}


public static void main (String[] args)
{
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater (new Runnable ()
{
public void run ()
{
guiApp ();
}
}


);
}
}
DemonWasp




PostPosted: Tue May 18, 2010 11:38 am   Post subject: RE:delay problem using list...

Having now had a good look at your code, I've actually solved the problem (instead of guessing, as I was before). The problem seems to be that you are doing the updating in the user-interface thread - the one that runs all the updates.

If you want entries to appear periodically, you will either need to have a Timer that periodically rolls the computer's dice, or else separate the button-rolling into another Thread. I did the latter, and I can confirm that it works.

ButtonHandler changes to the following:
Java:

        private static class ButtonHandler implements ActionListener
        {
                public void actionPerformed (ActionEvent e)
                {
                        Actor a = new Actor ( e );
                        new Thread(a).start();
                }
        }


And we also need a new class (hinted at above) called Actor:
Java:

        static class Actor implements Runnable {
               
                protected ActionEvent e;
               
                public Actor ( ActionEvent e ) {
                        this.e = e;
                }
               
                @Override
                public void run() {//Which button was pressed?
                        if (e.getSource () == btnDice)
                        {
                                diceRoll = (int) (Math.random () * 6 + 1);
                                rollnum.setText ("" + diceRoll);
                                btnDice.setEnabled (false);
                                rollnum.setEnabled (false);
                                comprollnum.setEnabled (true);
                                btnB.setEnabled (true);
                        }
                        else if (e.getSource () == btnB)
                        {
                                comprollnum.setEnabled (false);
                                btnB.setEnabled (false);
                                do {
                                        compdiceRoll = (int) (Math.random () * 6 + 1);

                                        counter++;

                                        listModel.addElement ("Roll " + counter + ": " + compdiceRoll);
                                       
                                        try {
                                                Thread.sleep (200);
                                        } catch (InterruptedException ignored) { }

                                } while (compdiceRoll != diceRoll);

                                String newstring = comprollnum.getText ();
                                String intStr = String.valueOf (counter);
                               
                                if (counter == 1) {
                                        if ((newstring.equals (intStr)))
                                                lblFour.setText ("<HTML> You win! The compter took <BR>" + counter + " roll to reach your roll of " + diceRoll + ".");
                                        else
                                                lblFour.setText ("<HTML> You lost! The compter took <BR>" + counter + " roll to reach your roll of " + diceRoll + ".");
                                } else if (counter > 1) {
                                        if ((newstring.equals (intStr)))
                                                lblFour.setText ("<HTML> You win! The compter took <BR>" + counter + " rolls to reach your roll of " + diceRoll + ".");
                                        else
                                                lblFour.setText ("<HTML> You lost! The compter took <BR>" + counter + " rolls to reach your roll of " + diceRoll + ".");
                                }
                               
                                radC.setEnabled (true);
                                       
                        } else if (e.getSource () == radC) {
                                radC.setEnabled (false);
                                btnB.setEnabled (false);
                               
                                comprollnum.setEnabled (false);
                                radC.setEnabled (false);
                                btnDice.setEnabled (true);
                               
                                listModel.clear ();
                                rollnum.setText ("");
                                comprollnum.setText ("");
                                counter = 0;
                        } else if (e.getSource () == radD) {
                                int answer = JOptionPane.showConfirmDialog (null, "Goodbye.", "Exiting", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE);
                                if (answer == JOptionPane.YES_OPTION)
                                        System.exit (0);
                        }
                }
        }


Why it's so involved to perform what seems like a relatively simple operation, I will never know.
tianxiao




PostPosted: Tue May 18, 2010 2:46 pm   Post subject: RE:delay problem using list...

Thank you sooo much Smile I've learned quite a lot from this
DemonWasp




PostPosted: Tue May 18, 2010 3:01 pm   Post subject: RE:delay problem using list...

That was a relatively complicated problem for someone to encounter at the highschool level. I attribute that to Swing's poor design (not saying I would do better, just that it's not good).

The most important thing to remember here is that there is a fantastic Java API reference (which I've linked a few times) that will tell you all about any class that ships with Java by default. The only caveat is that if you're trying to work with Ready to Program, you're limited to Java 1.4.2, which is ancient; modern Java (1.6+) is much nicer.

Edit: You're welcome for the help. That's why I'm here Wink .
Display posts from previous:   
   Index -> Programming, Java -> Java Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 15 Posts ]
Jump to:   


Style:  
Search: