python - 如何在 python 中的类中引用 Tkinter 小部件

标签 python tkinter widget

我创建了几个列表框小部件,在其中选择一些项目,然后按下面的按钮将项目移动到另一个。

这工作得很好 - 但我想重用容器框架,因为两个框架的布局是相同的(除了标题标签和按下按钮时的功能)。因此,我将除按钮功能之外的所有代码都移至“ColumnSelector”类中。

但是,要将数据从一个“ColumnSelector”移动到另一个“ColumnSelector”,我需要引用实例内的列表框。下面是我想做的结构,但我不确定这是否可行。

我尝试了一些其他方法,例如在 ColumnSelector 类之外创建列表框并传递它,但我也遇到了这样做的问题。

在其他类的实例中引用小部件的最佳方式是什么?

    # Data to be included in second listbox widget
    startingSelection = ('Argentina', 'Australia', 'Belgium', 'Brazil', 'Canada', 'China', 'Denmark')

    # Two functions performed by the ColumnSelectors
    def removeSelected(*args):
        idxs = selectedColumns.listBox.curselection() # <- Does not reference correctly
        if len(idxs)>=1:
            for n in reversed(range(len(idxs))):
                idx = int(idxs[n])
                item = selectedColumns.listBox.get(idx)
                selectedColumns.listBox.delete(idx)
                availableColumns.listBox.insert(availableColumns.listBox.size(), item)

    def addSelected(*args):
        idxs = availableColumns.listBox.curselection() #<- Does not reference correctly
        if len(idxs)>=1:
            for n in reversed(range(len(idxs))):
                idx = int(idxs[n])
                item = availableColumns.listBox.get(idx)
                availableColumns.listBox.delete(idx)
                selectedColumns.listBox.insert(selectedColumns.listBox.size(), item)

    # Create ColumnSelectors, pass heading title and function to perform
    selectedColumns = ColumnSelector(self, "Columns to include in export", (), removeSelected).grid(column=0, row=0, sticky=(N,W))
    availableColumns = ColumnSelector(self, "Available Columns", startingSelection, addSelected).grid(column=1, row=0, sticky=(N,W))

class ColumnSelector(ttk.Frame):
    def __init__(self, parent, labelText, startingSelection, function ):
        listBox = Listbox(self, height=5, selectmode='multiple')
        removeColumnsButton = ttk.Button(self, text="Move", command=function)
        #(etc...)

最佳答案

What would be the best way to reference widgets inside instances of other classes?

我认为最常见的用例是无限次地重用对象,因为看起来您正在尝试处理框架内设置的一些列表框。在这种情况下,我认为您应该在子类中放置尽可能多的可重复代码,并在其中创建一个仅返回您想要的内容的方法。当您在主类中创建子类的实例时,您可以在需要时访问其方法(即 selectedColumns.get_all_listbox_values())。

您应该记住的一件事是,如果您创建实例并将其网格化在同一行上,则该实例将无法正常工作:

selectedColumns = ColumnSelector(self, "Columns to include in export", (), removeSelected).grid(column=0, row=0, sticky=(N,W))
selectedColumns.get_all_listbox_values()
>>> AttributeError: 'NoneType' object has no attribute 'get_all_listbox_values'

selectedColumns = ColumnSelector(self, "Columns to include in export", (), removeSelected)
selectedColumns.grid(column=0, row=0, sticky=(N,W))
selectedColumns.get_all_listbox_values()
>>> (0, 1, 2, etc)

下面是设置脚本的一种方法的示例。有一个主类 (App) 和另一个继承自 Frame (MyEntry) 的类,可以在 App 中多次使用。 App 类中有一个按钮,用于打印 MyEntry 中计算几个值的方法的结果。希望它能为您提供一些有关构建代码的想法。

class App(Frame):
    '''the main window class'''
    def __init__(self, parent):
        Frame.__init__(self, parent)

        # create instances of MyEntry, passing whatever operators as args
        # we can make as many of these instances as we need in just a couple of lines
        # and it retains readability
        self.divide = MyEntry(self, '/')
        self.multiply = MyEntry(self, '*')

        self.divide.pack()
        self.multiply.pack()

        Button(self, text='Calculate', command=self._print_result).pack()

    def _print_result(self):
        '''print the return of the calculate method from the instances of
        the MyEntry class'''
        print self.divide.calculate()
        print self.multiply.calculate()

class MyEntry(Frame):
    '''creates two entries and a label and has a method to calculate
    the entries based on an operator'''
    def __init__(self, parent, operator): # include the operator as an arg
        Frame.__init__(self, parent)

        # make an instance variable from the operator to access it between methods
        self.operator = operator

        # make two entries
        self.num1 = Entry(self)
        self.num2 = Entry(self)

        # grid the entries and a label which contains the operator
        self.num1.grid(row=0, column=0)
        Label(self, text=self.operator).grid(row=0, column=1)
        self.num2.grid(row=0, column=2)

    def calculate(self):
        '''return the value of the two entries based on the operator specified'''
        if self.operator is '/':
            return int(self.num1.get()) / int(self.num2.get())
        elif self.operator is '*':
            return int(self.num1.get()) * int(self.num2.get())
        else:
            return

root = Tk()
App(root).pack()
mainloop()

关于python - 如何在 python 中的类中引用 Tkinter 小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23683819/

相关文章:

c - 如何确定 GTK 小部件是否已被销毁

python - 单击()在 Selenium 中不起作用

python - 使用 networkx 提取所有 k-cores

java - Android App Widget,变量正在重启

python - 每次调用函数时,Tkinter 比例都会卡住

python - 如何在 Windows 10 中使用 pip 安装 tkinter

go - 导航并添加到TabItem中的内容

python - 没有名为 trainer 的模块,用于 TensorFlow 教程的 Cloud ML Engine,在本地运行

python - python 类层次结构问题

python - 加载黑框时出现 tkk checkbutton