Using Canvas object

HeLLo! :slight_smile:

I made a simple graphic editor (grid/tile), and I was previously using a JPanel object to draw on. Now that I use this editor as my game editor, I need performances. So I read some advices on bufferStrategy and made out that JPanel does not allow buffer strategies… GnGnGnGn Solution : using a similar component to draw on --> Canvas. Am I right? Is everybody using Canvas object to render 2D games?

My problem is that when I have a menu bar just above my Canvas (using a double buffering strat’), the Canvas render CUTs the menu when expanded… Is there a superposition tip whith Swing components? Do anybody use menus in there games?

I am using a Canvas object along with a BufferStrategy for a little side scroller that runs in window mode only. However, like you, I found that menus were cut off, I’m guessing because the BufferStrategy drawing no longer lives in the realm of normal 2D drawing. My solution was to resort to buttons instead of a menu. Then, of course, the tooltips were cut off at which point I subclassed the JTooltip class and hooked it into my BufferStrategy. I suspect you could do the same with menus, derive a class from JMenu and override the appropriate paint methods. I’ll play around with adding menus to my scroller and post if I discover anything else.

On a side note, I’ve noticed that Canvas doesn’t seem to perform very well with multiple video cards/monitors. Haven’t been able to pin down exactly why yet, but that about the only big obstacle I’ve found with Canvas so far.

I think this is to do with heavyweight vs lightweight components. I think alot of the Swing components have an option to set whether their rendering in one way or the other.

Kev

You can set the system to use heavyweight pop-ups which fixes the cut-off problems on menus and tooltips

JPopupMenu.setDefaultLightWeightPopupEnabled( false );

I wouldn’t have recognized that cause or thought of that solution. Thanks to you both for pointing me in the right direction. It saved me alot of time! :slight_smile:

swpalmer,

First, thanx for your help. I tried to use the method you indicated but...... it doesn't work :-/  Note that I use JMenuBar / JMenu / JMenuItem in my code, not JPopupMenu. I guess there's no very difference between the concepts but perhaps these components are not managed in the same way. Do you see where the problem's coming from else?

(I’ve a screenshot of my application running -with the menu, cut when expanded over the canvas- but I have no personal server to put it on so you can see the bug)

Cheers! ;D

If you’re not really stuck to Swing, you could try AWT instead, I think they all have native peers and hence should be heavyweight.

Kev

[quote]swpalmer,

First, thanx for your help. I tried to use the method you indicated but...... it doesn't work :-/  Note that I use JMenuBar / JMenu / JMenuItem in my code, not JPopupMenu. I guess there's no very difference between the concepts but perhaps these components are not managed in the same way. Do you see where the problem's coming from else?

(I’ve a screenshot of my application running -with the menu, cut when expanded over the canvas- but I have no personal server to put it on so you can see the bug)

Cheers! ;D
[/quote]
I doubt this is the problem, but it has the same symptom…

I’ve seen the same problem before from a student’s project, where he had made his program multi-threaded by overriding the AWT update method to do all his own “updates”. He had no idea how to start a Thread / Runnable, but had managed to make an MT program this way :).

