See the following snippet of code:
def choose_ID():
import ttk
global single_ID
id = BooleanVar()
toplevel = Toplevel()
label1 = Label(toplevel, text = "Choose a User ID.", width = 40).pack(anchor=W, pady=5)
for items in range(len(single_ID)):
id = Checkbutton(toplevel, text=single_ID[items], variable=single_ID[items])
id.pack(anchor=W, padx=5)
single_run_but = Button(toplevel, text = "Run", width=10, height=1, command=run_command).pack(anchor=S, pady=5)
id.get()
Its purpose is to open a popup window with a number of checkboxes (the number could be anything from 1 to 100) containing user id's that have been passed to the function from earlier in the script.
The problem is with the id.get() line at the end. When it runs it errors, saying "Checkbutton instance has no attribute 'get'"
What do I need to change to be able to note which of the checkboxes have been checked (it could be only one or multiple boxes)?
Many thanks,
Chris.
The last time you set id is in the for loop. During this, you set id to be a checkbutton, which does not have the get() method.
What you want to do is use the get() method on an IntVar that is associated with the checkbutton through the variable attribute. You can keep references to these variables in a list. I've made a small example of how to dynamically create checkbuttons and still be able to get their values.
from Tkinter import *
def run_command():
selected_ids = []
for i, id_var in enumerate(id_var_list):
if id_var.get():
selected_ids.append(id_list[i])
print selected_ids
root = Tk()
Label(root, text = "Choose a User ID.", width = 40).pack(anchor=W, pady=5)
id_list = ['ID1', 'ID2', 'ID100']
id_checkbutton_list = []
id_var_list = []
for item in id_list:
id_var = IntVar()
id_checkbutton = Checkbutton(root, text=item, variable=id_var)
id_checkbutton.pack(anchor=W, padx=5)
id_var_list.append(id_var)
id_checkbutton_list.append(id_checkbutton)
Button(root, text = "Run", width=10, height=1, command=run_command).pack(anchor=S, pady=5)
root.mainloop()
Related
I want to display the value stored in the varible "total" to the QlineEdit and add value of the variable 'points' to the QlistWidget when the button is clicked.
In the following block of code, i used "self.lineEdit.setText(str(points))" and "self.LW2.addItem(self.points)" to set text to QlineEdit and QlistWidget respectively. Still, the values won't show up.
def display(self):
sqlC = self.databaseConn()
#self.playersList = []
self.pointlist = []
self.total = 0
self.economic_rate=0
if "----SELECT TEAM----" == self.CB1.currentText():
self.msgbox("Warning","Select a team to evaluate")
else:
for x in range(self.LW1.count()):
player=self.LW1.item(x).text()
#print(player)
sqlC.execute("SELECT Scored,Faced,Fours,Sixes,Bowled,Wkts,Catches,Stumping,RO,Given FROM Match WHERE Player = ?",(player,))
score=sqlC.fetchall()
points = FantasyCricket.FantasyCricket.BattingBowlingPoints.batting(score)
points += FantasyCricket.FantasyCricket.BattingBowlingPoints.bowling(score)
self.pointlist.append(points)
#print(points)
self.total += points
#print(self.total)
self.LW2.addItem(str(points))
self.lineEdit.setText(str(self.total))
P.S- the values are displayed correctly on the Shell using print()
For a simple Gui in Iron python I need a simple dialog box with an input text field and OK and cancel button and return value of input text, equivalent to Visual Basic input box.
So basically, dialog pops up, you enter value, hit OK an dialog box closes and returns value to calling function.
I could not find anything in the windows forms library.
I guess you need to create a form yourself from scratch, using text box, etc..?
Is there really no input box in winforms?
If so, could anyone share how to create one with winforms and iron python?
Thanks for help!
Nils
I am new to Ironpython and GUI programming, therefore the following solution might not be elegant neither complete, but it seems to work.
Any ideas for improvement?
import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")
from System.Drawing import Point
from System.Windows.Forms import Button, Form, Label, TextBox, FormStartPosition, FormBorderStyle
class MyInputBoxClass(Form):
def __init__(self,message, title, defaultText):
#Creates Input Box with text Input Field
#define form
self.Text = title
self.Width = 600
self.Height = 110
self.StartPosition = FormStartPosition.CenterScreen;
self.FormBorderStyle = FormBorderStyle.FixedDialog
self.MinimizeBox = False;
self.MaximizeBox = False;
#define label
self.label = Label()
self.label.Text = message
self.label.Location = Point(10, 10)
self.label.Height = 30
self.label.Width = 250
#define text box
self.textbox = TextBox()
self.textbox.Text = defaultText
self.textbox.Location = Point(10, 40)
self.textbox.Width = 500
#define button
self.button1 = Button()
self.button1.Text = 'ok'
self.button1.Location = Point(510, 40)
self.AcceptButton = self.button1
#define dialog result
self.button1.DialogResult = DialogResult.OK;
#add controls to form
self.Controls.Add(self.label)
self.Controls.Add(self.textbox)
self.Controls.Add(self.button1)
#Todo: Handel Close Input Box Event
def MyInputBox(message, title, defaultText):
form = MyInputBoxClass(message, title, defaultText)
form.ShowDialog()
#Application.Run(form2) #this is not working, you need ShowDialog for modal form
return form.textbox.Text
def TestGui(analysis_obj):
#This function is beeing called from API
inputTextFromDialogBox = MyInputBox("Please Enter Example Text","ExampleInputBox","Its working but I'm not convinced")
print ("Input Box Return Value is '%s'"%inputTextFromDialogBox)
#ExtAPI.Log.WriteMessage("Input Box Return Value is '%s'"%inputTextFromDialogBox)
Using Tkinter, I have many buttons. I would like the same callback function to be triggered every time any of the buttons pressed. How can I find out which button was pressed ?
def call(p1):
# Which Button was pressed?
pass
for i in range (50):
B1 = Button(master, text = '...', width = 2)
B1.grid(row = i*20, column = 60)
B1.bind('<Button-1>',call)
B2 = Button(master, text = '...', width = 2)
B2.grid(row = i*20, column = 60)
B2.bind('<Button-1>',call)
Using a list to reference the dynamically created buttons and lambda to store a reference to the index of the button object. You can determine which button was clicked. In the below examples I use .cget("text") on the button object to demonstrate accessing the button widget.
import tkinter as tk
root = tk.Tk()
root.minsize(200, 200)
btn_list = [] # List to hold the button objects
def onClick(idx):
print(idx) # Print the index value
print(btn_list[idx].cget("text")) #Print the text for the selected button
for i in range(10):
# Lambda command to hold reference to the index matched with range value
b = tk.Button(root, text = 'Button #%s' % i, command = lambda idx = i: onClick(idx))
b.grid(row = i, column = 0)
btn_list.append(b) # Append the button to a list
root.mainloop()
Alternatively you can use bind and then access the widget from the event object generated.
import tkinter as tk
root = tk.Tk()
root.minsize(200, 200)
def onClick(event):
btn = event.widget # event.widget is the widget that called the event
print(btn.cget("text")) #Print the text for the selected button
for i in range(10):
b = tk.Button(root, text = 'Button #%s' % i)
b.grid(row = i, column = 0)
# Bind to left click which generates an event object
b.bind("<Button-1>", onClick)
root.mainloop()
#Steven Summers' first example seems most clear to me, but I think doing it without the list is even clearer.
The way I understood the question, you not only want to know which button was clicked but you also want each button to call one other, undescribed function (universal in my example below). In that case, you can use the very handy
combine_funcs (see: Have multiple commands when button is pressed) to call two functions from one widget.
Here is my code. Instead of a list, I simply have a string that is changed and printed with each click.
import tkinter as tk
root = tk.Tk()
root.minsize(200, 200)
buttonVal = ''
def combine_funcs(*funcs):
def combined_func(*args, **kwargs):
for f in funcs:
f(*args, **kwargs)
return combined_func
def universal():
print 'Universal function is called'
def button_check(buttonName):
buttonVal = buttonName
print buttonVal # Or whatever you want to do with the button info
for i in range(10):
B1 = tk.Button(root, text = 'Button #%s' % i, command = combine_funcs(universal, lambda buttonName = 'Button #%s' % i:button_check(buttonName)))
B1.grid(row = i, column = 0)
root.mainloop()
Use lambda:
B1 = Button(master, text = '...', width = 2, command = lambda: call('B1') )
And so on...
This might not be the simplest solution, but it is the only one I could come up with.
from Tkinter import *
master = Tk()
L = []
def call(p1):
for i in range(len(L)):
if str(L[i]) == str(p1.widget):
print 'Button' + str(i)
break
for i in range (50):
exec("Button" + str(i) + " = Button(master, text = '...', width = 2)")
exec("Button" + str(i) + ".grid(row = i*20, column = 60)")
exec("Button" + str(i) + ".bind('<Button-1>',call)")
s = 'L.append(str(Button' + str(i) + '))'
exec(s)
Hi to all that look and might be able to help. I'm new to Python, and to coding in general. I'm working on a program that the basic concept of it is to have a few lists, make a selection from one list, and then another list is populated based on that first choice. I have been able to create the GUI, I've been able to create various different forms of "Listbox", I've been able to follow tutorials that show how to retrieve the indicies of that "Listbox", but I haven't been able to get the 2nd Listbox to fill in with the list I created for a choice made in the 1st box. I've tried checkboxes too, I did get closer on that one, but still no dice.
The supplied code below works in the sense that I can print the 2nd list into the python shell, but when I get a listbox set up in my GUI I can't get it to populate there. Nothing every happens. And I know that I don't have a listbox in this code to have it be populated with the 2nd list. So in this code, I would like the 'brand' choice if 'Apples', to populate the list from 'modelA' in a listbox. Or if the checkboxes actually weren't there and the items in 'brand' where in their own listbox. Any direction might help a lot more than what I've been able to do. Thanks again.
Python 3.3.2
Mac OS X 10.8.5
from tkinter import *
#brand would be for first listbox or checkboxes
brand = ['Apples','Roses', 'Sonic', 'Cats']
#model* is to be filled into the 2nd listbox, after selection from brand
modelA = ['Ants', 'Arrows', 'Amazing', 'Alex']
modelR = ['Early', 'Second', 'Real']
modelS= ['Funny', 'Funky']
modelC= ['Cool', 'Daring', 'Double']
#create checkboxes
def checkbutton_value():
if(aCam.get()):
print("Models are: ", modelA)
if(rCam.get()):
print("Models are: ", modelR)
if(sCam.get()):
print("Models are: ", modelS)
if(cCam.get()):
print("Models are: ", modelC)
#create frame, and check checkbuttons state, print value of model
root = Tk()
aCam = IntVar()
rCam = IntVar()
sCam = IntVar()
cCam = IntVar()
#Checkbutton functions
apples = Checkbutton(root, text = "Apples", variable=aCam, command=checkbutton_value)
apples.pack(anchor="w")
roses = Checkbutton(root, text = "Roses", variable=rCam, command=checkbutton_value)
roses.pack(anchor="w")
sonic = Checkbutton(root, text = "Sonic", variable=sCam, command=checkbutton_value)
sonic.pack(anchor="w")
cats = Checkbutton(root, text = "Cats", variable=cCam, command=checkbutton_value)
cats.pack(anchor="w")
#general stuff for GUI
root.title('My Brand')
root.geometry("800x300")
root.mainloop()
To populate a Listbox based on the selection of another Listbox, you need to bind a method to the 1st Listbox's selection. Here's an example using makes/models of cars:
import Tkinter
class Application(Tkinter.Frame):
def __init__(self, master):
Tkinter.Frame.__init__(self, master)
self.master.minsize(width=512, height=256)
self.master.config()
self.pack()
self.main_frame = Tkinter.Frame()
self.main_frame.pack(fill='both', expand=True)
self.data = {
'Toyota': ['Camry', 'Corolla', 'Prius'],
'Ford': ['Fusion', 'Focus', 'Fiesta'],
'Volkswagen': ['Passat', 'Jetta', 'Beetle'],
'Honda': ['Accord', 'Civic', 'Insight']
}
self.make_listbox = Tkinter.Listbox(self.main_frame)
self.make_listbox.pack(fill='both', expand=True, side=Tkinter.LEFT)
# here we bind the make listbox selection to our method
self.make_listbox.bind('<<ListboxSelect>>', self.load_models)
self.model_listbox = Tkinter.Listbox(self.main_frame)
self.model_listbox.pack(fill='both', expand=True, side=Tkinter.LEFT)
# insert our items into the list box
for i, item in enumerate(self.data.keys()):
self.make_listbox.insert(i, item)
def load_models(self, *args):
selection = self.make_listbox.selection_get()
# clear the model listbox
self.model_listbox.delete(0, Tkinter.END)
# insert the models into the model listbox
for i, item in enumerate(self.data[selection]):
self.model_listbox.insert(i, item)
root = Tkinter.Tk()
app = Application(root)
app.mainloop()
I used the code below to create several spinners with a for loop.
Now, I can't figure out how to bind an event so that I know which spinner is being modified so that I can put the spinner value into the right variable.
If I can figure out which spinner is calling the handler I could map it to the correct variable.
Any thoughts? Is this even possible?
Thanks in advance!
import wx
class spinnerFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent,id, "Spinner Frame", size = (300,200))
#constants
spnr_sz = (50,-1)
names = ('name1','name2','name3','name4','name5','name6')
sizer = wx.GridBagSizer(5, 5)
# TEXT FONT EXAMPLE
# m_text = wx.StaticText(panel, -1, "Hello World!")
# m_text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
# m_text.SetSize(m_text.GetBestSize())
#temp
sizer = wx.GridBagSizer(5, 5)
row = 0
for n in names:
row += 1
my_label = wx.StaticText(self, -1, n)
spinner = wx.SpinCtrl(self, -1, size = spnr_sz, min = 0, initial = 10 )
self.Bind(wx.EVT_SPINCTRL, self.OnCompute, spinner)
sizer.Add(my_label, (row,0))
sizer.Add(spinner, (row,1))
sizer.AddGrowableRow(7)
sizer.AddGrowableCol(4)
self.SetSizerAndFit(sizer)
self.Centre()
def OnCompute(self,event):
# a = spinner.GetValue()
# ????
if __name__=='__main__':
app = wx.App(True) # was False
frame = wx.Frame(None)
frame = spinnerFrame (parent=None, id = -1)
frame.Show()
app.MainLoop()
Yes, this is possible. The easiest way I know is to associate your unique name with each call to Bind, either by giving the spinner a name or using partial functions (or lambdas, but lambdas can end up being messy), and then check for the name in the handler. Examples of how to use the name are given in this previous SO question.