java gui is flashing

1,419 views
Skip to first unread message

Mate Toth

unread,
Jul 24, 2010, 9:11:32 AM7/24/10
to Clojure
Hi,

my problem is that during execution my presentation java applet is
flashing. There are many components which paint to a JPanel using it's
Graphics (.getGraphics). I think maybe the problem is that I don't
have any "paint everything now" routine..(I don't know which Java
routine to use, how I have to synchronize it etc..) Thanks for your
time and help.


I've the following code for the gui part (fe stands for "flocking-
enviroment", I'm making a flocking library):

The main loop:

(defn main [starting-fe]
(let [first-fe starting-fe
panel (new JPanel)
frame (new JFrame)]

;; configuring panel
(. panel setPreferredSize (new Dimension width height))

;; configuring frame
(. frame add panel)
(. frame pack)
(. frame setVisible true)

(loop [fe first-fe]
(draw-fe fe panel)
(Thread/sleep 100)
(recur ((:update-f fe) fe)))))


Blanking the screen:

(defn blank-panel [panel]
(let [g (. panel getGraphics)]
(. g setColor (. Color BLACK))
(. g fillRect 0 0 width height))))

At the end every boid drawed by this(called by the draw-fe function):

(defn draw-boid [boid panel]
(let [[x0 x1] (:pos boid)]
(let [g (. panel getGraphics)]
(. g setColor (:color boid))
(. g fillRect (- x0 2) (- x1 2) 5 5)))))

Nurullah Akkaya

unread,
Jul 24, 2010, 11:52:14 AM7/24/10
to clojure
It is probably happening because a bare bones JPanel is a white canvas
every time swing paints it, it paints a white canvas than your
routines paint over that giving you the flashing behavior, right way
to paint on a JPanel is to extend it using proxy and overwrite
paintComponent method, this is the method Java calls when it wants to
paint a component. However it won't call it all the time, it will be
called only when swing thinks component needs a repaint (i.e when you
resize the frame). In order to create animations on the panel you have
two choices, you can use a swing timer and call repaint on the panel
say ever 100 ms or if your state is held in a ref you can add a watch
to the ref that will call repaint whenever ref is updated.

You can copy/paste the last snippet from,

http://nakkaya.com/2010/07/21/physics-with-clojure/

which uses the former method for painting on a JPanel.

Hope this helps...
--
Nurullah Akkaya
http://nakkaya.com

> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>

Brian Schlining

unread,
Jul 24, 2010, 11:52:29 AM7/24/10
to clo...@googlegroups.com
I see 2 things:

1) It's best to explicitly start your Swing UI on Swing's event dispatch thread. The java code to do this is:
SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new App(); // OR whatever you're started UI code is
                }
            });

2) You're calling Thread.sleep on the same thread you're drawing your UI. If that's the EventDispatchThread, you're stopping all drawing events while the thread is sleeping. 

Cheers
B


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en



--
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Brian Schlining
bschl...@gmail.com

Ryan Sattler

unread,
Jul 24, 2010, 10:01:01 PM7/24/10
to Clojure
I've been working on a game with Clojure/Swing lately and the simplest
way to avoid flashing is to draw to a bufferedImage first, then draw
that bufferedImage all at once. This means that parts of the screen
that don't change won't be briefly overwritten by the background
color, avoiding flashing. Here's some code:

(defn render [game window]
(let [#^BufferedImage image (.createImage window window-width window-
height)
#^Graphics gfx (.createGraphics image)
#^Graphics2D gfx2 (.getGraphics #^JFrame window)]

(render-background gfx)
;draw more stuff on gfx here, eg, your draw-boid would go here

(.drawImage gfx2 image 0 0 window))) ;finally draws the buffered
image to the screen all at once

--
Ryan Sattler

Ryan Twitchell

unread,
Jul 25, 2010, 5:55:23 AM7/25/10
to Clojure
HI,

You'd be best served overriding the JPanel's paint or paintComponent
method (I'm fuzzy on the difference), and then calling repaint
periodically (at your desired frame rate). IIRC, repaint is safe to
call from any thread, and it will cause the paint methods to be called
in the swing thread. Also, try to ensure your swing setup code runs
in the swing thread if possible (see Brian's reply).

See also :
Background on Java 2D: http://java.sun.com/docs/books/tutorial/2d/TOC.html
contrib has a do-swing macro for evaling in the swing thread:
http://richhickey.github.com/clojure-contrib/swing-utils-api.html

Ryan

Isak Hansen

unread,
Jul 25, 2010, 10:04:20 AM7/25/10
to clo...@googlegroups.com
On Sat, Jul 24, 2010 at 3:11 PM, Mate Toth <tot...@gmail.com> wrote:
> Hi,
>
> my problem is that during execution my presentation java applet is
> flashing. There are many components which paint to a JPanel using it's
> Graphics (.getGraphics). I think maybe the problem is that I don't
> have any "paint everything now" routine..(I don't know which Java
> routine to use, how I have to synchronize it etc..) Thanks for your
> time and help.
>

Google for "double buffering".


Isak

Nurullah Akkaya

unread,
Jul 25, 2010, 10:40:20 AM7/25/10
to clojure
On Sun, Jul 25, 2010 at 12:55 PM, Ryan Twitchell <metat...@gmail.com> wrote:
> You'd be best served overriding the JPanel's paint or paintComponent
> method (I'm fuzzy on the difference), and then calling repaint
> periodically (at your desired frame rate).  IIRC, repaint is safe to
> call from any thread, and it will cause the paint methods to be called
> in the swing thread.  Also, try to ensure your swing setup code runs
> in the swing thread if possible (see Brian's reply).


Unless you have a good reason, you should not override paint,

http://download.oracle.com/docs/cd/E17409_01/javase/tutorial/uiswing/painting/closer.html

Mate Toth

unread,
Jul 25, 2010, 12:22:45 PM7/25/10
to Clojure
Thx guys!
I used double-buffering like in Ryan's code and it worked like a
charm!

M
Reply all
Reply to author
Forward
0 new messages