Variable value changes from string to instance - python-2.7

I am trying to put together my first little program, but I keep having some difficulties. I am using data from an SQLite DB, but I changed the code below a bit so it's usable without the DB itself. The list_base and List_sold_at_base functions usually would pull data from a DB (base and commodities info from the Freelancer game, so I can list what commodities are sold on what base).
What the program should do is build up a list of all bases when the 'bases' button is pressed and put this in the Combobox.
When selecting an option from the Combobox this selection should be stored in the variable v, and update when another base is selected. This works. the variable v is a str type so far.
The Goods sold at base button calls a function that takes v and uses it to check in de DB what goods are sold at this base, and prints this out in a list.
However, now the variable v isn't a string type anymore (which it should be for the function to work properly), but an instance. Somehow this gets changed but I can't figure out where and why. I put in a couple of print statements to see how and where, but they don't really show it all that well.
from Tkinter import *
import csv, sqlite3, sys
from ttk import Combobox
root = Tk()
v = StringVar()
def on_field_change(index, value, op):
print "combobox updated to ", boxBases.get()
v = boxBases.get()
print 'v is', v
print type(v)
def List_bases():
dropdownBases = []
for i in ['base1', 'base2', 'base3', 'base4',]:
dropdownBases.append(i)
return dropdownBases
def List_sold_at_base(selbase):
goodsSoldAtBase = []
sb=selbase
print "selbase value (v) is", selbase
print "selbase type is ", type(selbase)
dataFromDB = [['base1', 'Cobalt 275', 'Copper 180'],['base2', 'High Temp Alloy 280', 'Mining Machinery 130'], ['base3', 'H-Fuel 240', 'Oxygen 6', 'Water 18'], ['base4', 'Hydrocarbons 40', 'Polymers 107']]
for i in dataFromDB:
if i[0] == sb:
goodsSoldAtBase.append(i)
print "goods sold at base list: ", goodsSoldAtBase
print " "
print v
print type(v)
def base():
dropdownBases = List_bases()
boxBases.config(values=dropdownBases)
print "bases!"
def goods():
List_sold_at_base(v)
print '=========='
dropdownBases = []
v.trace('w',on_field_change)
boxBases = Combobox(root, textvar=v, values=dropdownBases)
boxBases.grid(row=4, column=3, sticky='w', padx=5, pady=5)
baseButton=Button(root, text="bases", command=base)
baseButton.grid(row=3, column=0, sticky='w', padx=5, pady=5)
goodsButton = Button(root, text="Goods sold at base", command=goods)
goodsButton.grid(row=3, column=2, sticky='w', padx=5, pady=5)
root.mainloop()

Thanks for the input. I got it to work by trying around with the .get() a bit more and taking out 1 function that basically just called another function. I cut out the middle man (goods() ).
from Tkinter import *
import csv, sqlite3, sys
from ttk import Combobox
root = Tk()
v = StringVar()
def on_field_change(index, value, op):
v = boxBases.get()
print 'v is', v
def List_bases():
dropdownBases = []
for i in ['base1', 'base2', 'base3', 'base4',]:
dropdownBases.append(i)
return dropdownBases
def List_sold_at_base():
goodsSoldAtBase = []
sb=v.get()
dataFromDB = [['base1', 'Cobalt 275', 'Copper 180'],['base2', 'High Temp Alloy 280', 'Mining Machinery 130'], ['base3', 'H-Fuel 240', 'Oxygen 6', 'Water 18'], ['base4', 'Hydrocarbons 40', 'Polymers 107']]
for i in dataFromDB:
if i[0] == sb:
goodsSoldAtBase.append(i)
print "goods sold at base list: ", goodsSoldAtBase
def base():
dropdownBases = List_bases()
boxBases.config(values=dropdownBases)
print "bases!"
dropdownBases = []
v.trace('w',on_field_change)
boxBases = Combobox(root, textvar=v, values=dropdownBases)
boxBases.grid(row=4, column=3, sticky='w', padx=5, pady=5)
baseButton=Button(root, text="bases", command=base)
baseButton.grid(row=3, column=0, sticky='w', padx=5, pady=5)
goodsButton = Button(root, text="Goods sold at base", command=List_sold_at_base)
goodsButton.grid(row=3, column=2, sticky='w', padx=5, pady=5)
root.mainloop()

Related

Python Tkinter - Get value from mutliple checkboxes

