We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hello everyone!
I'm quite new at processing and I'm having an issue with closing windows and the G4P Tool. I've created a main window from where I want to choose a set of parameters to configure (checkbox). So far, I've managed to create the main window and the other windows for parameter configuration. This other set of windows is closing when I press the X button (Windows OS close). But I can't seem to keep that behavior going. If I try to repeat the close action, after opening and closing a first time, the window.setActionOnClose(window.CLOSE_WINDOW) doesn't work anymore. I was thinking that the best option would be to create the second window set only after making the selection on the main window but fiddling with the createGUI() function is not an option (every change on the GUI Builder will revert my changes) I've attached the files here: http://we.tl/ejQjB64Gmr
Can anyone help? Thanks!
Answers
The problem with using the X button (Windows) to close the configuration windows is that G4P will attempt to release the resources allocated to the window, so if you attempt to re-use a closed wIndow the results will be unpredictable. This is true no matter how the window was closed.
If you have a program with a window that you only want to use now-and-again, then leave the window close action as
KEEP_OPEN
and simply change the windows visibility. You can later use theforceClose()
method when the window is no longer required, but once closed - DO NOT ATTEMPT TO USE IT AGAIN.GUI Builder makes it quite clear in the gui.tab that the only safe place to place your own code is inside the event handlers.
GUI Builder cannot be used to set every single option available in G4P, but it is safe to tweak GUI created, but only AFTER the call to
createGUI()
PS I have moved this the the 'Questions about Libraries' section
quark,
Thank you! I'll work on trying to make my application resemble a configuration wizard and I may comeback to this topic to ask for help.
Any thoughts on how to display real-time collected data on a graph?
Not sure what you mean by the same frame.
GWindow is a sub class of java.awt.Frame so any methods for that class also apply to GWindows i.e.
void setLocation(int x, int y);
Point getLocation();
If your sketch is executed as an application (i.e. run in Java mode) then it will open the main sketch window. In that case you can use the frame attribute to get the sketch window location.
Try out the code below.
Please do not edit your posts once you get a reply.
It can get very confusing for readers trying to follow the topic, also members' replies can appear to have no relevance to the questions because the questions have disappeared.
ALWAYS add a new post to the topic unless you are correcting a simple typo.
You might look at the 'graphica' library.
quark,
Thank you once again! My apologies for changing the post. Your help is much appreciated! I've downloaded the graphica library but I don't know how to integrate it with the G4P tool (I need to place a real-time graph somewhere on a G4P window). Should I use a sketchpad or floating panel object and then associate that with a function that creates the graph?
You can't use graphica (or any other library) from inside the GUI Builder tool but most libraries work alongside the G4P library.
Forget that it won't work. Graphica was developed as an independent library and has to draw directly onto a PApplet surface.
Every GWindow contains its own PApplet object, and this is what you use to draw inside the GWindow.
I have modified the MultiplePlots example from graphics to include a GWindow (created with the GUI Builder tool). In the modified example the plots are drawn into the GWindow (variable name
graphicaWindow
). Apart from including G4P and creating the GWindow code the only changes areEach of the 4 plots were created with a statement like
plot1 = new GPlot(this);
where this is the main sketch PApplet object, is replaced with a statement like this
plot1 = new GPlot(graphicaWindow.papplet);
I also created a new method called drawPlots() and removed the plot drawing code from the draw() method and placed in in this new method. Finally I called the 'drawPlots()' from the draw handler for the GWindow
graphicaWindow
.You can download this example from here
Hello once again,
quark, my apologies for not thanking you for your help. I did not resume my work until now for several reasons. So, thank you so much for your help. I'm here to ask for it again. To you or to anyone who can help. I'm trying to draw a plot on a window which is not the main. Code here. I can't seem to make the plot appear on the second window, even though the other two (on the main window) are working just fine. What I'm a doing wrong?
The problem is fixed you can download my solution sketch as an archived (zip) file here
The main difference is that the call to
plot.defaultDraw()
is done from the appropriate draw() method.Thank you for your help once more quark. The thing is that when I use serial port data, I get "Exception in event handles" warnings and I'm afraid that will get me to memory overflow errors (which I've had in the past, when trying to implent other solutions). Also, I don't want to draw the plots with the draw method (and hence the set framerate), just when I have new data available at the serial port. Each graph may need to be updated at a different time (and that's why I was thinking about using the serial port function to update the plots, not the draw methods).
There are two things here
1) Update the plots (add / remove points)
2) Draw the graph
Now the draw() method should be responsible for (2) so keep my draw methods as is.
The serial event handler should be responsible for (1) but not (2) so remove the three calls to plot.defaultDraw() from the serialEvent method.
Let us know if it helps.
I see. That puts things in a new perspective (for me at least). But, unfortunately, that didn't solve the errors. They seem to be tied to the secondary window:
########## EXCEPTION IN EVENT HANDLER
An error occured during execution of the eventhandler: CLASS: serie_pH METHOD: win_draw1
It took me a while but I have the solution.
The problem is caused because win_draw1 is being called before the setup method is complete i.e. before plotpH is created. This might appear to be an impossibility but as soon as you realise that GWindow is effectively a secondary sketch executing in its own thread it is entirely possible.
There are 2 possible solutions, this is the simpler one.
quark,
Thank you so much. It makes sense. I'm still learning the basics with processing, your help is very much appreciated. I've implemented your suggestion and everything works smoothly! Can you still present the other solution? I'm interested in learning about other possible solutions!
It's just my guess, but I think the most performant solution is stall the sketch in setup() via a loop until the other threads are completely initialized (non-
null
). O:-)The other solution is also quite simple made slightly more difficult because you are using GUI Builder
Start your sketch and launch GUI Builder (GB). In GB click on the second window and in the property grid delete the entry for the draw method name. When you go back to the PDE the code in GUI tab will have changed and the window draw method will have disappeared.
NOW in the main sketch pde (not the gui tab)
Put this as the last line in setup
and add the method
You will no longer need to test the value of plotpH because the plot is created BEFORE the draw handler is added to the window.
@quark, would
synchronized
still be needed after that? How many threads'd be invoking it after all? :-/@GoToLoop Good question.
Multiple windows first appeared in G4P in June 2009, can't remember if it was Processing 1.2.1 or 1.5.1 but it soon became apparent that in many situations there was flickering of the displays, particularly in the second window but sometimes also the main sketch display. The solution was using
synchronized
on the GWindow draw method.In the early alpha releases of Processing 2 the developers changed the event handling model of Processing dramatically and several libraries found themselves on the wrong side of the fence, G4P was one of them. I had to modify the library so I took the opportunity of a complete refactoring of G4P event system and in particular how GWindows were managed.
I still think it might be needed since the method is being called from another thread and Processing does not provide much support or information about managing concurrent access violations.
GUI Builder adds the
synchronised
keyword by default because it has no measurable affect on the frame rate and is the 'safe' option. It also saves me posting 'try adding synchronised' everytime someone gets a bit of flicker.AFAIK, what determines whether a method (or a portion of it) should be
synchronized
is when more than 1 diff. Thread can potentially invoke it!A method declared as
synchronized
locks up on some particularthis
instance of its class.In this case,
this
is the sketch's reference and win_draw1() is a callback for some GWindow instance.As long as win_draw1() is registered to 1 GWindow instance only,
synchronized
is redundant.However, if more than 1 GWindow has that very same callback registered too, we gotta put
synchronized
back!As I understand it, each GWindow instance got its own Thread, is that so? <):)
Each GWindow is an instance of java.awt.Frame
Each GWindow has a GWinApplet object embedded.
GWinApplet extends PApplet so effectively each GWindow is a Processing sketch.
Now the GWinApplet has the following methods -
but they cannot be modified by the library user but we want each GWindow to be able to do 'display its own thing'.
So each of these methods can invoke a method registered with GWindow hence
window1.addDrawHandler(this, "win_draw1");
This method is actually inside the main thread PApplet. It means that it can interfere / be affected by the main draw() method (when executed at the same time), also there is a risk of other concurrent access violations.
I discovered that
synchronized
solved some difficult issues in the past and since it appears to have no noticeable effect on performance I am not worried if it is redundant.I suspect that you are right and that it may no longer be needed (G4P event and windows management system was completely overhauled with Process V2). Perhaps when I have time I will look into it more deeply but I have many other more challenging projects on the go to worry about it at the moment. :)
The main draw() is run by the sketch's "Animation Thread". And whether a programmer stupidly calls a reserved callback from draw() is another subject entirely!
The matter is again how many unique threads are "supposed" to invoke some particular registered callback!
In other words, is that callback "shared" by other threads? :>
If the answer is not, then
synchronized
is redundant and just slows down the callback! :-&Although
synchronized
by itself has indeed very little performance impact, the lock/monitor/mutex chosen for it can make an app even slow to a crawl! :-SWhen a whole method is declared
synchronized
, its lock is implicitlythis
.Any other
synchronized
method belonging to thatthis
instance automatically shares that lock!Let's say we've got 3 GWindow instances, and each 1 got its own
synchronized
callback method(s).B/c those methods share the same lock, when 1 callback is being run, the other GWindow instances gotta w8,
even though they've got individual registered callbacks and don't share them! b-(
It's obvious that synchronizing w/ a shared reference creates unnecessary contention and slowness! :-B
But w8! It's gonna get worse now! After perusing the PApplet, I've found out some other
synchronized
methods there too!There aren't many, and actually most of them are circumstantial methods like redraw(), loop() & noLoop()!
Unfortunately, there's a very nasty & important 1:
protected synchronized void render() {}
!Yup! The 1 responsible to render the canvas after draw()! [..]
It means that when any other
synchronized
method is busy, the "Animation Thread" gotta w8 for it before entering render(), slowing down the main sketch!Likewise, once render() is being run, no other
synchronized
method locked on the sketch'sthis
can run!I believe by now you understand how cheap
synchronized
methods are a bad lazy idea! 8-XIf you really need to lock a method, you should use the
synchronized
block version w/ another unique reference!But only if you fear that win_draw1() is potentially being invoked by other GWindow threads! >-)
@GoToLoop Thanks for your research I will look at the options when I get a chance. It is possible for GWindows to share the same draw method, this is done in the Mandelbrot example where every generated window shares the same draw method but have their own
appc
anddata
objects.@quark, @GoToLoop,
Here I am again with another question. My interface is flowing nicely but now I need to plot a graph with two vertical axis, one at right and the other at left. Basically, points with one x and two y. I'm using the grafica library. My thought was to build two plots, each with the same x and two different sets of y values. I was thinking of drawing the plots on top of each other and enabling the right axis on one of them. Unfortunately, I've only been able to display the vertical line of the axis, not the values of it. I've looked into the GAxis and GPlot classes. Both mention the right axis but the GAxis seems to address its representation. I've noticed, tough, that the GAxis class refers to the PApplet itselft...I'm puzzled and can't seem to figure out the solution to my problem. Can you help?
@PetePT
This question is very different from the topic title (G4P closing windows) and is in fact it is about using the graphica library. I suggest that you start a new topic for this and make sure you have the name of the library in the title.
It is not surprising that GAxis refers to PApplet since a sketch is a PApplet object and gives access to all the drawing commands.
Hello, you can repair the link, I am working with multiple windows by G4P and graphica and that example would help me a lot, thank you very much.
That post is over a year old and I no longer have that file. Sorry :(
Also G4P has been changed for Processing 3 and the latest version is not backwardly compatible. I am not sure whether graphica works with PS2 but its API has changed since I first used it.