Skip to main content

paint() not called on resize down

37 replies [Last post]
qu0ll
Offline
Joined: 2006-12-09
Points: 0

Could someone please tell me why the paint() method is not not being called while the frame is being resized smaller? I have turned on dynamic layout and paint() is called repeatedly as the frame is resized larger but not when it's being resized smaller.

<br />
import java.awt.Color;<br />
import java.awt.EventQueue;<br />
import java.awt.Frame;<br />
import java.awt.Graphics;<br />
import java.awt.Graphics2D;</p>
<p>public class TestFrame2 extends Frame {<br />
	public TestFrame2() {<br />
		getToolkit().setDynamicLayout(true);<br />
		setSize(500, 500);<br />
	}</p>
<p>	@Override<br />
	public void paint(Graphics g) {<br />
System.out.println("Painting!");<br />
		int width = getWidth();<br />
		int height = getHeight();<br />
		Graphics2D g2d = (Graphics2D)g;<br />
		g2d.setClip(0, 0, width, height);<br />
		g2d.setColor(Color.WHITE);<br />
		g2d.fillRect(0, 0, width, height);<br />
		g2d.setColor(Color.BLUE);<br />
		g2d.fillRect(20, 40, width - 40, height - 60);<br />
	}</p>
<p>	public static void main(String[] args) {<br />
		EventQueue.invokeLater(new Runnable() {<br />
			public void run() {<br />
				new TestFrame2().setVisible(true);<br />
			}<br />
		});<br />
	}<br />
}<br />

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
qu0ll
Offline
Joined: 2006-12-09
Points: 0

Hi swv,

The algorithm used to render the screen in my example is just something whipped-up for the sake of demonstrating the fact that paint() is not called on resize down. I am using a more sophisticated algorithm in my actual program which only repaints the dirty regions.

I take your point about advanced graphics programming techniques and I am reading a lot to enhance my knowledge on this subject. There is no real time limit on producing the library I am working on so I don't mind learning along the way. There will be progress and some negative progress at times which I accept. I am financing the project myself so I don't have to answer to anyone in that respect.

I should add that the more I get into this project the more I gain increased respect for Swing and the way it accomplishes some very complex tasks.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

qu0ll
Offline
Joined: 2006-12-09
Points: 0

...now I am COMPLETELY confused! I am not sure if you are saying that paint() is being called or not. In one sentence you say it was called 18 times while resizing smaller but then you say that paint() is not being called when resizing smaller in another sentence.

Well, I am absolutely sure that when I am resizing smaller on any platform with any Java and using any variation of your program or my program I get NO paint() calls. If you grab the border of the window and drag it smaller it should call paint() WHILE YOU ARE DRAGGING like it does when you resize larger. It doesn't. It just doesn't. I am not talking about stopping or pausing along the way while you are dragging or what happens after you have completed dragging/resizing. That's irrelevant to what I am talking about. I am not sure you completely understand what I am on about. Maybe I am not explaining it very well. I am sorry if that is so.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

swv
Offline
Joined: 2007-05-28
Points: 0

swv said : So when is paint invoked? Don't know. Must be a Windoze thing. You're right about it not having to be invoked when things are getting smaller.

but it DOES in fact get called as I said earlier.. 18 times. I was just referring to the notion that it might not HAVE to be called when it's resized down. It does in fact get called as I said, when it's resized down.

All I am saying is, there's a theoretical rational for it not being called. But on my machine? Called when resizing down.

Why the difference? I mentioned that in my previous post. Those are the only things I can think of.

qu0ll
Offline
Joined: 2006-12-09
Points: 0

Ok swv, I will accept that paint IS being called on your machine... but it definitely isn't on either of my machines. Now, we need to work out why there is a difference.

It can't be an argument or JVM option as I am not setting any on either machine and I have checked the JRE configuration in the Control Panel. I doubt it is an OS-dependent thing because the 2 machines are running different flavours of Windows (I haven't tried on Linux though). It can't be a BIOS or machine dependent thing because the hardware on the 2 machines concerned is vastly different (even in regard to the number of CPUs). And it's not an Eclipse thing as I have tried running the programs from NetBeans as well as the command line in addition to Eclipse.

