OK, I'm trying to explain what I want to achieve in another way. Here's an example:
Say if it's an anti virus program, and user can choose between two ways to run the program, choice one, automatically start to scan disks for virus when the program starts up, choice two, hit the start button to make the program scan disks for virus after the program starts up any time the user wants. So, as a wxpython beginner, I know how to bind wx.EVT_BUTTON to let scanning start after the user hit the start button, but I don't know how to make the scanning start once the program starts up. I wonder if there's a program_start event I can bind? Hope you guys can help me out. Thanks!
In wxPython you can override the OnInit method of your Application class to run code when the program launches. For example:
def OnInit(self):
# Check for a running instance for this user. Do not instantiate if found.
if self.checkInstance():
dbcon.cursor().callproc('post_mutex', (self.mutexname,))
dbcon.commit()
self.Cleanup()
return False
# Register for database events.
DataCache['dbListener'] = dbListener()
return True
There is of course another method on my Application class called checkInstance. Depending on it's return value, my application either launches, or triggers the other running instance to launch.
In wxPython you don't have to do anything special with your App class to get the binding to take place for your OnInit method. It'll happen automatically if you override it.
Why don't you run it just in module code? This way it will be run only once, because code in module is run only once per program instance.
In your init or OnInit method, do some kind of check to see if the program should run the startup process on startup (i.e. check a config file or some such). If yes, call the "scan" method using wx.CallAfter or wx.CallLater or call it after you Show() the frame.
Related
I've got an interface where there is a 'Start' button. It runs a 'main' command where it starts a loop to run some measurements on a powermeter. I want to be able to click on an 'OK' button every time the measure is ready to be done. This button would replace the 'Start' button.
But when I try to destroy the button (buttonStart.destroy()) and then run the command main()
, the command executes but doesn't delete the button until the very end.
I've tried using threads from threading package, but it doesn't really work.
If there is a way to both destroy the button and run a command, I would be very interested !
Thanks a lot
The event loop must be given the opportunity to process events in order for the window to be removed from the screen.
There are a couple of ways to make that happen. The first is to call the update_idletasks method on any widget. That is usually enough to process the event related to the destruction of the widget, though it may be necessary to call update instead. Calling update should be avoided if at all possible. My rule of thumb is to start with update_idletasks. If that doesn't work, switch to update or switch to using after.
def my_custom_function():
startButton.destroy()
root.upddate_idletasks()
main()
The second method is to run your main function via after or after_idle. This will let tkinter naturally process all pending events before starting main. I would argue that this is the best approach. I recommend trying after_idle first, and if that doesn't work, switch to after with a small delay.
def my_custom_function():
startButton.destroy()
root.after_idle(main)
I want a Maya camera orbiting a mesh while user chooses what to do with that mesh on my own script interface.
So i have a while orbiting the camera, but no way to interact with user interface while this happens.
There is anyway to "share", or part the focus in second's decims to be able to interact with user interface?
I tried with cmds.evaldeferred(), but no luck...
Technically, Maya widgets interface is immediately available when script finishes the job...
I'm trying to finish the job with one single camera little orbit, and relaunch it with mouse movement event... Time changing event... But no way how to do that... Would be like a daemon running in the background... No idea how I could reach something like that....
Some code:
import maya.cmds as cmds
#declares global variable
global orbitCam
#just something to see in the scene
cmds.polyCube()
#function to stop camera orbit
def stopOrbiting():
global orbitCam
orbitCam = False
#simplest ui
cmds.window("testWindow")
cmds.formlayout("flo", parent="testWindow")
#button that calls stopOrbit function
cmds.button("pushMeIfYouCan", parent="flo", label="pushMeIfYouCan", c="stopOrbiting()")
cmds.showWindow("testWindow")
#condition for the while
orbitCam=True
#while itself
while orbitCam:
cmds.orbit("persp", ra=(0.2,0.1))
Any way to be able to push the button -and interact with widgets- while camera orbits?
Well, based on solution provided by mhlester in the link I posted under the question (and considering a great answer too by theodox, as a wonderful alternative, thank you both, guys), I'm gonna aswer my own question and provide another new detailed explanation perhaps can help somebody in the future.
First of all, Maya's "scriptjob" command utility puts in memory a script (or a function), haves a trigger to start executing that function, and the condition to Maya to execute that function once registered and triggered, is that Maya must to be doing exactly nothing, so, Maya must be idle.
Being that way, Maya never collapses or crashes or hangs by a scriptJob. ScriptJob is basically a... kind of "daemon" working in the background.
The good thing, is that is possible to limit the maximum number of times per second, so you can even maintain your system fresh and working if you want to care it about.
Once a scriptJob is launched (or registered in Maya memory), it can be killed to never runs again, and obviously, can be registered again if we want to start working again.
Exists an internal scriptJobs list inside of Maya, where you can find the scriptjob if you have forgotten to store that scriptJob in a variable, where you can find the "scriptJob ID", just an integer number you can use to kill the job.
After the first theory, let's see some code now:
This line will register a new daemon (maya scriptjob), its reference will be stored in "activeDaemon" variable, it will call a function called "camDaemon" with some arguments:
activeDaemon = registerDaemon(0.04, BackgroundFunction, ArgumentsForBackgroundFunction)
The point here is not just launch the daemon with conditions, besides, to store the daemon id to be able to kill it with:
cmds.scriptJob(kill=activeDaemon)
If we forgotten to store the daemon (scriptjob) id, we can use this command to watch a list with all scriptJobs of Maya:
cmds.scriptJob(listJobs=True)
We would need to find the last ids in the list with the event "idle", and probably we could hit and finished stopping our daemon killing it.
Now let's see "registerDaemon" function (all the absolute credit for MhLester):
def registerDaemon(seconds, backgroundFunction, *args, **kwargs):
def updateNow():
now = time.time()
if now - updateNow.then > seconds:
updateNow.then = now
backgroundFunction(*args, **kwargs)
updateNow.then = time.time()
return cmds.scriptJob(event=("idle", updateNow))
registerDaemon defines an internal function (updateNow) that calls "automatically" at the backgroundFunction we pass as argument, including this "backgroundFunction" arguments. Just that. A function A that defines a function B that calls a function C. And it calls it every quantity of seconds we specify at register the daemon with the first argument, so if we want it executed 25 times per second, 1seg/25fps = 0.04 would be the right value.
To have this function working, we must import the module time in our script with:
import time
Finally it returns the scriptJob id at the same time it registers it in Maya memory, registering with the event "idle" and with the function (B) that calls the function (C) we really want executed in the background. This way we can control the temperatures of the machine not overwhelming the cpu unnecessary. Very complete last line, brilliant, at least, for me.
At this point no other thing left than just register the function we want to have running the background in the Maya memory (take the code you want in the background, put inside a function and execute it one time in Script Editor)
def backgroundFunction():
print "this message shows in idle time by a daemon (Maya scriptjob)"
Of course there are much more in the documentation (Maya scriptJob documentation), as a list of events or conditions, but the base is this.
I am building an app that, when the user hits a 'run' button, generates a table of buttons.
Because this process takes a while, I want to add a popup or progress bar to alert the user that the function is running and not frozen. To do this I decided to create a popup and call my function using threading so that the screen will be updated when the function starts (as opposed to once it is done).
mythread = threading.Thread(target=run_function)
mythread.start()
The trouble is that when I call my function from the above code it works very strangely: the columns of my table are the wrong width, some of my buttons are arbitrarily empty, and others have the wrong fill color. To fix this, all I need to do is to remove the threading operation and simply call run_function()
Any idea why this is happening?
I am new to Python, so it is likely some dumb mistake, but I have no idea. What is different between a process running as a thread and its default operation?
Disclaimer: I haven't worked with Kivy.
Not every framework works well with multithreading.
But most of the GUI frameworks have an event loop which is responsible for managing user events (mouse clicks, keyboard) and queued drawing operations (widgets).
In your case if don't want the UI to be freezed, you should regularly give control to your framework's event loop.
I guess kivy.base.EventLoopBase.dispatch_input is what you need to call to show an added widget or to handle user events.
I'm attempting to transition a program from tkinter to Kivy. When I got to a section where I used messagebox.askyesno, I figured that I could just create a popup with a couple of buttons, and I'd be done. The issue I've encountered is that, while Kivy's popup and tkinter's messagebox are both modal, when I call messagebox.askyesno in a function, messagebox will halt all execution of the current function until the messagebox is destroyed, while the popup will allow the function to finish. My original program had
flag = messagebox.askyesno(message='...',parent=self)
if flag:
#Stuff if flag is true
else:
#Stuff if flag is false
However, this will not work with a Kivy popup since the popup will open, and the program will continue to execute. Is there a way to halt execution until the popup has been destroyed, or another way to solve the problem?
The basic idea is a quasi-dialog for a two player game. Here, the program asks one player if he wants to perform an action, such as move a piece. If the player says "yes," then the second player is given a messagebox.askyesno for a counter-move. A simple analogy is advancing a runner from first base to third base on a single in baseball. You would have to ask the offensive team if he wants to advance the runner, or have the runner remain at second. If the answer is yes, then the program would have to ask the defensive team if he wants to throw to third. It would definitely be possible to create a function to handle each instance of askyesno, with appropriate bindings, but it seems excessive.
I'm not very familiar with how tkinter does things, but kivy requires a slightly different mental model here. You don't want to stop and start the eventloop in between bits of python code, but instead probably want to start the popup, pass any state you need into it or store it somewhere else, then bind the result of the popup (e.g. when the user presses a 'done' button) to some new function that does the rest of your calculation.
I can provide an example if you like, especially if you give more information about what you're trying to do.
Here is my dilemma: I have a log parser with a pygtk window. After the user opens a file via the dialog, I have a progress bar showing them approximately when the open will be complete (as it can be a lengthy process). I recently added an option to allow the user to specify a file via the command line.
My problem is, since I have to load the file before calling gtk.main(). Thus, the window and, more importantly, the progress bar are not displayed until after this lengthy load completes, giving the user no indication.
So, I am hoping there is a way to execute a function after calling gtk.main(), or somebody has an alternative approach. Thanks
Rather than beginning the process from the command line as soon as you parse the command line arguments, simply pass the command line argument to your application class (or store in a variable) and process it AFTER you've entered gtk.main. That way you can setup your GUI first. Before beginning the process, and every time you increment the progress bar, make sure you let Gtk catch up using something like:
while Gtk.events_pending():
Gtk.main_iteration()