I am creating a Tkinter application where trying to get value from multiple checkboxes. I am able to create the checkboxes but not able to retrieve the value .i.e. checked or not checked checkboxes.
Requirement:
I need to loop through all checkbox variables to identify the checked ones.
import openpyxl
import sys
import pandas as pd
from Tkinter import *
import ttk
import tkFont
reload(sys)
sys.setdefaultencoding('utf8')
top = Tk()
notebook = ttk.Notebook(top)
notebook.grid(row=1, column=0, columnspan=1, sticky=W)
frame1 = ttk.Frame(top)
notebook.add(frame1, text='TAB1')
s = ttk.Style()
s.theme_use('clam')
helv36 = tkFont.Font(family='Helvetica', size=12, weight=tkFont.BOLD)
wb = openpyxl.load_workbook('File',data_only=True)
ws = wb['Sheet1']
mylist = []
mylist1 = []
for col in ws['A']:
mylist.append(col.value)
for col in ws['B']:
mylist1.append(col.value)
mylist = [str(item) for item in mylist]
mylist1 = [str(item) for item in mylist1]
i=2
for name in mylist:
Label(frame1, text="col1",
borderwidth=1,font=helv36).grid(row=1)
Label(frame1, text=name,
borderwidth=1).grid(row=i)
i +=1
i =2
for name in mylist1:
Label(frame1, text="col2",
borderwidth=1,font=helv36).grid(row=1, column=1)
Label(frame1, text=name,
borderwidth=1).grid(row=i,column=1)
val = IntVar()
val = "v" + str(i)
c_val = Checkbutton(frame1, variable=val)
c_val.grid(row=i, column=2,sticky = W)
i +=1
***def chkbox_checked():
#Need to loop to get checked checkboxes***
B200 = Button(frame1, text ="Check", command = chkbox_checked,font=helv36, bg='orange')
B200.grid(row=100)
top.mainloop()
You can associate a BooleanVar to the checkbox and get the value. You can then use set() method to set the default value for the checkbox and get() to get the state of the checkbox. For example:
import tkinter as tk
root=tk.Tk()
c=tk.BooleanVar()
tk.Checkbutton(root,variable=c,command=lambda: print(c.get())).pack()
root.mainloop()
if you want to loop over a number of checkboxes, you can do this:
import tkinter as tk
root=tk.Tk()
c1=tk.BooleanVar()
c2=tk.BooleanVar()
c3=tk.BooleanVar()
c4=tk.BooleanVar()
def get_value():
for c in (c1,c2,c3,c4):
print(c.get())
tk.Checkbutton(root,text='checkbox1',variable=c1,).pack()
tk.Checkbutton(root,text='checkbox2',variable=c2,).pack()
tk.Checkbutton(root,text='checkbox3',variable=c3,).pack()
tk.Checkbutton(root,text='checkbox4',variable=c4,).pack()
tk.Button(root,text='get value',command=get_value).pack()
root.mainloop()

If loop in tkinter - button pressed

How to get tkinter to enter the if loop when button pressed to print? I do not want the print command to be in the button function.
Code:
from tkinter import *
class Player:
N = 0
def __init__(self, name, points):
# instance variables goes here
self.name = name
self.score = points
# increment class variable
Player.N = Player.N+1
class G_501:
def __init__(self, players=[]):
self.NoPlayers = len(players)
print("Number of players",self.NoPlayers)
Spillere = []
Score = []
Runde = 0
for i in range(0, len(players)):
P = Player(players[i], 501)
print("Player", Player.N, P.name, "- Point:", P.score)
Spillere.append(P.name)
Score.append(P.score)
Score = list(map(int, Score))
root = Tk()
c = [False]
def half_bull(c, event=None):
c.append(True)
return c
b1 = Button(root, text="Half Bull", bg="green", fg="black", command=lambda c=c: half_bull(c))
b1.pack()
print(c)
if c[-1] == True:
print("Fedt")
root.mainloop()
S = G_501(["Chr"])
Only need help with the tkinter part... Thanks!

Generate a bunch of tkinter checkbuttons and read the status of all those radio buttons at once

