Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / GUI / January 2008

Tip: Looking for answers? Try searching our database.

Choppy refresh problem with JLabels and JMenuItem accelerators

Thread view: 
Daniel Gee - 12 Jan 2008 23:10 GMT
I've got a tile based game (a roguelike) which uses a grid of JLabels
each displaying an ImageIcon to display what's happening within the
game. I want to use keyboard input, so I setup JMenuItem instances
each with an accelerator for a different key. When a key is pressed,
the key is responded to with the accelerators and the hero goes one
square left, right, or whatever using an action listener to get an
appropriate command to the game model. Then the screen is redrawn.
Very simple.

My problem is this: if a key is held down, the refreshing becomes very
choppy and although every event is responded to, the program doesn't
refresh the display fast enough and ends up skipping. What I'd like is
either a suggestion of a way to make the graphics faster or a way to
set a "delay" on the menu accelerator or the event processing so that
events aren't generated faster than a specific speed.
Andrew Thompson - 12 Jan 2008 23:44 GMT
...
> ...What I'd like is
> either a suggestion ..

Post shorter line to usenet?  Or..

>..of a way to make the graphics faster ...

..oh, in that case, post code we can play with.
(but please note the line width).

--
Andrew T.
PhySci.org
Daniel Gee - 13 Jan 2008 00:55 GMT
Sorry about the lines, Google Groups shows them wrapped around when it
posts
but I guess it doesn't actually send it out to others like that.

ok, so there are a few classes involved:
the main class: http://paste.uni.cc/18079
the JRogueFrame: http://paste.uni.cc/18080
the MapPanel: http://paste.uni.cc/18081

The LogFrame just captures the System.out stream. The HeroStatusPanel
just has
some player stats along the bottom of the JRogueFrame.

MapInfo just returns a string of what image file should be at that
location,
and the IconManager stores all the game's images in a HashMap, and
loads new
ones lazily as they're required.
Andrew Thompson - 13 Jan 2008 01:43 GMT
> Sorry about the lines, Google Groups shows them wrapped around when it
> posts
> but I guess it doesn't actually send it out to others like that.

Sure it does, then the *client* newsreader
wraps the lines wherever it feels like.
That is the point.  Since you cannot control
where the *reader's* news client wraps the text,
it is better to claim control of it yourself
by breaking lines relatively short.

(As an aside, by 'short' I mean around 62-70
chars, as opposed to the larger widths at which
you seem to be hitting 'newline'.)

Here is a tool I developed to help check line
width.  You might find it useful.
<http://www.physci.org/codes/sscce.html#twc>

> ok, so there are a few classes involved:
> the main class:http://paste.uni.cc/18079
> the JRogueFrame:http://paste.uni.cc/18080
> the MapPanel:http://paste.uni.cc/18081

There are acutally a few more, like..
'JRogueGlobals'.  But please do not 'put up'
that class - I prefer a *single* source file
that has everything included 'out of the box'.
Specifically an SSCCE.

* <http://www.physci.org/codes/sscce.html>

> The LogFrame just captures the System.out stream.

Wa'..Huh?  Is this output stream necessary for
displaying the problem?  If not, remove it.  If
so, try to programmatically emulate it (rather
than force the user to supply data).

--
Andrew T.
PhySci.org
Daniel Gee - 13 Jan 2008 03:54 GMT
Alright, here's a SSCCE that seems to still capture the problem:
http://paste.uni.cc/18083

As you should be able to see, if you tap a key extremely rapidly
then it'll take one step at a time over and over just fine. But
if you hold a key down running from one edge to another then it'll
become laggy and only show every few 'frames' of movement.

So it seems I need either a different (faster) way to display and
get input, or a way to slow down how often a held key generates
Action Events. There might be a third option I'm not seeing.

Because of the nature of the game, I can't just update the
player's label only, since there will be many other creatures,
as well as "fog of war" being updated over a variable area
every turn. The exact area would depend on the shape of the level.

(On the same aside, I was using line width slightly less than
80 in the second post, which I figured was short enough for
everyone. Oh well.)
Andrew Thompson - 13 Jan 2008 07:55 GMT
> Alright, here's a SSCCE that seems to still capture the problem: > http://paste.uni.cc/18083

Hmmm.  That code was frustratingly close
to code that displays the problem (after
re-enabling the menu!).

Still - I was intrigued enough to continue
with it, and came up with this variant*.
I chose to:
- dump the JLabels for a direct 'paint()'
- lose the try/catch
- change the ActionListener for a KeyListener
- a number of other minor things I cannot recall.

