2

I am writing a program for a Golf Simulator. Up to this point, it essentially works as intended, but the window only updates when I drag to resize it. Why would this be? I have attached the relevant classes below (there are others). Help is greatly appreciated. Updated as MWE. The program should change background colors, but only does this when the window is resized. What follows is the FieldComponent Class, and then the main class.

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

public class FieldComponent extends Canvas {

    private BufferedImage back;
    private int time;

public FieldComponent() {
    setVisible(true);
}

public void update(Graphics window) {
    paint(window);
}


public void paint(Graphics window) {
    Graphics2D twoDGraph = (Graphics2D) window;
    if (back == null) {
        back = (BufferedImage) createImage(getWidth(), getHeight());
    }
    Graphics graphToBack = back.getGraphics(); 
    if(time%2==0){
        graphToBack.setColor(Color.RED);
    }
    else{
        graphToBack.setColor(Color.GREEN);
    }
    graphToBack.fillOval(200, 300, 600, 600);
    time++; 
    twoDGraph.drawImage(back, null, 0, 0);
}

}

And the main class:

import javax.swing.JFrame;
import java.awt.Component;

public class GolfRunner extends JFrame {

    private static final int width = 1000;
    private static final int height = 800;

    public GolfRunner() {
        super("Golf Simulator");
        setSize(width,height); 
        FieldComponent golfgame = new FieldComponent();
        ((Component)golfgame).setFocusable(true); 
        getContentPane().add(golfgame);
        setVisible(true);
    }

    public static void main(String args[]) {
        GolfRunner run = new GolfRunner();
    }

}
user17902
  • 45
  • 3
  • Can you provide a MWE for the remaining dependencies? or maybe remove them altogether. – Simon Kuang May 24 '14 at 00:10
  • 1
    [for MWE help](http://www.sscce.org/) – Simon Kuang May 24 '14 at 00:17
  • You're casting into a subclass? That doesn't look like a good idea. `back = (BufferedImage) (createImage(getWidth(), getHeight()));` – Simon Kuang May 24 '14 at 00:28
  • What if you simply changed `back` to `Image`? (`BufferedImage` is a [decorator](https://en.wikipedia.org/wiki/Decorator_pattern) for `Image`) – Simon Kuang May 24 '14 at 00:42
  • First, don't mix heavy (`Canvas`) with light weight (`JFrame`) components, there are z-order painting issues – MadProgrammer May 24 '14 at 00:49
  • @MadProgrammer What are z-order painting issues? – Simon Kuang May 24 '14 at 00:52
  • 2
    Basically, mixing heavy and light weight components together can cause the components to fit for visibility and paint over each other. Z-order describes the depth at which a component is in the visible hierarchy, but heavy weight components don't have a concept of z-order. – MadProgrammer May 24 '14 at 00:55
  • 2
    We can't help you unless you remove the noise and isolate the problem in a demonstrative, immediately useful way. Please [provide a MWE](http://www.sscce.org/). – Simon Kuang May 24 '14 at 01:16

1 Answers1

2

I've revised your code to conform with contemporary Swing standards.

  1. You must start with a call to the SwingUtilities invokeLater method to put the Swing components on the Event Dispatch thread (EDT).

  2. You use Swing components, like JFrame. The only reason to extend a Swing component is when you want to override one of the component methods.

  3. Don't use AWT components like Canvas. Use a JPanel as a canvas.

  4. Swing automatically double buffers the Graphics. You don't have to draw on a separate BufferedImage.

  5. You set the preferred size in the JPanel, not the JFrame. Set the size for your drawings, and the JFrame pack method will take care of the size of the JFrame.

I put the classes together to make it easier to paste. You should separate the classes.

package com.ggl.testing;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class GolfRunner implements Runnable {

    private static final int    width   = 1000;
    private static final int    height  = 800;

    private JFrame frame;

    @Override
    public void run() {
        frame = new JFrame();
        frame.setTitle("Golf Simulator");
        FieldComponent golfgame = new FieldComponent();
        ((Component) golfgame).setFocusable(true);
        frame.getContentPane().add(golfgame);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new GolfRunner());
    }

    public class FieldComponent extends JPanel {

        private static final long   serialVersionUID    = 
                -6481773088613540357L;

        private int             time;

        public FieldComponent() {
            this.time = 1200;
            this.setPreferredSize(new Dimension(width, height));
        }

        @Override
        protected void paintComponent(Graphics window) {
            super.paintComponent(window);

            Graphics2D twoDGraph = (Graphics2D) window;

            if (time % 2 == 0) {
                twoDGraph.setColor(Color.RED);
            } else {
                twoDGraph.setColor(Color.GREEN);
            }
            twoDGraph.fillOval(100, 100, 600, 600);

            time++;
        }

    }

}
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111
  • Can you explain `time`? It's a magic number. – Simon Kuang May 29 '14 at 17:11
  • @Simon Kuang: I had to define the time as something so the Java would compile. 1200 was the first number that came to mind. From user17902's code, it looks like he alternates between a red circle and a green circle every time the JPanel is repainted. – Gilbert Le Blanc May 29 '14 at 17:18