0
import tkinter as tk
from tkinter import ttk

def draw_mine_field(x=5, y=3):
    mine_frame = tk.Toplevel(root)
    mine_frame.grid()
    root.withdraw()

    for a in range(x):
        for b in range(y):
            ttk.Button(mine_frame, text='*', width=3 ).grid(column=a, row=b)

root = tk.Tk()
root.title("MS")

startframe = ttk.Frame(root)

ttk.Label(root,text="y").grid(row=1,column=1)
y_entry_box = ttk.Entry(root).grid(row=1,column=2)

ttk.Label(root,text="x").grid(row=1,column=3)
x_entry_box = ttk.Entry(root).grid(row=1,column=4)

ttk.Button(root,text="Start",command=draw_mine_field).grid(row=2,column=1)
ttk.Button(root,text="Quit",command=root.destroy).grid(row=2,column=2)

root.mainloop()

There may be an easier way for this particular example. Basically, what I want to know is when passing the fucntion reference in command=draw_mine_field, how do I pass (x, y) without running the function? In general how does this work?

martineau
  • 119,623
  • 25
  • 170
  • 301
Jay Taffer
  • 11
  • 2
  • 1
    Where are x and y coming from, if not the default values? – Scott Hunter Mar 15 '17 at 16:37
  • You can't pass values to the function without running it. What you could do in this design is set some global variables and have the function use those rather than arguments, but that's not exactly classy design. Typically in a GUI you'd enter the x and y values into input widgets (text boxes or spin boxes) and have the draw function read from those. – Simon Hibbs Mar 15 '17 at 16:47

1 Answers1

2

Use the functool.partials function to make a closure.

from functools import partial
#...
btn = ttk.Button(root,text="Start",command=partial(draw_mine_field, 5, 3))
btn.grid(row=2,column=1)

Some people will tell you to use lambda, but that only works with literals. I'd avoid lambda unless you know exactly how it works. Partial works all the time.

Also, if you want to avoid bugs in the future, don't put the layout (pack, grid, or place) on the same line as the initialization.

Novel
  • 13,406
  • 2
  • 25
  • 41
  • Using `partial` like that only works if the values of the arguments are known when the `Button` widget it created. The OP might as well use default argument values (as shown in the code in their question) if that's the case. – martineau Mar 15 '17 at 16:58