Very cunning, completely inadvertent - and of course he had no idea what was going on :(. One of the side effects was that everytime that re-painting was done by AWT for the Frame, he was overpainting with his own code. So the menus all got cut off (you could see them flick on very briefly before they were cut off).

Perhaps you are having a similar problem - check HOW, WHEN and WHY your paint() code gets invoked (nb: this is non-trivial. It can take quite a long time. My suggestion is to use the following little trick to find out:


// Stick this anywhere in your code when you want to find out where it's being called from
try
{
  String a = null;
  a.toString();
}
catch( Exception e )
{
  // Wouldn't it be lovely if printStackTrace were accessible from Thread?
  // ...surely that would be the correct place for it to live - NOT in Exception?
  // Anyway, this works:
  System.out.println( e.printStackTrace() );
}

Once you’ve worked that out, check the Swing (and/or AWT) docs for the methods involved and make sure you are not accidentally abusing the spec.

I normally go for just:



new Exception("I need a trace").printStackTrace();


Kev

[quote]I normally go for just:



new Exception("I need a trace").printStackTrace();


[/quote]
Indeed; much better. It’s been a while since I’ve needed it, and I wasn’t sure whether you had to “throw” it in order to generate the stack-trace; in fact, IMHO, it should NOT generate the stack trace in the constructor (as it appears to), but should be lazy.

I suppose the verbose way I suggested might have a small advantage in that you see it in a source file and immediately think “WTF???! Do I want this?” - which is probably the correct reaction, since you probably shouldn’t be leaving that kind of thing lying around :slight_smile:

::slight_smile: Dear professor,

I tried to repaint my menu components one by one at just after my bufferStrategy.show() invokation but there's nothing new, it is still cut by my canvas. About the spy suggestion : I only override the Canvas.paint() method, and did not touch the MenuComponent's, so I guess that re-draw them just after the canvas would overlay them to the front... But... Hem... Doesn't work ;)

[quote]If you’re not really stuck to Swing, you could try AWT instead, I think they all have native peers and hence should be heavyweight.

Kev
[/quote]
I want to use Swing ('cause I love toolTips ;D)

TigRoO°

[quote]Note that I use JMenuBar / JMenu / JMenuItem in my code, not JPopupMenu. I guess there’s no very difference between the concepts but perhaps these components are not managed in the same way. Do you see where the problem’s coming from else?
[/quote]
That JPopup method does set a global flag that is used for all popups - regular menus and tool tips included. At least it worked that way in my application.

I still believe this is caused by the mixing of heavyweights with lightweights… I would read what Sun’s Java pages have to say about this…

http://java.sun.com/products/jfc/tsc/articles/mixing/index.html

In particular are you doing the JPopup call before instantiating your menu objects? As mentioned in this paragraph:
"If you place Swing popup components in a window containing heavyweight components and it’s possible that the popup windows will intersect a heavyweight, then invoke

JPopupMenu.setDefaultLightWeightPopupEnabled(false)

before the popup components are instantiated."

I bet you simply have to move that code so it is called before you construct your menus.

Blah,
Note that you can probably also re-use a single Throwable and explicitly call fillInStackTrace() as needed. The reason that all constructors call fillInStackTrace is that there is no method called to do this work at any other suitable time. Unless they change the language so that ‘throw’ automatically calls fillInStackTrace on the Throwable prior to throwing… but then that might not be what you want and it would complicate re-throwing exceptions etc.

Yeah, U got it :smiley: Thanx a lot!

I’m going to catch a headache reading your stuff on expection (even more that I am French!). Spying is so simple with a System.out.print… :wink:

But I’ll read this all soon. Not yet, 'cause I’m making test on my PathFinder ::slight_smile:

Perhaps that I will give a little project soon to the community :slight_smile:

Do u already have a existing game which draws the tiles for you ?

If the answer is yes, why dont u use your app as editor ?

I have a WorldEditor which is plugged into the real game, but its your decision.

Hmm, interesting…in what situation might that not be what you want?

My only reason against the constructor-based filling in is that I really really don’t like heavyweight constructors. I wouldn’t mind so much if Sun had documented them, but there are quite a lot of constructors in the standard libraries that take - in some cases - as much as 100 (or more!) times as long to execute as the average. This makes development much more difficult than it should be :(. (although I think some of them are gradually being removed, thank goodness).

Over the years I’ve found heavy constructors tend to be more trouble than they’re worth - in the long run, with any complex app, sooner or later you nearly always find you’d prefer to be able to do a two-stage init:

  1. allocate memory, perform any essential but lightweight init
  2. perform any heavyweight or multiple-code-path init

The first would be the constructor, the second is an “init()” method or similar. In practice, the current encouragement to do everything in the constructor is anti-OOP - you end up with a lot of unnecessary code duplication.

Even worse, the compiler / JLS is broken (IMHO) w.r.t. constructor delegation semantics:

“If you wish to delegate to another constructor, the delegation MUST be the first line of your constructor”…
…but that “first line” can contain any number of nested method calls etc (e.g. instantiation of objects etc). If you move them out of being nested in the first line, to the line above, the compiler says “no way” although - at a compilation level - AFAICS there is absolutely no change in the code produced. There is certainly no semantic change, other than that you generate additional references (assuming you wish to use your newly-instantiated objects in the delegation command).</rant :)>

Well it was re-throwing that made me say that… but I guess that could be handled by not filling in the stack trace if it was already filled in.

But then, why would you want to construct a Throwable if you didn’t intend to get the stack trace or throw it?

Re: delegating to other constructors on the first line only… yeah that is just odd.

Why not use Thread.dumpStack()? It’s designed exactly for what you seem to need…

[quote]Do u already have a existing game which draws the tiles for you ?

If the answer is yes, why dont u use your app as editor ?

I have a WorldEditor which is plugged into the real game, but its your decision.
[/quote]
My work :

I designed a World object, that is composed of tiles, each of them able to contain an entity (or more if they are "crossable"). Entity is the generic object for an... entity (:)) living in the world. They can be Tree or Actor for the moment. Tree is a simply not-crossable sprite and Actors are the default intelligent entities. (I am coding a bit of AI to embed Entities). Leading the whole of this, Game is the master class, managing Players. Each of them has a vision on the real World, this latter ruled by a super player : MasterOfPuppets (= "Mother Nature" ;)).  And other stuff but this Thread has not been dedicated to my work yet ;)

My editor is mostly my developpment tool because I have no effective game ready. Actually, I take back my end-of-study school work that was nearly a strategy game (economy simulation) coded with a friend, with no time... So I rework the entire program to make a GREAT API  8)

I'd like to use an existing editor but mine rely on my own World architecture (as yours I guess) so it would be another work amount to lead on my work to maturity. But I thank you :) 

If some are interrested in seeing my work, ask me! ;)

Cooo, now I look like a proper idiot :slight_smile: Thanks for the info tho, when did that turn up?

Kev

[quote]Why not use Thread.dumpStack()? It’s designed exactly for what you seem to need…
[/quote]
Because that’s what they’d EXPECT us to do!

Or actually just because I’m an idiot ;).

I think I failed to find it on previous occasions because:

  1. it won’t show up when you do a search for “printstacktrace” - and I use the full-text-indexed versions of the API docs whenever possible, e.g. the windows help file versions. So I usually search for stuff.
  2. …if/when I did find it, it would have been in the pre-1.4 days, and I would probably have dismissed it because it still didn’t let me print the stack trace to an arbitrary stream - making it useless in lots of situations. I believe this is what’s called a “blind spot”? i.e. you completely fail to make a logical connection between two things that’s staring you in the face (in this case “no, it doesn’t print to stream…but it would let me avoid faffing with Exceptions just to get a stack trace”).

Chuckle.