But we are running exactly the same code with the same version of Java - how can there be such a significant difference? I am at a complete loss to explain this.

If anyone can offer a solution I will be eternally grateful!

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

swv
Offline
Joined: 2007-05-28
Points: 0

anyway this thread is all involved with the vagarities of when paint is invoked by the VM, but if your goal is to know when your frame is being resized and change what it displays, the way to do that (and the most reliable way, apparently) is to attach a listener to the resizing event and invoke a repaint from that listener.

qu0ll
Offline
Joined: 2006-12-09
Points: 0

Unfortunately, that is not quite correct... I have tried adding a listener and calling repaint() on resize but it only helps in that the painting is done after completion of the resizing. It still doesn't do anything WHILE it's resizing down. The only difference is, as I said, paint() is called after the resize which it isn't (on my machines) at the moment.

Which is the whole point of what I am trying to do and the whole point of this thread. I am trying to FORCE a repaint() as the frame is resized up or down but (as we have discussed) I can only get it to happen during resize up or after resize down by adding the listener. The result is that, if don't use the listener, the user resizes down and the layout does not adjust. It seems the best I can do is have it adjust AFTER they have resized down but I don't think this is acceptable.

Anyway, I think there is more to this issue given that you and I experience markedly different results using the same JRE and source. There has to be an explanation to that and I will not rest until I find it!

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

swv
Offline
Joined: 2007-05-28
Points: 0

Ahh they hooked the event to the mouseRleased event... that's when Frame wakes up and smells the coffee.

I just tried to add a MouseMotionListener, the event they SHOULD be listening for... nothing happening- doesn't work

also tried the jack-of-all listeners PropertyChangeListener. Nada.

I can think of lots of workarounds.... for instance, attach your listeners to the content pane or a gratuitous JPanel you add to the Frame. That should work..... I think. OF course I thought the PorpertyChange listener would work....

qu0ll
Offline
Joined: 2006-12-09
Points: 0

Actually, adding a Panel and doing it that way solves the problem of paint() not being called but I don't do it simply because it also causes the screen to be cleared and results in flickering. So, if you can somehow show me how to avoid that flickering then I am happy to go with adding a Panel. The solution of using the argument -Dsun.awt.noerasebackground=true in the other thread works but has the unwanted side effect of painting ugly black backgrounds in the area of the screen being updated. I have tried setting the background colour to white but it still draws black backgrounds. I guess this is not a major drama and may be the only solution there is (unless we can figure out why our apps behave so differently).

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

swv
Offline
Joined: 2007-05-28
Points: 0

What do you want to have happen on screen, neverminding for now how it's to be achieved. YOU want that blue square to always be centered in the screen with the same amount of white border around it? You want the area of the blue square to just get smaller as you downsize the frame, but keep the white border around it?

qu0ll
Offline
Joined: 2006-12-09
Points: 0

I want the blue square to always be centered with a white border around it so yes, the blue square needs to get smaller as the frame is resized smaller but the white border remains the same. The ugly black background I referred to only happens when you resize larger when using a Panel.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

swv
Offline
Joined: 2007-05-28
Points: 0

DOes it have t be heavyweight? Can it be Swing?

qu0ll
Offline
Joined: 2006-12-09
Points: 0

It has to be heavyweight (not Swing) although I notice that Swing allows you to resize a window up or down without flickering and does honour the background colour so it must be possible. I just need to do something similar in my AWT application.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

irond13
Offline
Joined: 2007-06-26
Points: 0

Hi qu0ll,

I just tried your test app and I get the same results as you do - paint() isn't called on resize down. Reshape() & setBounds() also aren't called. If you use a JFrame instead of an AWT Frame however, things seem to work as hoped (I still get flickering with both Frame and JFrame implementations though).

I think the reason for this behaviour has something to do with the fact that a Frame is, for all intents and purposes, a native container, and so reacts differently to resizes (amongs other things).

Regards,
Pierre

qu0ll
Offline
Joined: 2006-12-09
Points: 0

Hi Pierre,