* See how this works for you..
<sscce>
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class JRSCE
 extends JFrame
 implements KeyListener
{
 static final int COLS = 80;
 static final int ROWS = 22;
 String[][] grid = new String[COLS][ROWS];

 int columnX = 3;
 int columnY = 3;

 /**
  * @param args none.
  */
 public static void main(String[] args)
 {
   SwingUtilities.invokeLater(new Runnable() {
     public void run()
     {
       JRSCE thisClass = new JRSCE();
       thisClass.setDefaultCloseOperation(
         JFrame.EXIT_ON_CLOSE);
       thisClass.setVisible(true);
     }
   });
 }

 /**
  * build.
  */
 public JRSCE()
 {
   super("Use NUMPAD");

   GridPanel gp = new GridPanel();
   gp.addKeyListener(this);
   this.setContentPane(gp);
   pack();
   for (int y = 0 ; y < ROWS ; y++)
   {
     for (int x = 0 ; x < COLS ; x++)
     {
       grid[x][y] = ".";
     }
   }
   refresh();
 }

 public void keyReleased(KeyEvent ke) {}
 public void keyTyped(KeyEvent ke) {}
 public void keyPressed(KeyEvent ke) {
   switch ( ke.getKeyCode() )
   {
     case KeyEvent.VK_NUMPAD1:
       columnX--;
       columnY++;
       break;
     case KeyEvent.VK_NUMPAD2:
       columnY++;
       break;
     case KeyEvent.VK_NUMPAD3:
       columnX++;
       columnY++;
       break;
     case KeyEvent.VK_NUMPAD4:
       columnX--;
       break;
     case KeyEvent.VK_NUMPAD6:
       columnX++;
       break;
     case KeyEvent.VK_NUMPAD7:
       columnX--;
       columnY--;
       break;
     case KeyEvent.VK_NUMPAD8:
       columnY--;
       break;
     case KeyEvent.VK_NUMPAD9:
       columnX++;
       columnY--;
       break;
     default:
       System.err.println(
         "Use the numpad to walk!  " +
         ke.getKeyCode() +
         " / " +
         ke.getKeyChar());
   }
   /**
    * Bounds check to not "walk off the screen"
    */
   columnX = Math.min(COLS - 1, columnX);
   columnY = Math.min(ROWS - 1, columnY);
   columnX = Math.max(0, columnX);
   columnY = Math.max(0, columnY);
   refresh();
   repaint();
 }

 /**
  * Refresh the screen after each STEP.
  */
 void refresh()
 {
   for (int y = 0 ; y < ROWS ; y++)
   {
     for (int x = 0 ; x < COLS ; x++)
     {
       if (columnX == x && columnY == y)
       {
         grid[x][y]="P";
       }
       else
       {
         grid[x][y]=".";
       }
     }
   }
 }

 class GridPanel extends JPanel {

   static final int STEP=10;

   GridPanel() {
     setFocusable(true);
   }

   /**
    * The displayed dgrid of labels.
    */
   public void paintComponent(Graphics g)
   {
     for (int y = 0 ; y < ROWS ; y++)
     {
       for (int x = 0 ; x < COLS ; x++)
       {
         g.drawString(
           grid[x][y],
           (x+1)*STEP,
           (y+1)*STEP );
       }
     }
   }

   public Dimension getPreferredSize() {
     return new Dimension(
       (COLS+1)*STEP,
       (ROWS+1)*STEP);
   }
 }
}
</sscce>

--
Andrew T.
PhySci.org
Daniel Gee - 13 Jan 2008 22:08 GMT
Andrew:: Thank you. That example works extremely well.

I'm not sure why my example didn't work for you with the
JMenu disabled, but maybe you're on Windows or Mac which
might treat it differently (I didn't test). I kept it
disabled to most closely match the actual program.

I also didn't know that KeyListener was even available
for use outside of things like TextArea and TextField.
Good tip there. I was afraid that I'd have to use JNI
to just make a Curses program, which would have killed
all possible mouse support. Thanks again.

Roedy:: I'm afraid since it was not literal flicker in
the normal sense, the only tip that applies is tip #8,
which was already in use.
Andrew Thompson - 14 Jan 2008 02:49 GMT
> Andrew:: Thank you. That example works extremely well.

You're welcome.

> I'm not sure why my example didn't work for you with the
> JMenu disabled, but maybe you're on Windows ...

Right first time.  Win XP, running Java 1.6.something.

--
Andrew T.
PhySci.org
Lew - 13 Jan 2008 16:45 GMT
> Alright, here's a SSCCE that seems to still capture the problem:
> http://paste.uni.cc/18083

Small stylistic notes, not related to your primary question:

"thisClass" is a very misleading name for a variable that is neither a class
nor points to 'this'.

Also, the convention for class names is that the first letter of each compound
word part is capitalized, not the entire identifier (e.g., "SwingUtilities",
not "SWINGUTILITIES") - so JRSCE should be "Jrsce", or better yet, a name that
actually describes something about the class, e.g., "FlickerDemo".

May I further suggest that you choose an indent level smaller than 8 spaces?
You run past the nominal 80-character line width much faster with such a large
indent.

Signature

Lew

Jeff Higgins - 13 Jan 2008 01:59 GMT
> ok, so there are a few classes involved:
> the main class: http://paste.uni.cc/18079
> the JRogueFrame: http://paste.uni.cc/18080
> the MapPanel: http://paste.uni.cc/18081

Gee, thanks for the pointer to pastebin.com.
I wasn't aware of this excellent service.
Wish I could help with your refresh query.
Appreciative,
JH
Andrew Thompson - 13 Jan 2008 02:40 GMT
> > ok, so there are a few classes involved:
> > the main class: http://paste.uni.cc/18079
...
> I wasn't aware of this excellent service.

Yes.  Daniel neatly sidestepped some of the
perils of posting code to usenet, by instead
loading it up at pastebin (they offer semi-nice
code formatting, too).

Sites like pastebin are of great use to us
'distributed tech types'.  :-)

--
Andrew T.
PhySci.org
Roedy Green - 13 Jan 2008 08:30 GMT
On Sat, 12 Jan 2008 15:10:28 -0800 (PST), Daniel Gee
<zefria@gmail.com> wrote, quoted or indirectly quoted someone who said

>My problem is this: if a key is held down, the refreshing becomes very
>choppy and although every event is responded to, the program doesn't
>refresh the display fast enough and ends up skipping.

See http://mindprod.com/jgloss/flicker.html
Signature

Roedy Green, Canadian Mind Products
The Java Glossary, http://mindprod.com



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.