PsychoPy reopen window - python

I programmed a dot probe paradigm using the Standalone PsychoPy v1.80.03. After the dot probe I need a modified task that looks identical to the dot probe. I therefore pass the dot probe object in the 2nd task's constructor to re-use the window and the stimulus containers bound to this window.
Before the 2nd task starts I, however, need to input some information (e.g. the condition) using a gui.DlgFromDict. With the window from the dot probe still in fullscreen, the Dialog Box cannot be reached.
I tried to change the fullscreen to false by dotProbe.window.fullscr = False followed by a dotProbe.window.flip() but once the window is instantiated, changing this attribute doesn't seem to have an effect.
Closing the window with dotProbe.window.close() makes the Dialog accessible but there is no function that opens the window again to proceed in the 2nd task. Of course I could just construct a new window but as I said I need the identical setup with the stimuli at the exact same positions and all other parameters alike. Copying all parameters from one script to another to "manually" ensure them to look identical is undesired - as are workarounds like providing the input for the 2nd task prior to the dot probe since the scripts should be able be run independently (if no dot probe object is provided in the constructor, a new one is created to provide the default look).
Thanks for any help!

You don't want to close the window: that actually destroys the entire object, along with all of its stimuli and other attributes.
A solution to a similar problem was posted here: https://groups.google.com/forum/#!msg/psychopy-users/zq2E12vnYiI/6mXirJMlq3cJ
According to Jan Kramer there (and a subsequent improvement from jashubbard here: https://discourse.psychopy.org/t/bug-user-defined-gui-does-not-display-in-full-screen-on-mac-osx/2214/3), I think you want to use something like:
win.winHandle.minimize() # minimise the PsychoPy window
win.winHandle.set_fullscreen(False) # disable fullscreen
win.flip() # redraw the (minimised) window
This will hide the window away rather than closing it. Then restore it with:
win.winHandle.maximize()
win.winHandle.set_fullscreen(True)
win.winHandle.activate()
win.flip()

Related

Restart button for a tkinter tic-tac-toe [duplicate]

I just want the equivalent of closing and reopening my main program. I want to invoke it when a "new"-like option from a drop-down menu is clicked on. Something like calling root.destroy() and then re-initiating the mainloop.
How can I get this done?
There are at least three ways you can solve this.
Method one: the head fake. When you create your app, don't put all the widgets in the root window. Instead, hide the root window and create a new toplevel that represents your application. When you restart it's just a matter of destroying that new toplevel and re-running all your start-up logic.
Method two: nuke and pave. Similar in concept but slightly different in execution. In this model, when you want to restart you simply delete all the widgets in the main window, reset the geometry to null (so the window will once again resize itself based on its contents) and then run the logic that draws all the other widgets.
Method three: if it worked the first time... As suggested by Martin v. Löwis, simply have your program exec a new instance of the program, then exit.
The first two methods are potentially faster and have the (dis?)advantage of preserving the current environment. For example you could save the copy of the clipboard, column widths, etc. The third method absolutely guarantees a blank slate.
If you are on Unix, restart the entire application with os.execv. Make sure you pass all command line arguments etc.
You could take all your GUI building logic and initial state code out of the mainloop and put it into functions. Call these functions from the mainloop (something like: buildgui() & initstate()) and then, when the user clicks your menu icon, just call initstate() to set it back like it was when the application first started.

Difference between iconify() and withdraw() in Python Tkinter

I've been searching and not finding an answer as far as the differences of iconify() and withdraw() methods of Tkinter are concerned.
iconify() seems to "convert" the window to a taskbar icon and has a state of "iconic"
withdraw() seems to just remove the window from the screen, after which the window has a state of "withdrawn"
If you need to reverse the situation, you simply call deiconify() on both situations.
However, what is the real difference between the two methods and how do they essentially differ from one another?
Moreover, are they applied in different situations?
You've got it down correctly.
In more detail:
iconify() Turns the window into an icon (without destroying it). To redraw the window, use deiconify. Under Windows, the window will show up in the taskbar.
When the window has been iconified, the state method returns “iconic”.
withdraw() Removes the window from the screen (without destroying it). To redraw the window, use deiconify.
When the window has been withdrawn, the state method returns “withdrawn”.
Source: Tkinter -- Toplevel Window Methods
As far as use-cases go, you would normally use iconify() in situations where you want the user to be able to easily gain access to a window that was "minimized" (via iconify()) for whatever reason. For example, say a user clicks a button that "minimizes" a window and opens up a new one. Using iconify() lets the user do whatever they need to do in the new window and then return to the previous one easily since it appears to them as an icon.
On the other hand, withdraw() is useful to "hide" windows. For example, I have developed some applications that automatically created multiple windows on start-up of the application. If I had used iconify() the user would be aware of all the windows that had been created because they'd see them as icons. Imagine the shock of a user seeing 10 windows by simply starting up an application! Therefore, I used withdraw() so that each window would appear (via deiconify()) only if the user triggered the right event.

Strategy for managing long GUI construction times (wxPython)

I have a wxPython application with a multi-stage GUI. First a simple form pops for selecting from one of many (> 100) options (it's a part number list with a search box). Once the user has made their selection it builds the appropriate form and shows it, hiding the initial selection dialog. Due to the nature of this project, each secondary form has several matplotlib figures in a Notebook, around 7 or 8 figures each with 2-5 axes each. Because of this, the form takes several seconds between initialization and when it can be shown on the screen.
Does wxPython have a way to build a frame in the background? I don't mind forcing the user to wait a short while before it can be shown, but as it is right now building the form hogs the event loop and everything becomes unresponsive. If I use a thread to build the form, it completes successfully but when I call .Show() nothing happens and there's no error message.
As you can imagine, such a GUI has fairly complex code so it would be difficult to show a SSCCE (and it's not open source). If needed I can try to hack together something that would approximate my problem.
I have used BusyInfo before to tell the user that something is happening. You would put that in your frame's init() BEFORE you actually start creating the matplotlib figures. You can read about it here:
http://wiki.wxpython.org/BusyInfo
Another idea would be to create a second frame with a progressbar in it and a message. The progressbar would be set to just bounce back and forth and when you got done creating the matplot stuff, you would close the second frame.
Mike's idea of using wxBusyInfo is useful when something takes a long time, but it's possible you could make it take less time instead (or at least as well).
First, when inserting many (although I wouldn't say that 100 is that many, 1000 however definitely is) items into a wxChoice, freeze it before adding them -- and thaw it afterwards. This should cut down the time needed for the insertion drastically.
Second, creating all controls of a multi-page wxNotebook (or another wxBookCtrl) can be long, even in C++. So the idea is to not do it immediately but only create the controls of the page you are going to initially show to the user. And then create the other pages controls only when the user is about to select them, i.e. in your wxEVT_BOOKCTRL_PAGE_CHANGING event handler.
If you put this in place, you might not need wxBusyInfo any longer...

Why does the light_manager of MlabSceneModel not get set?

I am using Mayavi for a 3D visualization with TraitsUI. The scene is a trait of the type MlabSceneModel. I want to change the lighting and trying to access scene.light_manager in a function called on the activated event. However, scene.light_manager is always None.
Using mlab.figure() to creates a scene which has a light manager, but as I want the scene to be integrated in the UI and not in an additional window this is no option for me.
Good question which threw me for a loop at first.
Looking at the tvtk source, the light manager is added to the scene when the interactor is generated, which occurs after scene activation. Furthermore, the first thing I tried, which was to listen to 'scene:light_manager' doesn't work because the light manager is a Property trait that doesn't directly change. That said, if you listen to the object itself, which is referred to by the property, it will trigger a notification on creation. In other words, do this:
class Application(HasTraits):
scene=Instance(MlabSceneModel,())
...
#on_trait_change('scene:scene_editor:light_manager')
def muck_with_the_lights(self):
print self.scene.light_manager

Resetting the main GUI window

I just want the equivalent of closing and reopening my main program. I want to invoke it when a "new"-like option from a drop-down menu is clicked on. Something like calling root.destroy() and then re-initiating the mainloop.
How can I get this done?
There are at least three ways you can solve this.
Method one: the head fake. When you create your app, don't put all the widgets in the root window. Instead, hide the root window and create a new toplevel that represents your application. When you restart it's just a matter of destroying that new toplevel and re-running all your start-up logic.
Method two: nuke and pave. Similar in concept but slightly different in execution. In this model, when you want to restart you simply delete all the widgets in the main window, reset the geometry to null (so the window will once again resize itself based on its contents) and then run the logic that draws all the other widgets.
Method three: if it worked the first time... As suggested by Martin v. Löwis, simply have your program exec a new instance of the program, then exit.
The first two methods are potentially faster and have the (dis?)advantage of preserving the current environment. For example you could save the copy of the clipboard, column widths, etc. The third method absolutely guarantees a blank slate.
If you are on Unix, restart the entire application with os.execv. Make sure you pass all command line arguments etc.
You could take all your GUI building logic and initial state code out of the mainloop and put it into functions. Call these functions from the mainloop (something like: buildgui() & initstate()) and then, when the user clicks your menu icon, just call initstate() to set it back like it was when the application first started.

Categories

Resources