Thanks for doing that - I appreciate it - and it's good that my results have been confirmed. I am probably going to go with a Frame, a Panel and the JVM option -Dsun.awt.noerasebackground=true to prevent flicker. As I said, the only drawback with this solution is the ugly black background in the areas of the frame being updated when resizing up.

Thanks again mate.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

irond13
Offline
Joined: 2007-06-26
Points: 0

Just for interest sake, why don't you use Swing?

qu0ll
Offline
Joined: 2006-12-09
Points: 0

Yes, fair question. The answer is that I am developing something which doesn't need Swing as it renders its own components in Java2D. So it's simply a case of not requiring Swing rather than not being able to use it.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

swv
Offline
Joined: 2007-05-28
Points: 0

Well if it's nothing to you either way, why not use Swing? Since your components are lightweight in the same way Swings are? At least then you take whatever-the-hell Windoze is doing out of the equation as far as painting goes, right? Remove a variable you have no, or not much , control over.

OK as far as the painting goes, I am not sure where you are in terms of your knowledge, so I'll just say what I see and you take it as you see fit.

The first thing is, you re-create the entire screen each time. That's not going to give you the best performance. Getting good (non-flicker, no black areas etc) results from painting is all about the algo you use to paint with.
Everything in engineering is about tradeoffs, right? So if the way you're doing it (nothing in memory, but bad performance) isn't working for you trade off memory for performance until you get acceptable performance.

The way it's written now, you fill the screen with white then superimpose the blue square. That's a lot of pixels you're drawing that ultimately get covered up again by the blue square. Why not draw a Shape or GeneralPath around the blue square?

Also, is it faster to draw a pre-rendered image of a blue square or use drawRect the way you do? If it's faster to draw a pre-rendered blue square, then render once, cache, blit to screen and surround with white. On resizing down, it doesn't matter that the blue square is too big because the Frame will cut everything outside the white off anyway. It may even know that that part is not visible and stop painting for free. In fact, I know it does this.

Ask yourself this question- the opposite question people usually ask - can a programmer write painting code so bad that paint() always does horrible things and does them slowly, no matter how a machine is set up or what switches are flipped?

You want to draw your own lightweights, so you have to learn the tricks of painting- just using the API (not saying you're doing this) in the most-straighforward-to-program way isn't going to give good results, unfortunately, mostly because computer graphics is one of the areas where CPUs aren't fast enough and, in fact, our grasp will always exceed our reach in this area.

Anyway the point is- whether you realize it or not, you've set down the path to be a capable graphics programmer when you say you want to draw your own lightweights. Now you have to know what they know.

Cheers!

Message was edited by: swv

Message was edited by: swv

qu0ll
Offline
Joined: 2006-12-09
Points: 0

Nope, it's not working on XP either... are you absolutely sure that paint() is being called when you resize SMALLER and not LARGER? It's just not happening here.

Can anyone else verify this? Just run the program for us and report back your findings.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

swv
Offline
Joined: 2007-05-28
Points: 0

Well, if you make it smaller in width only, it prints out.
If you make it smaller in height only, it prints out.
If you make it smaller diagonally , it OCCASIONALLY seems to sometimes not print out, implying that they either deliberately or through omission don't repaint if the aspect ratio isn't changed.

But to give you some idea of the extent of the effect, I can't reliably get it to not print out for very long as a SLOWLY resize the aspect ratio, even when I am trying to move only diagonally.

So there is some small variance in paint being invoked, but the emphasis is on small.

Try attaching a listener to listen for changes and see if that doesn't get it to report more often? Just a thought.

qu0ll
Offline
Joined: 2006-12-09
Points: 0

Hi swv,

Something is wrong - I am just not getting that behaviour at all. If I resize down either with the diagonal or by height or by width only I get NO painting happening WHILE THE RESIZING DRAGGING IS HAPPENING (I am not referring to what happens AFTER the resize is completed even though that doesn't work for me either).

BTW, I have tried attaching a resize listener that calls paint() but it still doesn't work.

What could possibly be happening here??? I have tried Java 6 Update 2 on Vista and XP. I wish someone else would report in their findings.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

swv
Offline
Joined: 2007-05-28
Points: 0

back.
Well it can't not be calling paint, because you can see on the screen that paint is being invoked- the JFrame IS being resized on screen! Nothing is responsible for that but paint() (I believe!)

There's some sort of total disconnect going on.

1) you're not looking in the right place for output. Somehow you've directed System.out.println to somewhere else, another stream or something. Or you're not setting your eyes in the right place to see it (please forgive me if some of these sound vaguely insulting- believe me, I've done things far simpler than these wrong!)

