Java canvas doesn't update at all - Stack Overflow most recent 30 from stackoverflow.com 2026-04-14T22:46:06Z https://stackoverflow.com/feeds/question/64063073 https://creativecommons.org/licenses/by-sa/4.0/rdf https://stackoverflow.com/q/64063073 0 Java canvas doesn't update at all Sora https://stackoverflow.com/users/10366577 2020-09-25T11:16:52Z 2020-09-25T11:45:19Z <p>I'm trying to make a Brick Breaker game where the ball which is initially on the paddle(referred to as BAR in the code below) is launched with a speed(approx 100) in some random direction, if it hits any brick on the screen the brick disappears and the ball changes direction accordingly.</p> <pre><code>import java.awt.Canvas; import java.awt.Color; import java.awt.Graphics; import javax.swing.JFrame; import java.awt.event.KeyEvent; import java.awt.event.*; public class Brick_Breaker extends Canvas implements KeyListener{ int BRICK_WIDTH=60,BRICK_HEIGHT=30,X=0,Y=0; int BAR_X = 390,BAR_Y=560,BAR_WIDTH=120,BAR_HEIGHT=20,BAR_DX=10; int BALL_X=440,BALL_Y=540,BALL_SIZE=20,BALL_DX=0,BALL_DY=0; int LEFT_WALL=100,RIGHT_WALL=800,TOP_WALL=10; boolean GAME_STATE=false; int BAR_STATE=0; static int[][] y = new int[10][5]; static int[][] x = new int[10][5]; static int[][] status = new int[10][5]; static Canvas canvas; static JFrame frame; @Override public void keyReleased(KeyEvent ke){} @Override public void keyTyped(KeyEvent ke){} public void STaRT(){ frame = new JFrame(&quot;My Drawing&quot;); frame.addKeyListener(this); canvas = new Brick_Breaker(); canvas.setSize(900, 600); frame.add(canvas); frame.pack(); frame.setVisible(true); } @Override public void update(Graphics g){ BALL_X += BALL_DX; BALL_Y += BALL_DY; for(int i=0;i&lt;10;i++){ for(int j=0;j&lt;5;j++){ if(BALL_X&gt;x[i][j]&amp;&amp;BALL_X&lt;(x[i][j]+BRICK_WIDTH)&amp;&amp;BALL_Y&lt;=y[i][j]+BAR_HEIGHT+BALL_SIZE &amp;&amp; BALL_Y&gt;y[i][j]&amp;&amp;BALL_DY&lt;0){ BALL_DY=-BALL_DY; status[i][j]-=1; }else if(BALL_X&gt;x[i][j]&amp;&amp;BALL_X&lt;(x[i][j]+BRICK_WIDTH)&amp;&amp;BALL_Y&gt;=y[i][j]-BALL_SIZE &amp;&amp; BALL_Y&lt;y[i][j]+BAR_HEIGHT&amp;&amp;BALL_DY&gt;0){ BALL_DY=-BALL_DY; status[i][j]-=1; }else if(BALL_X+BALL_SIZE&gt;=x[i][j]&amp;&amp;BALL_X&lt;(x[i][j]+BRICK_WIDTH)&amp;&amp;BALL_Y&gt;=y[i][j] &amp;&amp; BALL_Y&lt;y[i][j]+BAR_HEIGHT&amp;&amp;BALL_DY&lt;0){ BALL_DX=-BALL_DX; status[i][j]-=1; }else if(BALL_X&gt;x[i][j]&amp;&amp;BALL_X-BALL_SIZE&lt;=(x[i][j]+BRICK_WIDTH)&amp;&amp;BALL_Y&gt;=y[i][j] &amp;&amp; BALL_Y&lt;y[i][j]+BAR_HEIGHT&amp;&amp;BALL_DY&lt;0){ BALL_DX=-BALL_DX; status[i][j]-=1; }else if(BALL_X-BALL_SIZE&lt;LEFT_WALL||BALL_X+BALL_SIZE&gt;RIGHT_WALL){ BALL_DX=-BALL_DX; }else if(BALL_Y-BALL_SIZE&lt;TOP_WALL){ BALL_DY=-BALL_DY; } } } BAR_X = BAR_X +BAR_STATE*BAR_DX; repaint(); } public static void main(String[] args) { Brick_Breaker bb = new Brick_Breaker(); bb.STaRT(); for(int i=0;i&lt;10;i++){ for(int j=0;j&lt;5;j++){ x[i][j] = 300+60*j; y[i][j] = 50+30*i; status[i][j] = 1; } } } @Override public void keyPressed(KeyEvent ke){ if(!GAME_STATE){ BALL_DX = (int)(100*Math.random()); BALL_DY = (int)(Math.sqrt(100*100-BALL_DX*BALL_DX)); GAME_STATE = true; }else if(ke.getKeyCode() == KeyEvent.VK_LEFT){ BAR_STATE=-1; }else if(ke.getKeyCode()==KeyEvent.VK_RIGHT){ BAR_STATE=1; } } @Override public void paint(Graphics g) { super.paint(g); g.setColor(Color.white); g.drawLine(LEFT_WALL,600, LEFT_WALL, TOP_WALL); g.drawLine(RIGHT_WALL, 600, RIGHT_WALL, TOP_WALL); g.drawLine(LEFT_WALL,TOP_WALL,RIGHT_WALL,TOP_WALL); g.fillRect(BAR_X,BAR_Y,BAR_WIDTH,BAR_HEIGHT); g.setColor(Color.red); g.fillOval(BALL_X, BALL_Y, BALL_SIZE, BALL_SIZE); for(int i=0;i&lt;10;i++){ for(int j=0;j&lt;5;j++){ if(status[i][j]&gt;0){ X = x[i][j];Y=y[i][j]; g.setColor(Color.white); g.fillRect(X, Y, BRICK_WIDTH, BRICK_HEIGHT); g.setColor(Color.red); g.fillRect(X+3, Y+3, BRICK_WIDTH-6, BRICK_HEIGHT-6); } } } setBackground(Color.black); } } </code></pre> <p>Here the update function doesn't seem to update at all. I'm not really sure on how the method works as well. Any help would be appreciated</p> https://stackoverflow.com/questions/64063073/-/64063505#64063505 2 Answer by MadProgrammer for Java canvas doesn't update at all MadProgrammer https://stackoverflow.com/users/992484 2020-09-25T11:45:19Z 2020-09-25T11:45:19Z <p><code>Canvas</code> is a pretty low level component and one which I'd only consider using if I needed to use a <code>BufferStrategy</code>.</p> <p><code>update</code> is called as part of the paint phase and because you've overridden it without calling it's <code>super</code> implementation, you broke the paint workflow.</p> <p>AWT and Swing generally employ a passive rendering system, this means that updates only occur when the system decides it needs to happen, so overriding <code>update</code> the way you have doesn't really make sense and isn't going to help you.</p> <p>A better place to start is with a <code>JPanel</code>, the main reason is because it's double buffered and saves you hassles of trying to figure out how to eliminate flickering.</p> <p>A good place to start is <a href="https://docs.oracle.com/javase/tutorial/uiswing/painting/index.html" rel="nofollow noreferrer">Performing Custom Painting</a> and <a href="https://www.oracle.com/java/technologies/painting.html" rel="nofollow noreferrer">Painting in AWT and Swing</a> to gain a better understanding of how painting works (and how you should work with it).</p> <p><code>KeyListener</code> is also a poor choice for input monitoring, seriously, just do some searching on SO for all the reasons why.</p> <p>A better, and generally less problematic approach is to use <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html" rel="nofollow noreferrer">key bindings</a> as well.</p> <pre><code>import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.Timer; public class Test { public static void main(String[] args) { new Test(); } public Test() { EventQueue.invokeLater(new Runnable() { @Override public void run() { JFrame frame = new JFrame(); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { int BRICK_WIDTH = 60, BRICK_HEIGHT = 30, X = 0, Y = 0; int BAR_X = 390, BAR_Y = 560, BAR_WIDTH = 120, BAR_HEIGHT = 20, BAR_DX = 1; int BALL_X = 440, BALL_Y = 540, BALL_SIZE = 20, BALL_DX = 0, BALL_DY = 0; int LEFT_WALL = 100, RIGHT_WALL = 800, TOP_WALL = 10; boolean GAME_STATE = false; int BAR_STATE = 0; int[][] y = new int[10][5]; int[][] x = new int[10][5]; int[][] status = new int[10][5]; private Timer timer; public TestPane() { for (int i = 0; i &lt; 10; i++) { for (int j = 0; j &lt; 5; j++) { x[i][j] = 300 + 60 * j; y[i][j] = 50 + 30 * i; status[i][j] = 1; } } BALL_DX = 0; //(int) (100 * Math.random()); BALL_DY = -1;//(int) (Math.sqrt(100 * 100 - BALL_DX * BALL_DX)); setBackground(Color.BLACK); InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), &quot;left&quot;); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), &quot;right&quot;); ActionMap am = getActionMap(); am.put(&quot;left&quot;, new KeyAction(this, -1)); am.put(&quot;right&quot;, new KeyAction(this, 1)); } @Override public void addNotify() { super.addNotify(); //To change body of generated methods, choose Tools | Templates. if (timer == null) { timer = new Timer(5, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { tick(); } }); timer.start(); } } @Override public void removeNotify() { super.removeNotify(); if (timer != null) { timer.stop(); timer = null; } } @Override public Dimension getPreferredSize() { return new Dimension(900, 600); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); g2d.setColor(Color.white); g2d.drawLine(LEFT_WALL, 600, LEFT_WALL, TOP_WALL); g2d.drawLine(RIGHT_WALL, 600, RIGHT_WALL, TOP_WALL); g2d.drawLine(LEFT_WALL, TOP_WALL, RIGHT_WALL, TOP_WALL); g2d.fillRect(BAR_X, BAR_Y, BAR_WIDTH, BAR_HEIGHT); g2d.setColor(Color.red); g2d.fillOval(BALL_X, BALL_Y, BALL_SIZE, BALL_SIZE); for (int i = 0; i &lt; 10; i++) { for (int j = 0; j &lt; 5; j++) { if (status[i][j] &gt; 0) { X = x[i][j]; Y = y[i][j]; g2d.setColor(Color.white); g2d.fillRect(X, Y, BRICK_WIDTH, BRICK_HEIGHT); g2d.setColor(Color.red); g2d.fillRect(X + 3, Y + 3, BRICK_WIDTH - 6, BRICK_HEIGHT - 6); } } } g2d.dispose(); } protected void tick() { BALL_X += BALL_DX; BALL_Y += BALL_DY; for (int i = 0; i &lt; 10; i++) { for (int j = 0; j &lt; 5; j++) { if (BALL_X &gt; x[i][j] &amp;&amp; BALL_X &lt; (x[i][j] + BRICK_WIDTH) &amp;&amp; BALL_Y &lt;= y[i][j] + BAR_HEIGHT + BALL_SIZE &amp;&amp; BALL_Y &gt; y[i][j] &amp;&amp; BALL_DY &lt; 0) { BALL_DY = -BALL_DY; status[i][j] -= 1; } else if (BALL_X &gt; x[i][j] &amp;&amp; BALL_X &lt; (x[i][j] + BRICK_WIDTH) &amp;&amp; BALL_Y &gt;= y[i][j] - BALL_SIZE &amp;&amp; BALL_Y &lt; y[i][j] + BAR_HEIGHT &amp;&amp; BALL_DY &gt; 0) { BALL_DY = -BALL_DY; status[i][j] -= 1; } else if (BALL_X + BALL_SIZE &gt;= x[i][j] &amp;&amp; BALL_X &lt; (x[i][j] + BRICK_WIDTH) &amp;&amp; BALL_Y &gt;= y[i][j] &amp;&amp; BALL_Y &lt; y[i][j] + BAR_HEIGHT &amp;&amp; BALL_DY &lt; 0) { BALL_DX = -BALL_DX; status[i][j] -= 1; } else if (BALL_X &gt; x[i][j] &amp;&amp; BALL_X - BALL_SIZE &lt;= (x[i][j] + BRICK_WIDTH) &amp;&amp; BALL_Y &gt;= y[i][j] &amp;&amp; BALL_Y &lt; y[i][j] + BAR_HEIGHT &amp;&amp; BALL_DY &lt; 0) { BALL_DX = -BALL_DX; status[i][j] -= 1; } else if (BALL_X - BALL_SIZE &lt; LEFT_WALL || BALL_X + BALL_SIZE &gt; RIGHT_WALL) { BALL_DX = -BALL_DX; } else if (BALL_Y - BALL_SIZE &lt; TOP_WALL) { BALL_DY = -BALL_DY; } } } BAR_X = BAR_X + BAR_STATE * BAR_DX; repaint(); } class KeyAction extends AbstractAction { private TestPane source; private int delta; public KeyAction(TestPane source, int delta) { this.source = source; this.delta = delta; } @Override public void actionPerformed(ActionEvent e) { source.BAR_STATE = delta; } } } } </code></pre> <p>I've messed with delta values, because the ball and bar disappeared real quick</p>