I have a tkinter class which reads some data into a couple of lists. From this now i have created a dictionary for creating checkbuttons.
I'm trying to create those checkbuttons in a new window() with a button to submit and read the stutus of those. I want this data to process.
def get_data(self):
self.flags = ["one","two","three", "four"]
self.tests = ["Jack","Queen","King","Ace"]
self.value = [11,12,13,1]
self.dict1 = {k:v for k,v in enumerate(self.flags,1)}
def get_status(self):
self.selectWindow = Toplevel(root)
self.selectWindow.title("Select Test Cases")
Submit_btn = Button(selectWindow, text="Submit", command=read_status )
for testcase in self.dict1:
self.dict1[testcase] = Variable()
l = Checkbutton(self.selectWindow,text=self.dict1[testcase], variable=self.dict1[testcase])
l.pack()
def read_status(self):
pass
From here I'm not able go ahead and read the status of checkbuttons and get those are checked. I need this data for further processing on tests(not actual lists given here I have few more). How to solve? Please let me know.
Checkbutton has a built in command function that can solve this problem. Every time you press a button that function is called, and you can print out the values of the buttons (0,1)
def get_data(self):
self.flags = ["one","two","three", "four"]
self.tests = ["Jack","Queen","King","Ace"]
self.value = [11,12,13,1]
self.dict1 = {k:v for k,v in enumerate(self.flags,1)}
def get_status(self):
self.selectWindow = Toplevel(self)
self.selectWindow.title("Select Test Cases")
self.get_data()
Submit_btn = Button(self.selectWindow, text="Submit", command=read_status ) # This button should be packed
Submit_btn.pack()
for testcase in self.dict1:
self.dict1[testcase] = Variable()
l = Checkbutton(self.selectWindow,text=self.dict1[testcase], variable=self.dict1[testcase], command=self.read_status) # Note the command
l.pack()
self.selectWindow.mainloop()
# Here comes the interesting part
def read_status(self):
for i,j in self.dict1.iteritems():
print j.get()
You forgot to use self and pack method:
Submit_btn = Button(self.selectWindow, text="Submit", command=self.read_status )
Submit_btn.pack()
Checkbutton's states are (0, 1) so use IntVar() to inspect the state:
...
self.dict1[testcase] = IntVar()
...
Then use IntVar get method:
def read_status(self):
for v in self.dict1:
print self.dict1[v].get()

Tkinter and displaying iterating list

I have the following code:
from Tkinter import *
import itertools
l1 = [1, 'One', [[1, '1', '2'], [2, '3', '4'], [3, '5', '6']]]
l2 = [2, 'Two', [[1, 'one', 'two'], [2, 'three', 'four'], [3, 'five', 'six']]]
def session(evt,contents):
def setup_cards():
cards = [stack[2] for stack in contents]
setup = [iter(stack) for stack in cards]
return cards, setup
def end():
window.destroy()
def start():
print setup
print cards
pair = next(setup[0])
def flip():
side2cont.set(pair[2])
flipbutton.configure(command=start)
for stack in setup:
try:
for card in cards:
try:
side1cont.set(pair[1])
flipbutton.configure(command=flip)
except StopIteration:
continue
except StopIteration:
pair = next(setup[1])
window = Toplevel()
window.grab_set()
window.title("Session")
card_frame = Frame(window)
card_frame.grid(row=0, column=0, sticky=W, padx=2, pady=2)
button_frame = Frame(window)
button_frame.grid(row=1, column=0, pady=(5,0), padx=2)
side1_frame = LabelFrame(card_frame, text="Side 1")
side1_frame.grid(row=0, column=0)
side1cont = StringVar()
side2cont = StringVar()
side1 = Label(side1_frame, textvariable=side1cont)
side1.grid(row=0, column=0, sticky=W)
side2_frame = LabelFrame(card_frame, text="Side 2")
side2_frame.grid(row=1, column=0)
side2 = Label(side2_frame, textvariable=side2cont)
side2.grid(row=0, column=0, sticky=W)
flipbutton = Button(button_frame, text="Flip", command=start)
flipbutton.grid(row=0, column=2)
finishbutton = Button(button_frame, text="End", command=end)
finishbutton.grid(row=0,column=0, sticky=E)
cards = setup_cards()[0]
setup = setup_cards()[1]
w = Tk()
wbutton = Button(text='toplevel')
wbutton.bind('<Button-1>', lambda evt, args=(l1, l2): session(evt, args))
wbutton.pack()
w.mainloop()
It is piece of my project, I remade it just to the basics so it's easy to understand. In my project, function session accepts files, these are now emulated as lists l1 and l2.
The point where I am struggling is when I hit StopIteration exception. I would like my script to do the following:
1. When iteration reaches end, switch to another iterator (next item in setup list, in this case l2 iterator).
2. If no other iterators are present in setup, reset the iterator ("start over from the beginning").
The code above is the best I was able to come up with, that's why I'm turning to you folks. Thank you (also I'm newbie so I'm still struggling with basics of Python/programming in general).
StopIteration is caught by for and not propagated further. You may want to use for…else.
But your methods of iteration are weird, why not just use regular for loops?