2 You're not running the program you think you are. You're running an old version of another program by pushing the run button on your ide or something.

you need a sanity check. Start by writing the Hello World and making sure you see hello world. THen slowly insert the Frame code posted here method by method, invoking those methods in your new iteration each time and making sure you're inserting a different System.out.println to be sure you're seeing THAT VERY code.
Do this until you're back to the Frame program.

IF all else fails, nuke the paint() to do nothing. That should break everything (you see nothing). At least then you'll know it's being invoked.

No use looking at the program again since it's a known-to-work program on my machine. It's something to do with your config.

Let me know how it goes!

qu0ll
Offline
Joined: 2006-12-09
Points: 0

swv,

Let me just say that I appreciate your patience in this matter as clearly I must be doing something wrong. But I really can't see what that is - it's quite bizarre. I have been running the programs through Eclipse so I just tried your program from the command line and absolutely no output is produced when the window is sized smaller either while the border is being dragged or after the resize is complete. In desperation I have installed Java 7 and exactly the same thing happens. But you say the frame is being resized so paint() must be called. I disagree - I don't think paint needs to be called for the boundaries of the frame to be resized. Painting only affects the content of the frame.

So unless it's a bug that was introduced in Update 2 of Java 6 I am baffled. Is there any chance you could upgrade to the latest release of Java 6 and try it again? Also, could you please point out why your program should work whereas mine won't because I can't see any differences between them in the area of resizing and painting. And finally, can you tell me if when you run my program in the original post do the *contents* of the frame get updated AS YOU ARE RESIZING SMALLER? You can tell because the white border around the blue square will be updating its size. On my machine, the white border disappears around the right and bottom margins when resizing smaller.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

swv
Offline
Joined: 2007-05-28
Points: 0

java 6 update 2 is the latest version and it's what I have (where did you get java 7 from??).

well I ran your program and I got the paint method invoked 18 times going from launch size to minimum size.

then I rewrote it so it was like mine and got the same results.

Also I got it much more often when resizing horizontally or vertically than diagonally.

So when is paint invoked? Don't know. Must be a Windoze thing. You're right about it not having to be invoked when things are getting smaller. Maybe that's a good thing.. why repaint if you're only going to paint a subset of what you've already painted? Still, something is painting the frame at each iteration of making it smaller. IF it's not paint, then something is.

SO if this some sort of optimization, we can all take a lesson from it. Whoever optimized in this way didn't (or did, who knows?) take into consideration the use case where the programmer wanted the act of shrinking the window to MEAN something and paint the windows content differently.

So , as my great grandfather used to say - put that in your pipe and smoke it!

swv
Offline
Joined: 2007-05-28
Points: 0

really it smells like an optimization flag somewhere. Paint is being optimized in some way, as I mentioned above. I am quite sure there are flags and switches on my graphics card, my OS , my BIOS, my java installation, here there everywhere, and I know nothing about them and care not to know anything about them until I get caught in some sort of situation like this. Then I get really mad!!!

Just a thought.

swv
Offline
Joined: 2007-05-28
Points: 0

nope that code thing didn't work.... yours looks nicely formatted with color and mine is just text... not sure what the diff is.. maybe a view source will tell me?

swv
Offline
Joined: 2007-05-28
Points: 0

[code]
import javax.swing.JFrame;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;

