2

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!

trashgod
  • 203,806
  • 29
  • 246
  • 1,045

2 Answers2

1

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.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Could you elaborate on how to use a view in this case please? I've looked at View and its subclasses, and they all seem to be heavily related to text rather than general component painting. I also can't find a way to easily manipulate magnification. – Kyle Buzsaki May 25 '12 at 20:28
  • I use the word _view_ in the sense discussed in [*A Swing Architecture Overview*](http://java.sun.com/products/jfc/tsc/articles/architecture/). – trashgod May 26 '12 at 02:48
0

Use

javax.swing.SwingUtilities.updateComponentTreeUI(parentComponent);

when you need to make sure all of the parentComponents child component's look and feel are updated properly.

Ozzy
  • 8,244
  • 7
  • 55
  • 95
  • Thanks so much, I put that right under my `g2d.scale(2,2);` call, and everything is sized properly now. My next question is: how wasteful is that? Should I be putting that statement in my constructor? Somewhere else? Is just leaving it in the paint method fine? – Kyle Buzsaki Apr 18 '12 at 00:35
  • To answer that, you should open up the source code to see what it does. It actually calls updateUI() to each child component. How wasteful? Only as much as, as many EXTRA components you are updating that you didn't need to. Perhaps, if you know which components you want to update, call updateUI() on those directly? Try timing the process if you want, or use a profiler to see what it does to performance. – Ozzy Apr 18 '12 at 00:40
  • Thanks again, but could you clarify: What I really meant to ask was: do I need to call this every time I paint? Or can I set it once in the constructor (the container always has the same components), and leave it be? – Kyle Buzsaki Apr 18 '12 at 01:32
  • @KyleBuzsaki You need to call it as needed. That means, whenever the components are painted (if they are not updating correctly). The other way of course, is to invalidate() and validate() the component after repainting. All that does is cause the component to doLayout(), which prompts the layout manager to layout the component againt. – Ozzy Apr 18 '12 at 01:44
  • I can't endorse this approach; more [here](http://stackoverflow.com/a/10203736/230513). – trashgod Apr 18 '12 at 06:10