How can I call a "command" with tkinter.simpledialog? - python

So I'm trying to create a dialog box that asks the user for an input (a number) with python's built-in Tkinter library. In particular, I googled that this could be easily achieved with the method simpledialog.askinteger.
In a normal tkinter.button, I have the argument "command" which allows me to call a method. This is how I first made this part of my code within the main window:
self.generate_game_button = tkinter.Button(self.main_window, text='Start!', \
command=self.create_grid)
But as I want to ask for this number in a pop up window, in tkinter.simpledialog.askinteger, there is no argument for command, so I'm left with no way of calling my create_grid method... The code looks like:
def press_newgame(self):
global a
a = tkinter.simpledialog.askinteger('Inputz', 'Enter the gameboard size')
My create_grid method basically makes a set of buttons using the inputted int... How can I achieve this using a pop up window to ask the user for a number, and then call the create grid method similar to how the tkinter.Button works?
I hope this makes sense... Thanks.

Well, this is working differently than a simple button, because askinteger is a dialog window, which is not there constantly, it has to be called, and then it will automatically return you a value -- as you expect it.
So I guess you want to do something with the given a value (you probably want to pass it to the create_grid method, so all you have to do is call the method after you got the integer value, something like this:
def press_newgame(self):
a = tkinter.simpledialog.askinteger('Inputz', 'Enter the gameboard size')
self.create_grid(a)

I'm not sure a perfectly understand your usecase. If i understand well, you have a "New game" button, and after the user pressed that button, you want to show the askinteger dialog to get the size of the grid you have to generate for the player. In this case, why you just call your your grid-creating function simply after you came back from the dialog, so like:
global a
a = tkinter.simpledialog.askinteger('Inputz', 'Enter the gameboard size')
createGrid(size=a) # or whatever your function is

Related

Unable to send signal from Button created in Python loop

I am trying to create a series of buttons in a loop. Each button gets an id number as it's text and when the button is clicked it is supposed to send the id number to a function that will open an archived order. At this time I just want to print the order number to prove that the signal works and each button is connected to the correct order number.
ui.cmdOpen = QtWidgets.QPushButton(ui.frOrdHist)
ui.cmdOpen.setGeometry(QtCore.QRect(269, line1Y, 61, 22))
ui.cmdOpen.setText(iOrderId)
ui.cmdOpen.setObjectName("cmdOpen")
ui.cmdOpen.clicked.connect(lambda button=ui.cmdOpen:displayOrder(ui, button))
def displayOrder(ui, button):
i = button.text()
print(i)
When I click the button, I get an error message that says "boolean object has no text attribute"
I tried passing the order number directly and it would print "False" so still a boolean. I don't know where the boolean is coming from, it must be something wrong in the signal.
The clicked signal always sends the checked state of the button. So this will overwrite your default button argument with a boolean value, which is why you get the AttributeError (i.e. because bool doesn't have that method). You should instead make the connection like this:
ui.cmdOpen.clicked.connect(
lambda checked, button=ui.cmdOpen: displayOrder(ui, button))
PS: another common source of this issue is the triggered signal of QAction. If you ever find your slots receiving unexpected inputs, it's always worth checking the Qt Docs to see if the signature of the signal has any parameters with default values - i.e. that look something like this:
void QSomeClass::someSignal(bool param = false)

Python: Button widget in Tkinter

I have just now begun with GUI programming in Python 2.7 with Tkinter.
I want to have a button Browse, which when clicked opens the Windows File Explorer and returns the path of file selected to a variable. I wish to use that path later.
I am following the code given here. It outputs a window displaying 5 buttons, but the buttons do nothing. On clicking the first button, it doesn't open the selected file.
Likewise, on clicking the second button, the askopenfilename(self) function is called and it should return a filename. Like I mentioned, I need that filename later.
How to I get the value returned by the function into some variable for future use?
There is no point in using return inside a callback to a button. It won't return to anywhere. The way to make a callback save data is to store it in a global variable, or an instance variable if you use classes.
def fetchpath():
global filename
filename = tkFileDialog.askopenfilename(initialdir = 'E:')
FWIW (and unrelated to the question): you're making a very common mistake. In python, when you do foo=bar().baz(), foo takes the value in baz(). Thus, when you do this:
button = Button(...).pack()
button will take the value of pack() which always returns None. You should separate widget creation from widget layout if you expect to save an actual reference to the widget being created. Even if you're not, it's a good practice to separate the two.

Showing plots if checkbox is checked, on python (with PyQt4)

I'm brand new to Python and I'm trying to make my first program with PyQt4. My problem is basically the following: I have two checkboxes (Plot1 and Plot2), and a "End" push button, inside my class. When I press End, I would like to see only the plots that the user checks, using matplotlib. I'm not being able to do that. My first idea was:
self.endButton.clicked.connect(self.PlotandEnd)
self.plot1Checkbox.clicked.connect(self.Plot1)
self.plot2Checkbox.clicked.conncet(self.Plot2)
def PlotandEnd(self)
plot1=self.Plot1()
pyplot.show(plot1)
plot2=self.Plot2()
pyplot.show(plot2)
def Plot1(self)
plot1=pyplot.pie([1,2,5,3,2])
return plot1
def Plot2(self)
plot2=pyplot.plot([5,3,5,8,2])
return plot2
This doesn't work, of course, because "PlotandEnd" will plot both figures, regardless of the respective checkbox. How can I do what I'm trying to?
Wrap the plot creation in an if statement that looks at the state of the check boxes. For example:
def PlotandEnd(self)
if self.plot1Checkbox.isChecked():
plot1=self.Plot1()
pyplot.show(plot1)
if self.plot2Checkbox.isChecked():
plot2=self.Plot2()
pyplot.show(plot2)
You also don't need the following lines:
self.plot1Checkbox.clicked.connect(self.Plot1)
self.plot2Checkbox.clicked.conncet(self.Plot2)
This does nothing useful at the moment! Qt never uses the return value of your PlotX() methods, and you only want things to happen when you click the End button, not when you click a checkbox. The PlotX() methods are only currently useful for your PlotandEnd() method.

Creating A UI Window For My Previous Script

folks! So, thanks to you guys I was able to figure out what it was I was doing wrong in my previous script of staggering animation for selected objects in a scene. I am now on part two of this little exercise: Creating a UI for it.
This involves creating a window with a button and user input of how much the animation will be staggered by. So, instead of me putting how much the stagger should increment by (which was two in my previous script), I'd now allow the user to decide.
The script I have so far created the window, button, and input correctly, though I am having some trouble with getting the UI to properly execute, meaning when I click on the button, no error pops up; in fact, nothing happens at all to change the scene. I get the feeling it's due to my not having my increment variable in the correct spot, or not utilizing it the right way, but I'm not sure where/how exactly to address it. Any help would be greatly appreciated.
The code I have (with suggested edits) is as follows:
import maya.cmds as cmds
spheres = cmds.ls(selection=True)
stagWin = cmds.window(title="Stagger Tool", wh=(300,100))
cmds.columnLayout()
button = cmds.button(label="My Life For Aiur!")
count = cmds.floatFieldGrp(fieldgroup, query=True, value=True)
fieldgroup = cmds.floatFieldGrp(numberOfFields=1)
cmds.button(button, edit=True, command=lambda _:stagger(fieldgroup))
cmds.showWindow(stagWin)
def stagger(fieldgroup):
for i in spheres:
cmds.selectKey(i)
cmds.keyframe(edit=True, relative=True, timeChange=count)
print "BLAH"
Moving the comments into an answer because I think I've got it all figured out finally:
First of all, the better practice is to pass the stagger object to the button command rather than the string. so that would be:
cmds.button(label="My Life For Aiur!", command=stagger)
Secondly, the count isn't getting updated, so it stays 0 as per your third line. To update that:
count = cmds.floatFieldGrp(fieldgroup, query=True, value=True)
But wait, where did fieldgroup come from? We need to pass it into the function. So go back to your button code and take out the command entirely, also saving the object to a variable:
button = cmds.button(label="My Life For Aiur!")
Now store the object for the fieldgroup when you make it:
fieldgroup = cmds.floatFieldGrp(numberOfFields=1)
Now that you have fieldgroup, you can pass that in the function for the button, like this:
cmds.button(button, edit=True, command=lambda _:stagger(fieldgroup))
I had to wrap the function in a lambda because we're passing fieldgroup, but if I just put stagger(fieldgroup) it would call that and pass the result of that into the command for the button
Also update stagger def with fieldgroup argument:
def stagger(fieldgroup):
One final note that won't actually affect this, but good to know:
when you shift the keyframes inside stagger you're using a DIFFERENT count variable than the one you declared as 0 up above. The outer one is global, and the inner is local scope. Generally it's best to avoid global in the first place, which fortunately for you means just taking out count = 0
Putting that all together:
import maya.cmds as cmds
spheres = cmds.ls(selection=True)
stagWin = cmds.window(title="Stagger Tool", wh=(300,100))
cmds.columnLayout()
button = cmds.button(label="My Life For Aiur!")
fieldgroup = cmds.floatFieldGrp(numberOfFields=1)
cmds.button(button, edit=True, command=lambda _:stagger(fieldgroup))
cmds.showWindow(stagWin)
def stagger(fieldgroup):
count = 0
increment = cmds.floatFieldGrp(fieldgroup, query=True, value=True)[0]
print count
for i in spheres:
cmds.selectKey(i)
cmds.keyframe(edit=True, relative=True, timeChange=count)
count += increment
print "BLAH"

Get value from gtk.Entry in PyGTK

I am working on a PyGTK GUI project, and i would like to know, is there any way to get variable value from gtk.Entry?
text=gtk.Entry(0)
text.set_activates_default(True)
port = text.get_text()
This doesn't work as, the text box is empty by default, and get_text() returns empty string, any ideas?
This doesn't work as, the text box is empty by default, and get_text() returns empty string, any ideas?
Sounds like you're looking for getting the text after some user input. In order to do this, gtk uses signals that allow you to connect a user action to some function that will do something. In your case you want this function to get the text from the input. Because you haven't described the user interaction I'll give the simplest example. If you had a button
in your GUI that, when clicked, would grab whatever is typed in the entry at that moment, you'd do this:
button = gtk.Button( 'Click Me')
button.connect( 'clicked', on_button_click )
Then, you define the on_button_click function:
def on_button_click(self, widget, data=None):
port = text.get_text()
print 'Port: %s' % port
So with the sample code above, you'd have a button that, when clicked, grabs the text from your gtk.Entry.
Check out this link for a simple example on how to use signals in pygtk
Since your text field is by default empty, get_text() would return empty string.
Add a button callback function or some other function. So whenever that function is called, you would get the string from the Entry using
text.gtk_text()
You might want to use self here. since you'll be accessing entry in some other function and not in main thread, use
self.text=gtk.Entry()
self.text.set_activates_default(True)
def foo(self,widget,event): # some callback function
port = self.text.get_text()
print port
The retrieving method is the correct one, but right after the creation, the user can't yet have typed anyting into the field.
You would have to wait for the user to actually type something into the field, and afterwards calling get_text().

Categories

Resources