public class StartWithThis
{
MyFrame mainFrame;

public static void main(String args[])
{

StartWithThis name = new StartWithThis();
name.doit();

}

public void doit()
{
createComponents();
displayGUI();

}

private void createComponents()
{
mainFrame = new MyFrame();
//mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

private void displayGUI()
{
mainFrame.setSize(new Dimension(800, 800));
mainFrame.setVisible(true);

}

private class MyFrame extends Frame
{
private int number;

public void paint(final Graphics g)
{
super.paint(g);
System.out.println("StartWithThis$MyFrame.paint" + number++);

}

}

}
[/code]

Message was edited by: swv

qu0ll
Offline
Joined: 2006-12-09
Points: 0

swv,

That doesn't work for me with Java 6 Update 2. It increments the paint count when resizing up but not down. I am talking about painting while the frame is actually being resized - while the border is being dragged. Actually, yours doesn't even seem to repaint after a resize down has completed at all. Am I missing something?

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

swv
Offline
Joined: 2007-05-28
Points: 0

yeah that's a you thing then b/c it works on my computer and it should work on everyones...

me: 1.6.0-beta2 XP64

that's pretty weird definitely works on mine 100%.

huh....

qu0ll
Offline
Joined: 2006-12-09
Points: 0

Perhaps it's a Vista thing... I am on Vista x64. I will try it on my XP machine when I can and let you know what happens.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

priatuu
Offline
Joined: 2007-09-11
Points: 0

Guys, this just drove me crazy with Java 6:

Simple JDialog, overriding paint:

public void paint(Graphics g) {
super.paint(g);
g.drawImage(image, 0, 0, null);
}

I added a print to see what happens, paint is not called like this when I switch from this dialog to another window and back (and thus the pic disappears). When I remove the super call it is called everytime I switch. With Java 5 it works fine and the pic is repainted every time.

Something must go really wrong internally, this can't be the expected behaviour, can it?

swv
Offline
Joined: 2007-05-28
Points: 0

File a bug or RFE ?

alexfromsun
Offline
Joined: 2005-09-05
Points: 0

Hello Guys

Painting in Swing topLevels like JApplet, JFrame, JDialog and JWindow
should be performed with help of its child lightweight components,
so paint() methods should not be directly overridden

because in this case window's back buffer won't be updated correctly

Thanks
alexp

qu0ll
Offline
Joined: 2006-12-09
Points: 0

Hi Alex,

Does the same apply in my original post where I was using a simple Frame and overriding paint()? I found that adding a Panel in that case resulted in screen flicker when resizing so I avoided it for that reason.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

alexfromsun
Offline
Joined: 2005-09-05
Points: 0

Hello qu0ll

I am not sure about awt.Frame and awt.Panel
because I don't use them and actually don't see any reason
to use them instead of Swing components

Try to use JFrame and add JPanel with overridden paintComponent(g)
with your custom painting and it must work fine

Thanks
alexp

swv
Offline
Joined: 2007-05-28
Points: 0

If you tell me how to post code as HTML (which doesn't work ) I will give you a working version of your code.

qu0ll
Offline
Joined: 2006-12-09
Points: 0

Hi swv,

I am not sure I understand your request but I think you are referring to the use of

[ code ]
code goes here
[ /code ]

without the spaces before and after the brackets.

Is that what you meant? By the way, I am not using a Panel in this example because it results in flicker when resizing.

--
And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

swv
Offline
Joined: 2007-05-28
Points: 0

YEs I am hoping that will do it as far as posting code goes

OK I noticed you're using AWT and not Swing. Frame and not JFrame etc.... which is fine, just noticed it that's all.

Anyway, here is a Frame that invokes paint when it's downsized and tells you so in a println with a number so you know it's being invoked again..

[ code ]
import javax.swing.JFrame;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;

public class StartWithThis
{
MyFrame mainFrame;

public static void main(String args[])
{

StartWithThis name = new StartWithThis();
name.doit();

}

public void doit()
{
createComponents();
displayGUI();

}

private void createComponents()
{
mainFrame = new MyFrame();
//mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

private void displayGUI()
{
mainFrame.setSize(new Dimension(800, 800));
mainFrame.setVisible(true);

}

private class MyFrame extends Frame
{
private int number;

public void paint(final Graphics g)
{
super.paint(g);
System.out.println("StartWithThis$MyFrame.paint" + number++);

}

}

}

[ /code ]