What's the difference between these two functions in Tkinter?

Why are these two functions different?
def other_entry1(self, selection, row, el, var):
if selection == "Other":
var = StringVar()
el = Entry(self.frame1, textvariable=var)
el.grid(row=row, column=6)
#Calling it as part of an optionMenu
self.e33 = OptionMenu(self.frame1, self.ea_tf, *fixtures, command= lambda selection:self.other_entry1(selection,15, self.e33, self.ea_tf))
The other one:
def other_entry2(self, selection):
if selection == "Other":
self.ea_tf = StringVar()
self.e33 = Entry(self.frame1, textvariable=self.ea_tf)
self.e33.grid(row=15, column=6)
#Calling it in an optionMenu
self.e33 = OptionMenu(self.frame1, self.ea_tf, *fixtures, command=self.other_entry2)
I would like to be able to call the first function several times and just tell it what entry box to create instead of making several separate functions.
Edit: Isn't the second function just skipping the step of substituting in the arguments?
self.s33 is reference to OptionMenu
Second function overwrite self.e33 by reference to Entry and you can't use self.e33 to get access to OptionMenu.
First function copy reference from self.s33 to el then overwrites el by reference to Entry but you can still use self.s33 to get access to OptionMenu
See simple example using "Visual Execution" on PythonTutor.com:
Use link to open page with example, click "Visual Execution" and then you can use "Forward" button to see step by step how example works
function 1
function 2
You can use first function to create several Entry but you don't need to send self.e33 and self.ea_tf because function will not use it.
You get the same result as
def other_entry1(self, selection, row):
if selection == "Other":
var = StringVar()
Entry(self.frame1, textvariable=var).grid(row=row, column=6)
#Calling it as part of an optionMenu
self.e33 = OptionMenu(self.frame1, self.ea_tf, *fixtures, command=lambda selection:self.other_entry1(selection,15))
problem is with access to Entry or StringVar() to get value from Entry
self.all_vars = {} # dictionary
def other_entry1(self, selection, row):
if selection == "Other":
self.all_vars[row] = StringVar()
Entry(self.frame1, textvariable=self.all_vars[row]).grid(row=row, column=6)
#Calling it as part of an optionMenu
self.e33 = OptionMenu(self.frame1, self.ea_tf, *fixtures, command=lambda selection:self.other_entry1(selection,15))
# another place
row = 15
print "row:", row
print "value in Entry:", self.all_vars[row].get()
EDIT: working example
#!/usr/bin/env python
from Tkinter import *
class App():
def __init__(self, master):
self.master = master
self.all_entries = {} # empty dictionary
self.all_entries_vars = {} # empty dictionary
self.all_optionmenus = {} # empty dictionary
self.all_optionmenus_vars = {} # empty dictionary
fixtures = ["One", "Two", "Tree", "Other"]
# create 5 options menu
for i in range(5):
self.all_optionmenus_vars[i] = StringVar()
self.all_optionmenus_vars[i].set("One")
self.all_optionmenus[i] = OptionMenu(self.master, self.all_optionmenus_vars[i], *fixtures, command=lambda selection, col=i:self.addEntry(selection, col))
self.all_optionmenus[i].grid(row=1, column=i)
Button(master, text="Print OptionMenus Vars", command=self.printOptionMenus).grid(row=2, column=0, columnspan=5)
Button(master, text="Print Entries Vars", command=self.printEntries).grid(row=3, column=0, columnspan=5)
def run(self):
self.master.mainloop()
def addEntry(self, selection, col):
if selection == "Other":
# if Entry was created before
if col in self.all_entries:
# show existing Entry
self.all_entries[col].grid(row=0, column=col)
else:
# create new Entry
self.all_entries_vars[col] = StringVar()
self.all_entries[col] = Entry(self.master, textvariable=self.all_entries_vars[col])
self.all_entries[col].grid(row=0, column=col)
# if Entry was created before
elif col in self.all_entries:
# hide Entry
self.all_entries[col].grid_forget()
def printEntries(self):
print "-"*30
for key in self.all_entries_vars:
print "Entry #%d: %s" % ( key, self.all_entries_vars[key].get() )
def printOptionMenus(self):
print "-"*30
for key in self.all_optionmenus_vars:
print "OptionMenu #%d: %s" % ( key, self.all_optionmenus_vars[key].get() )
#----------------------------------------------------------------------
if __name__ == '__main__':
App(Tk()).run()