![](/img/trans.png)
[英]How to place items/ widgets inside other classes using tkinter and python oop
[英]How to reference Tkinter widgets inside classes in python
我创建了几个列表框小部件,在其中选择一个项目,然后按下面的按钮将项目移到另一个项目。
这绝对好用-但是我想重用容器框架,因为2个框架的布局是相同的(除了标题标签和按下按钮时的功能)。 因此,我将除按钮功能以外的所有代码移至“ 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...)
在其他类的实例中引用窗口小部件的最佳方法是什么?
我认为最常用的情况是无限期地重复使用对象,因为您似乎要尝试使用框架中设置的某些列表框。 在这种情况下,我认为您应该在子类中放置尽可能多的可重复代码,并在其中创建一个返回所需内容的方法。 在主类中创建子类的实例时,可以在需要时访问子类的方法(即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()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.