I was trying to create a simple app for illustration purposes. The idea is as follows:
Create an application which will run script files associated only to the selected courses (radio buttons). So, I create radio buttons which list out subjects (to click on). Once the subjects are selected the user has to hit the Enter button. This should run all the .py files for the selected subjects (execute_script function).
However, when I run my code, I get 4 messageboxes with 'None' written inside. After clicking ok on them, I get a square windows with only the enter button. What can I do to correct this problem?
def check(file_name, relStatus):
radioValue = relStatus.get()
tkMessageBox.showinfo('You checked', radioValue)
been_clicked.append(file_name)
return
def execute_script():
for name in been_cliked:
subprocess.Popen(['python', 'C:\Users\Max\Subjects\{}'.format(name)])
yield
def main():
#Create application
app = Tk()
app.title('Coursework')
app.geometry('450x300+200+200')
#Header
labelText = StringVar()
labelText.set('Select subjects')
#Dictionary with names
product_names = {}
names = []
file_name = []
names = ['Math', 'Science', 'English', 'French']
file_name = ['calc.py', 'physics.py', 'grammar.py', 'livre.py']
product_names = OrderedDict(zip(names, file_name))
#Create radio buttons
global been_clicked
been_clicked = []
relStatus = StringVar()
relStatus.set(None)
for name,file_name in product_names.iteritems():
radio1 = Radiobutton(app, text=name, value=name, \
variable=relStatus, command=check(file_name, relStatus))
button = Button(app, text='Click Here', width=20, command=execute_script())
button.pack(side='bottom', padx=15, pady=15)
app.mainloop()
if __name__ == '__main__': main()
1 Answer 1
There are a few issues with your script:
1) A typo in your execute_script() function: for name in been_cliked
2) You are actually calling the check() function when you create your radio buttons. That's why you're seeing the windows pop up when you run your program.
You need to change this:
radio1 = Radiobutton(app, text=name, value=name, \
variable=relStatus, command=check(file_name, relStatus))
to this:
radio1 = Radiobutton(app, text=name, value=name, \
variable=relStatus, command=check)
See how check no longer has brackets? That's means you're passing the function name as an argument, instead of actually calling the function. Of course, you'll see an immediate problem is that you can no longer pass arguments to your callback function! That's a bigger issue. Here's a couple links to help get you started:
- How to pass an argument to event handler in tkinter?
- How can I pass arguments to Tkinter button's callback command?
Here is the solution:
Change this:
command=check(file_name, reStatus)
to this:
command = lambda: check(file_name, relStatus)
3) You don't actually pack() your radio buttons anywhere. Add something like this just after you create your radio buttons in your for loop: radio1.pack(side='top')
4) You have the same problem with your callback for your Click Here button. You need to change your command to not call the function, but just refer to it: command = execute_script
5) In execute_script(), make sure you import subprocessing
6) Are you sure you want yield instead of return in your execute_script() function?
7) In all your functions, you need to make sure that been_clicked is global.
I think if you fix these issues you'll be closer to getting what you're looking for. Good luck.!
4 Comments
for name in been_cliked problem doesn't result in a NameError: global name 'been_cliked' is not defined error since the , command=execute_script() is calling execute_script.yield instead of return. Using yield won't cause NameError to be raised. Not sure why that is though.yield causes a generator to be returned, but until that generated is used, the code hasn't been run yet.