11package jason .environment .grid ;
22
3- import java .awt .BorderLayout ;
4- import java .awt .Canvas ;
5- import java .awt .Color ;
6- import java .awt .Font ;
7- import java .awt .FontMetrics ;
8- import java .awt .Graphics ;
3+ import java .awt .*;
4+ import java .awt .image .BufferedImage ;
95
10- import javax .swing .JFrame ;
6+ import javax .swing .* ;
117
128/**
139 * View component for a GirdWorldModel.
@@ -23,6 +19,8 @@ public class GridWorldView extends JFrame {
2319
2420 protected GridCanvas drawArea ;
2521 protected GridWorldModel model ;
22+ protected BufferedImage backBuffer ;
23+ private Graphics2D backG ;
2624
2725 protected Font defaultFont = new Font ("Arial" , Font .BOLD , 10 );
2826
@@ -46,20 +44,25 @@ public void repaint() {
4644 cellSizeW = drawArea .getWidth () / model .getWidth ();
4745 cellSizeH = drawArea .getHeight () / model .getHeight ();
4846 super .repaint ();
49- drawArea .repaint ();
5047 }
5148
5249 /** updates all the frame */
5350 public void update () {
51+ ensureBackBuffer ();
5452 repaint ();
5553 }
5654
5755 /** updates only one position of the grid */
5856 public void update (int x , int y ) {
59- Graphics g = drawArea .getGraphics ();
60- if (g == null ) return ;
61- drawEmpty (g , x , y );
62- draw (g , x , y );
57+ if (!SwingUtilities .isEventDispatchThread ()) {
58+ // Only the event dispatch thread can update the GUI
59+ SwingUtilities .invokeLater (this ::update );
60+ return ;
61+ }
62+
63+ ensureBackBuffer ();
64+ renderAllToBackBuffer ();
65+ drawArea .repaint ();
6366 }
6467
6568 public void drawObstacle (Graphics g , int x , int y ) {
@@ -100,25 +103,7 @@ public void draw(Graphics g, int x, int y, int object) {
100103 //drawString(g,x,y,defaultFont,String.valueOf(object));
101104 }
102105
103- private static int limit = (int )Math .pow (2 ,14 );
104-
105- private void draw (Graphics g , int x , int y ) {
106- if ((model .data [x ][y ] & GridWorldModel .OBSTACLE ) != 0 ) {
107- drawObstacle (g , x , y );
108- }
109-
110- int vl = GridWorldModel .OBSTACLE *2 ; // the next object after OBSTACLE
111- while (vl < limit ) {
112- if ((model .data [x ][y ] & vl ) != 0 ) {
113- draw (g , x , y , vl );
114- }
115- vl *= 2 ;
116- }
117-
118- if ((model .data [x ][y ] & GridWorldModel .AGENT ) != 0 ) {
119- drawAgent (drawArea .getGraphics (), x , y , Color .blue , model .getAgAtPos (x , y ));
120- }
121- }
106+ private static final int limit = (int )Math .pow (2 ,14 );
122107
123108 public Canvas getCanvas () {
124109 return drawArea ;
@@ -130,27 +115,73 @@ public GridWorldModel getModel() {
130115
131116 class GridCanvas extends Canvas {
132117
133- private static final long serialVersionUID = 1L ;
118+ private static final long serialVersionUID = 2L ;
119+
120+ @ Override
121+ public void update (Graphics g ) {
122+ paint (g );
123+ }
134124
135125 public void paint (Graphics g ) {
136- cellSizeW = drawArea .getWidth () / model .getWidth ();
137- cellSizeH = drawArea .getHeight () / model .getHeight ();
138- int mwidth = model .getWidth ();
139- int mheight = model .getHeight ();
140-
141- g .setColor (Color .lightGray );
142- for (int l = 1 ; l <= mheight ; l ++) {
143- g .drawLine (0 , l * cellSizeH , mwidth * cellSizeW , l * cellSizeH );
126+ ensureBackBuffer ();
127+ g .drawImage (backBuffer , 0 , 0 , this );
128+ Toolkit .getDefaultToolkit ().sync ();
129+ }
130+ }
131+
132+ private void ensureBackBuffer () {
133+ int w = Math .max (1 , drawArea .getWidth ());
134+ int h = Math .max (1 , drawArea .getHeight ());
135+ if (backBuffer == null || backBuffer .getWidth () != w || backBuffer .getHeight () != h ) {
136+ if (backG != null ) {
137+ backG .dispose ();
144138 }
145- for (int c = 1 ; c <= mwidth ; c ++) {
146- g .drawLine (c * cellSizeW , 0 , c * cellSizeW , mheight * cellSizeH );
139+ backBuffer = new BufferedImage (w , h , BufferedImage .TYPE_INT_ARGB );
140+ backG = backBuffer .createGraphics ();
141+ backG .setRenderingHint (RenderingHints .KEY_TEXT_ANTIALIASING , RenderingHints .VALUE_TEXT_ANTIALIAS_ON );
142+ }
143+ renderAllToBackBuffer ();
144+ }
145+
146+ private void renderAllToBackBuffer () {
147+ cellSizeW = Math .max (1 , backBuffer .getWidth () / model .getWidth ());
148+ cellSizeH = Math .max (1 , backBuffer .getHeight () / model .getHeight ());
149+
150+ backG .setColor (Color .white );
151+ backG .fillRect (0 , 0 , backBuffer .getWidth (), backBuffer .getHeight ());
152+
153+ backG .setColor (Color .lightGray );
154+ for (int l = 1 ; l <= backBuffer .getHeight (); l ++) {
155+ backG .drawLine (0 , l * cellSizeH , model .getWidth () * cellSizeW , l * cellSizeH );
156+ }
157+ for (int c = 1 ; c <= backBuffer .getWidth (); c ++) {
158+ backG .drawLine (c * cellSizeW , 0 , c * cellSizeW , model .getHeight () * cellSizeH );
159+ }
160+
161+ for (int x = 0 ; x < model .getWidth (); x ++) {
162+ for (int y = 0 ; y < model .getHeight (); y ++) {
163+ renderCell (backG , x , y );
147164 }
165+ }
166+ }
167+
168+ private void renderCell (Graphics2D g , int x , int y ) {
169+ drawEmpty (g , x , y );
148170
149- for (int x = 0 ; x < mwidth ; x ++) {
150- for (int y = 0 ; y < mheight ; y ++) {
151- draw (g ,x ,y );
152- }
171+ if ((model .data [x ][y ] & GridWorldModel .OBSTACLE ) != 0 ) {
172+ drawObstacle (g , x , y );
173+ }
174+
175+ int vl = GridWorldModel .OBSTACLE *2 ; // the next object after OBSTACLE
176+ while (vl < limit ) {
177+ if ((model .data [x ][y ] & vl ) != 0 ) {
178+ draw (g , x , y , vl );
153179 }
180+ vl *= 2 ;
181+ }
182+
183+ if ((model .data [x ][y ] & GridWorldModel .AGENT ) != 0 ) {
184+ drawAgent (g , x , y , Color .blue , model .getAgAtPos (x , y ));
154185 }
155186 }
156187}
0 commit comments