Search code examples
javaswingwindowscalerepaint

How to successfully modify the way a JFrame (and all of its components) paint?


I'm trying to implement a simple window scale in java's swing library. The goal is simply to double the window height and width, and paint the window and each of its components in scale.

Here's an example of the code I'm using:

public class MyWindow extends JFrame {

...

public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    g2d.scale(2,2);
    super.paint(g);
}
}

The position and size for each my components in this window is set manually using setBounds with a null layout for the window.

When I actually run the program, what happens is that the first paint for the window seems successful-- everything is sized appropriately. Each subsequent repaint by the components, however, is neither twice the size, nor in the proper location. Here's what I mean:

game view

As you can see, portions of the screen which have components that call repaint manually (the animating bits), don't seem to be using the Graphics2D scale of the JFrame. I looked in the source code, and tried overloading a few other methods (update and repaint, mostly), but all of them seemed to produce the same result. I further looked at the paint and repaint methods of the component and container classes, but they all seem to call a specified repaint of their parent. Shouldn't my Window be the "biggest" parent? If so, why haven't these repaint calls reached my Window?

My big question to you is, therefore: what repaint methods of the parent component do the child components call? Why aren't the calls properly routed to my JFrame's paint call? Is there any other (better) way that I can scale my window? Any and all help is appreciated!


Solution

  • As discussed in Painting in AWT and Swing: The Paint Methods, "Swing programs should override paintComponent() instead of overriding paint()." A common approach is to create a view by overriding paintComponent() in a JComponent (or subclass), as shown here. Let your view listen for changes to the game's model, as discussed here.

    SwingUtilities.updateComponentTreeUI() should be used to change the Look & Feel, not update the view.