cqwcns 发表于 2021-11-17 16:14

Python Tkinter循环渲染组件和command传参的问题

之前,一直在写vue.js相关的程序,近段时间研究一下python GUI,经过一番了解,决定选择Tkinter。


以下demo,有三个输入框和三个按钮(效果见图),功能是点击按钮选择文件后,将文件名赋值到输入框。
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from tkinter import filedialog


class tanZhen:

    def __init__(self, root):

      # 窗口属性
      root.title("数据处理")

      # 创建组件
      mainframe = ttk.Frame(root, padding="50 30")
      # 渲染组件
      mainframe.grid(column=0, row=0, sticky=(N, W, E, S))

      # 变量
      self.entry1 = StringVar()
      self.entry2 = StringVar()
      self.entry3 = StringVar()

      # 标签
      ttk.Label(mainframe, text="表1").grid(row=1, column=0, sticky=W)
      ttk.Label(mainframe, text="表2").grid(row=2, column=0, sticky=W)
      ttk.Label(mainframe, text="表3").grid(row=3, column=0, sticky=W)

      # 输入框
      entry1 = ttk.Entry(mainframe, textvariable=self.entry1)
      entry1.grid(row=1, column=1, sticky=(W, E), padx=10, pady=10)

      entry2 = ttk.Entry(mainframe, textvariable=self.entry2)
      entry2.grid(row=2, column=1, sticky=(W, E), padx=10, pady=10)

      entry3 = ttk.Entry(mainframe, textvariable=self.entry3)
      entry3.grid(row=3, column=1, sticky=(W, E), padx=10, pady=10)

      # 按钮
      btn1 = ttk.Button(mainframe, text='选择',
                        command=self.func_select_file1)
      btn1.grid(row=1, column=2)

      btn2 = ttk.Button(mainframe, text='选择',
                        command=self.func_select_file2)
      btn2.grid(row=2, column=2)

      btn3 = ttk.Button(mainframe, text='选择',
                        command=self.func_select_file3)
      btn3.grid(row=3, column=2)

    # 函数
    def func_select_file1(self):
      filename = filedialog.askopenfilename()
      self.entry1.set(filename)

    def func_select_file2(self):
      filename = filedialog.askopenfilename()
      self.entry2.set(filename)

    def func_select_file3(self):
      filename = filedialog.askopenfilename()
      self.entry3.set(filename)


root = Tk()
tanZhen(root)
root.mainloop()




以上Demo虽然功能已实现,但可见无论是组件还是对应函数都是类似的,如果在vue中,就是一个数组+列表渲染的问题,但按照JS的思路写了一下,发现问题还比较多。


from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from tkinter import filedialog


class tanZhen:

    def __init__(self, root):

      # 窗口属性
      root.title("数据处理")

      # 创建组件
      mainframe = ttk.Frame(root, padding="50 30")
      # 渲染组件
      mainframe.grid(column=0, row=0, sticky=(N, W, E, S))

      # 变量
      self.entry0 = StringVar()
      self.entry1 = StringVar()
      self.entry2 = StringVar()
      # 为了简化代码,变量声明我以为可以这样,但发现是报错的
      # self.entry0, self.entry1, self.entry2 = StringVar()

      this_element = [['表1', 'entry1'],
                        ['表2', 'entry2'],
                        ['表3', 'entry3'],
                        ]

      for i in range(0, len(this_element)):
            # label的渲染没有问题
            ttk.Label(mainframe, text=this_element).grid(
                row=i, column=0, sticky=W)

            # 这种写法就不行了
            ['entry' + i] = ttk.Entry(mainframe, textvariable=self['entry' + i])
            ['entry' + i].grid(row=i, column=1,
                               sticky=(W, E), padx=10, pady=10)

            ['btn' + i] = ttk.Button(mainframe, text='选择', command=self.func_select_file)
            ['btn' + i].grid(row=i, column=2)
            
            # 函数(函数方面,传参也不知道怎么解决)
            # def func_select_file1(self):
            #   filename = filedialog.askopenfilename()
            #   self.entry1.set(filename)


root = Tk()
tanZhen(root)
root.mainloop()

求指教,如果优雅的写出Tkinter的这种类似组件和对应事件?谢谢指教。

suifenging 发表于 2021-11-17 16:24

用QT是不是会好点,有QTDesigner

Wakes 发表于 2021-11-17 18:24

正在学习中

FireCloud 发表于 2021-11-17 21:07

本帖最后由 FireCloud 于 2021-11-17 21:16 编辑

仅供参考:
      this_element = [['表1', 'entry1'],
                        ['表2', 'entry2'],
                        ['表3', 'entry3'],
                        ]
      # 后面加上

      self.EntryList = list()
      self.ButtonList = list()

      for i in range(0, len(this_element)):
            ttk.Label(mainframe, text=this_element).grid(row=i, column=0, sticky=W)
            self.new_a_entry(mainframe, i)
            self.new_a_button(i, mainframe, text='选择')
   
    def new_a_button(self, i, frame, text):
      butt_index = i
      butt = ttk.Button(frame, text=text, command=lambda:self.func_select_file(butt_index))
      butt.grid(row=i, column=2)
      self.ButtonList.append((butt, butt_index))

    def new_a_entry(self, frame, i):
      new_Entry_var = StringVar()
      new_Entry = ttk.Entry(frame, textvariable=new_Entry_var)
      new_Entry.grid(row=i, column=1, sticky=(W, E), padx=10, pady=10)
      self.EntryList.append((new_Entry_var, new_Entry))

    def func_select_file(self, i):
      filename = filedialog.askopenfilename()
      self.EntryList.set(filename)
      print(filename)

边查CSDN边复制粘贴的,非专业选手
页: [1]
查看完整版本: Python Tkinter循环渲染组件和command传参的问题