Reputation: 129
I've got an Excel spreadsheet I'm pulling info from. This will probably be changed to a database at some point but for now its fine for testing. It has two columns with data and looks like:
Key | ProgramName | Path
0 | Calculator | C:\Windows\System32\calc.exe
1 | Notepad | C:\Windows\System32\notepad.exe
I've built a pretty basic GUI using Python Tkinter and use the xlrd library to extract data from the spreadsheet into a list that contains dictionary entries.
https://pypi.python.org/pypi/xlrd
This gives me a list with dictionary entries:
[{'Path':'C:\Windows\System32\notepad.exe', 'Program':'Notepad', 'Key':0.0}, {'Path':'C:\Windows\System32\calc.exe', 'Program':'Calculator', 'Key':1.0}]
I can get the radio buttons working decently but I'm having an issue pulling the path data and re-using it, since I will (hopefully) use subprocess.Popen to actually open the program selected.
Heres the code so far:
from Tkinter import *
from xlrd import open_workbook
import os
import subprocess
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
bottomframe= Frame(master)
bottomframe.pack(side = BOTTOM)
book = open_workbook('programlist.xls')
sheet = book.sheet_by_index(0)
# read header values into the list
keys = [sheet.cell(0, col_index).value for col_index in xrange(sheet.ncols)]
global dict_list
dict_list = []
for row_index in xrange(1, sheet.nrows):
d = {keys[col_index]: sheet.cell(row_index, col_index).value
for col_index in xrange(sheet.ncols)}
dict_list.append(d)
self.w = StringVar()
self.w.set(dict_list[0]['Key']) # initialize
for eachprogram in dict_list:
self.c = Radiobutton(master, text=eachprogram['Program'], variable=self.w, value=eachprogram['Key'])
self.c.pack(anchor=W)
self.quitButton = Button(
bottomframe, text="QUIT" , fg="red", command=frame.quit
)
self.quitButton.pack(side=LEFT, anchor=S)
self.programRun = Button(bottomframe, text="Run", command=self.programRun)
self.programRun.pack(side=LEFT, anchor=S)
def programRun(self):
???
root = Tk()
app = App(root)
root.mainloop()
root.destroy()
Not sure what I need to do so that when the programRun button is pressed, correct path is pulled so I can put it into a "subprocess.Popen" command. Do I need to create another variable? Can I pull this info using a dictionary key?
Any suggestions are greatly appreciated.
Upvotes: 1
Views: 1210
Reputation: 4482
It's not a hard task to pull path from your example and here're even two options to choose from. And you don't need to create an another variable.
According to Docs:
The variable option must be set to a control variable, either an IntVar or a StringVar. All the radiobuttons in a functional group must share the same control variable.
Set the value option of each radiobutton in the group to a different value. Whenever the user sets a radiobutton, the variable will be set to the value option of that radiobutton, and all the other radiobuttons that share the group will be cleared.
As you see - you don't need to use a StringVar
, but DoubleVar
since your value
parameters (and keys) are floats
. Downside here - you need to iterate over list to check each dictionary for Key
.
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.frame = tk.Frame(self)
self.frame.pack()
self.bottomframe = tk.Frame(self)
self.bottomframe.pack(side=tk.BOTTOM)
# book = open_workbook('programlist.xls')
# sheet = book.sheet_by_index(0)
# read header values into the list
# keys = [sheet.cell(0, col_index).value for col_index in xrange(sheet.ncols)]
self.keys = ['Key', 'ProgramName', 'Path']
self.dict_list = [{'Path': r'C:\Windows\System32\notepad.exe', 'Program': 'Notepad', 'Key': 0.0},
{'Path': r'C:\Windows\System32\calc.exe', 'Program': 'Calculator', 'Key': 1.0}]
# global dict_list
# dict_list = []
# for row_index in xrange(1, sheet.nrows):
# d = {keys[col_index]: sheet.cell(row_index, col_index).value
# for col_index in xrange(sheet.ncols)}
# dict_list.append(d)
self.w = tk.DoubleVar()
self.w.set(self.dict_list[0]['Key']) # initialize
for each_program in self.dict_list:
self.c = tk.Radiobutton(self.master, text=each_program['Program'], variable=self.w, value=each_program['Key'])
self.c.pack(anchor=tk.W)
self.quitButton = tk.Button(
self.bottomframe, text="QUIT", fg="red", command=self.frame.quit
)
self.quitButton.pack(side=tk.LEFT, anchor=tk.S)
self.programRun = tk.Button(self.bottomframe, text="Run", command=self.programRun)
self.programRun.pack(side=tk.LEFT, anchor=tk.S)
def programRun(self):
print('Pulled path: %s' % self.search_list_dict())
def search_list_dict(self):
try:
return [item for item in self.dict_list if item['Key'] == self.w.get()][0]['Path']
except IndexError:
return ''
app = App()
app.mainloop()
As an alternative - you can use a StringVar
and Path
item as a value
parameter! Just change some lines:
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
...
self.w = tk.StringVar()
self.w.set(self.dict_list[0]['Path']) # initialize
for each_program in self.dict_list:
self.c = tk.Radiobutton(self.master, text=each_program['Program'], variable=self.w, value=each_program['Path'])
self.c.pack(anchor=tk.W)
...
def programRun(self):
print('Pulled path: %s' % self.w.get())
app = App()
app.mainloop()
Upvotes: 1