I am working on a Python program which performs various calculations. There are many different parameters that need to be inputed, and it can get confusing to remember what changes you made to the different inputs. I want to have a button that resets everything to their default values, so basically like restarting it, but without actually closing it/needing to run it again. I have used TraitsUI to design the GUI. How can I implement this ? I saw on the TraitsUI User manual that there is a reset command:
reset(destroy=True)
"Resets the contents of a user interface"
,but I don't actually know how and where to use this.
Here is a quick overview of how my code is formatted from start to end.
import os
os.environ['ETS_TOOLKIT'] = 'qt4'
os.environ['QT_API'] = 'pyqt'
from traits.api import HasTraits, Range, ...
...
class class1(HasTraits)
...
class class10(HasTraits)
mrm = class10()
mrm.configure_traits(kind='livemodal')
I have looked at this and this but they either didn't work or I just don't know to implement them properly in my program's layout. Looking forward to any advice/help.
I just read into this but look into reset_traits()
Try adding a "refresh" button to the GUI where
def _refresh_fired(self):
self.reset_traits()
This will reset all traits within your class. If you want to reset some of the traits, pass a list of strings along with it.
self.reset_traits(['trait1', 'trait2'])
Related
The title isnt very accurate i think
Here are my script at the right
Screenshot
It's a bot to automatize some actions. Now i want to add some gui to it but i dont know how.
Like you see at the left, i have " import questions" but cuz of it when I launch the tkinter file, it automatically launches the questions without taking my openBtn code into account.
How can I add gui to each command of my questions.py?
You need to break your questions.py script into actual functions . Python will simply execute all actions in questions.py when the namespace is imported before it reaches the logic below the import statements in testkinter.py.
So in questions.py remove your while True: statements in favor of function definitions like:
def check_database(param):
database check logic here
Then link the functions defined in questions.py to Tkinter button actions in testkinter.py like this:
w = tkinter.Button( fenetre, command=check_database )
I'm using the QUuid class in my project and for testing and debugging purposes it would be very nice to see the QUuid objects in human readable form instead of their low-level form.
For some reason, the people at Qt have not included a dump method for this type so I attempted to create one on my own, following this documentation and this guide.
I'm not familiar with Python so unfortunately, I could not get something running. Could someone help me create such a function that does nothing more than display the output of QUuid::toString() in the value column of Qt Creator?
Edit:
Mitko's solution worked perfectly. I expanded it a bit so the details can still be read if so desired:
from dumper import *
import gdb
def qdump__QUuid(d, value):
this_ = d.makeExpression(value)
finalValue = gdb.parse_and_eval("%s.toString()" % (this_))
d.putStringValue(finalValue)
d.putNumChild(4)
if d.isExpanded():
with Children(d):
d.putSubItem("data1", value["data1"])
d.putSubItem("data2", value["data2"])
d.putSubItem("data3", value["data3"])
d.putSubItem("data4", value["data4"])
The following python script should do the job:
from dumper import *
import gdb
def qdump__QUuid(d, value):
this = d.makeExpression(value)
stringValue = gdb.parse_and_eval("%s.toString()" % this)
d.putStringValue(stringValue)
d.putNumChild(0)
The easiest way to use it with Qt Creator is to just paste these lines at the end of your <Qt-Creator-Install-Dir>/share/qtcreator/debugger/personaltypes.py file. In this case you can skip the first line, as it's already in the file.
As the personaltypes.py file is overwritten when you update Qt Creator you might want to put the script above in its own file. In that case you'll need to configure Qt Creator to use your file. You can do this by going to Tools > Options... > Debugger > GDB > Extra Debugging Helpers > Browse and selecting your file.
Note:
This script will only work inside Qt Creator, since we use its specific dumper (e.g. putStringValue).
We call QUuid::toString() which creates a QString object. I'm not sure exactly how gdb and python handle this, and if there is a need to clean this up in order to avoid leaking memory. It's probably not a big deal for debugging, but something to be aware of.
I am creating a rig through scripting and I have a UI. I would like to connect multiple functions to one button. Or rather, have a function inside of a function. Any suggestions on how to go about this issue?
I am importing the following libraries:
import maya.cmds as cmds
from functools import partial
Could you explain further more what you to do with a little example ?
I see you want to use partial so you may have multiple variables to pass through ?
My first idea would to create a function grouping your multiples function, ie :
def temp01():
return cmds.ls(sl=True)
def connection(obj01, obj02):
someCommand(obj01, obj02)
def printor():
print('yeah it is working')
def uiCommandButton_whatShouldIDoFunc(obj02, specialOkay, *args):
someCommand(temp01(), obj02)
specialOkay() #should print message
button01 = cmds.button(c=partial( uiCommandButton_whatShouldIDoFunc, cmds.ls(sl=1)[-1]), printor )
To have things nice and clean, I would use handlers.
A handler is a method that is called when an event occurs on your GUI element, like click. In the handler you can do whatever you want to (like calling your two functions). Handlers/event handlers are a tried and test GUI programming technique.
Here is an example:
my_button = cmds.button(command=partial(my_button_on_click_handler, arg1, arg2))
def my_button_on_click_handler(arg1, arg2):
# call all your functions and do stuff here
my_other_func1(arg1)
my_other_func2(arg2)
Some great posts on this topic (courtesy: #theodox and his awesome blog):
http://techartsurvival.blogspot.ca/2014/04/maya-callbacks-cheat-sheet.html?m=1
http://techartsurvival.blogspot.ca/2014/04/the-main-event-event-oriented.html?m=1
There is a "dirty" way of doing so by using PyMel and PySide/Qt.
First, turn your button into Pymel button :
import pymel.core as pm
import pymel.core.uitypes as pui
pyBtn = pm.button(label="", etc...)
or
pyBtn = pui.PyUI(my_button)
Then, convert it to a QtObject:
qtBtn = pyBtn.asQtObject()
And finally, you can add functions when the button is clicked like that:
qtBtn.clicked.connect(func1)
qtBtn.clicked.connect(partial(func2, arg1))
etc...
But like I said, this is not really recommended... It's just another way of doing it.
I thought it might be interesting to share it.
As an example, you can use this solution if the UI already exists, but you can't access the code that creates it.
Otherwise, I would do like suggested in the other answers, creating handlers functions.
PS : This will only works with maya2014 and above, or a maya with PyQt installed !
I'm just finding out now that when importing a module, it seems to run through ALL the code, instead of just the one function that I want it to go through. I've been trying to find a way around this, but can't seem to get it. Here is what is happening.
#mainfile.py
from elsewhere import something_else
number = 0
def main():
print('What do you want to do? 1 - something else')
donow = input()
if donow == '1':
something_else()
while 1:
main()
#elsewhere.py
print('I dont know why this prints')
def something_else():
from mainfile import number
print('the variable number is',number)
Now, although this code KIND OF works the way I want it to, the first time when I initiate it, it will go to the main menu twice. For example: I start the program, press one, then it asks me what I want to do again. If I press one again, then it will print "the variable number is 0".
Once I get this working, I would like to be importing a lot of variables back and forth. The only issue is,if I add more import statements to "elsewhere.py" I think it will just initiate the program more and more. If I put "from mainfile import number" on line 1 of "elsewhere.py", I think this raises an error. Are there any workarounds to this? Can I make a different file? What if I made a class to store variables, if that is possible? I'm very new to programming, I would appreciate it if answers are easy to read for beginners. Thank you for the help.
As Jan notes, that's what import does. When you run import, it runs all of the code in the module. You might think: no it doesn't! What about the code inside something_else? That doesn't get run! Right, when the def statement is executed it creates a new function, but it doesn't run it. Basically, it saves the code for later.
The solution is that pretty much all interesting code should be in a function. There are a few cases which make sense to put at the top-level, but if in doubt, put it inside a function. In your particular case, you shouldn't be printing at the top level, if you need to print for some reason, put that into a function and call it when you need it. If you care when something happens, put it in a function.
On a second node, don't import your primary script in other scripts. I.e. if your mainfile.py directly, don't import that in other files. You can but it produces confusing results, and its really best to pretend that it doesn't work.
Don't try to import variables back and forth. Down that path lies only misery. You should only be importing things that don't change. Functions, classes, etc. In any other case, you'll have hard time making it do what you want.
If you want to move variables between places, you have other options:
Pass function arguments
Return values from a function
Use classes
I'll leave it is an exercise to the reader to learn how to do those things.
import executes imported code
import simply takes the Python source file and executes it. This is why it prints, because that instruction is in the code and with import all the instructions get exectued.
To prevent execution of part of imported package/module, you shall use the famous:
if __name__ == "__main__":
print("I do not print with `import`")
Note, that this behaviour is not new in Python 3, it works the same way in Python 2.x too.
I would like to update a number without changing its placement in the output of a program. How would i go about doing this using only what is included in the standard library for python 2.7.2 ?
For example i want output like:
working on: 9
and change to:
working on: 10
without changing the line that it is displayed on. How would i go about doing this? I would also prefer that you not use cls as to prevent "flashing".
How to do this depends on your terminal type (and possibly on your platform). An easy way that works on many platforms and terminals is to use a \r character to move the cursor back to the beginning of the line:
import time
import sys
for i in range(10):
print "\rworking on:", i,
sys.stdout.flush()
time.sleep(1)
To make the line actually appear, you might need the call to sys.stdout.flush().
There isn't any easy way to do this without resorting to a GUI of some type. The standard way to create a GUI using the terminal is python's curses module. For an explanation of how to use curses in your application see: Curses Programming with Python.