【发布时间】:2020-01-13 20:44:37
【问题描述】:
所以我的项目是关于结合图像显示来自数据库的信息。 思路如下:
我有一个描述图像的数据库。一个表有一般信息,比如哪个颜色包含在哪个图像中,另一个表有更详细的信息,比如可以找到该颜色的位置等。
当我启动搜索时,我希望打开两个窗口(@987654323@ 和 ClassThree)。
我的完整应用程序不是第一个仅包含启动搜索的按钮的窗口,而是包含用于过滤数据库请求的字段。当我启动该搜索时,我想要例如所有带有绿色的图像,因此ClassTwo 将列出所有带有该颜色的图像以及其他元数据。
ClassThree 然后会列出所有包含相同颜色但细节更多的区域,例如图像中的位置和大小等。
单击任一MultiListbox 后,我想打开一个显示图像的 ImageViewer。
如果是ClassThree,我也会直接突出显示我点击的区域,这样两个类的函数都会绑定到MultiListbox。
我的问题在于Listboxes 的绑定,它无法正常工作。当我使用例如image_parts_info_lb.bind()该功能根本没有被触发。当我使用image_parts_info_lb.bind_all() 时,只会触发最后一个MultiListbox 的功能。
你可以在类的评论中找到MultiListbox的原始Python2版本。
这是我的代码
import tkinter as tk
class MultiListbox(tk.Frame):
#original Python2 code here:
#https://www.oreilly.com/library/view/python-cookbook/0596001673/ch09s05.html
def __init__(self, master, lists):
tk.Frame.__init__(self, master)
self.lists = []
print(lists)
for l,w in lists:
frame = tk.Frame(self)
frame.pack(side='left', expand='yes', fill='both')
tk.Label(frame, text=l, borderwidth=1, relief='raised').pack(fill='x')
lb = tk.Listbox(frame, width=w, borderwidth=0, selectborderwidth=0,
relief='flat', exportselection=False, height=16)
lb.pack(expand='yes', fill='both')
self.lists.append(lb)
#commented out functions that were not necessary, as suggested in the comments
#lb.bind('<B1-Motion>', self._select)
lb.bind('<<ListboxSelect>>', self._select)
#lb.bind('<Leave>', lambda e: 'break')
lb.bind('<MouseWheel>', lambda e, s=self: s._scroll_mouse(e))
#lb.bind('<Button-2>', lambda e, s=self: s._button2(e.x, e.y))
frame = tk.Frame(self)
frame.pack(side='left', fill='y')
tk.Label(frame, borderwidth=1, relief='raised').pack(fill='x')
sb = tk.Scrollbar(frame, orient='vertical', command=self._scroll)
sb.pack(expand='yes', fill='y')
self.lists[0]['yscrollcommand']=sb.set
def _select(self, event):
w = event.widget
curselection = w.curselection()
if curselection:
self.selection_clear(0, self.size())
self.selection_set(curselection[0])
def _button2(self, x, y):
for l in self.lists:
l.scan_mark(x, y)
return 'break'
def _b2motion(self, x, y):
for l in self.lists: l.scan_dragto(x, y)
return 'break'
def _scroll(self, *args):
for l in self.lists:
l.yview(*args)
return 'break'
def _scroll_mouse(self, event):
for l in self.lists:
l.yview_scroll(int(-1*(event.delta/120)), 'units')
return 'break'
def curselection(self):
return self.lists[0].curselection()
def delete(self, first, last=None):
for l in self.lists:
l.delete(first, last)
def get(self, first, last=None):
result = []
for l in self.lists:
result.append(l.get(first,last))
if last: return apply(map, [None] + result)
return result
def index(self, index):
self.lists[0].index(index)
def insert(self, index, *elements):
for e in elements:
for i, l in enumerate(self.lists):
l.insert(index, e[i])
def size(self):
return self.lists[0].size()
def see(self, index):
for l in self.lists:
l.see(index)
def selection_anchor(self, index):
for l in self.lists:
l.selection_anchor(index)
def selection_clear(self, first, last=None):
for l in self.lists:
l.selection_clear(first, last)
def selection_includes(self, index):
return self.lists[0].selection_includes(index)
def selection_set(self, first, last=None):
for l in self.lists:
l.selection_set(first, last)
class ClassOne:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master)
self.create_elements()
self.frame.pack()
def create_elements(self):
search_button = tk.Button(self.frame, text = "Launch searches", command = \
self.call_other_classes)
search_button.grid(row = 2, column = 0, padx = 20, pady = 10)
exit_button = tk.Button(self.frame, text = "Exit", command = self.master.quit)
exit_button.grid(row = 2, column = 1, padx = 20, pady = 10)
def call_other_classes(self):
self.classes_list = []
self.classes_list.append(ClassTwo(self.master))
self.classes_list.append(ClassThree(self.master))
class ClassTwo:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(tk.Toplevel(self.master))
self.frame.pack()
self.create_elements()
self.fill_image_listbox()
def create_elements(self):
#placement of the custom MultiListbox
self.available_images_lb = MultiListbox(self.frame, (('stuff1', 0), ('stuff1', 0), \
('stuff1', 0), ('stuff1', 0), ('stuff1', 0) ))
self.available_images_lb.grid(row = 1, column = 1)
self.available_images_lb.bind('<<ListboxSelect>>', self.print_stuff_two)
#Button
exit_button = tk.Button(self.frame, text = "Quit", command = self.frame.quit)
exit_button.grid(row = 2, column = 1, padx = 20, pady = 10)
def fill_image_listbox(self):
image_info = [5*['ABCD'],5*['EFGH'],5*['JKLM'],5*['NOPQ'],5*['RSTU'], 5*['VWXY']]
for item in image_info:
self.available_images_lb.insert('end', item)
def print_stuff_two(self, event):
print('Class Two active')
class ClassThree:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(tk.Toplevel(self.master))
self.create_elements()
self.frame.pack()
self.fill_imageparts_listbox()
def create_elements(self):
self.image_parts_info_lb = MultiListbox(self.frame, (('stuff1', 0), ('stuff1', 0), \
('stuff1', 0), ('stuff1', 0), ('stuff1', 0) ))
self.image_parts_info_lb.grid(row = 1, column = 1)
self.image_parts_info_lb.bind('<<ListboxSelect>>', self.print_stuff_three)
def fill_imageparts_listbox(self):
self.image_parts_info_lb.delete(0, 'end')
image_part_info = [5*['1234'],5*['5678'],5*['91011']]
for item in image_part_info:
self.image_parts_info_lb.insert('end', item)
def print_stuff_three(self, event):
print('Class Three active')
def main():
root = tk.Tk()
root.title('Image Viewer')
root.geometry('500x150+300+300')
my_class_one = ClassOne(root)
root.mainloop()
if __name__ == "__main__":
main()
我会启动一个简单的图像查看器并使用 Pillow 来突出显示图像中的区域,而不是打印功能。该功能已实现且运行良好,只是绑定到自定义 Listbox 的函数无法正常运行。
我愿意接受任何意见。另外,如果您对编码模式有任何建议,请随时告诉我。
【问题讨论】:
-
谢谢到目前为止,我已经阅读了第一个线程(见我的代码)显然没有找到第二个。我删除了绑定,除了 MouseWheel。我不明白的是,我怎样才能在其中一个类中触发一个函数,例如启动我的图像查看器?介意回答详细一点吗?
-
我在
ClassTwo.create_elements()中发现了一个问题。将bind()的调用更改为self.available_images_lb.bind('<<ListboxSelect>>', self.print_stuff_two),这将避免此时调用self.print_stuff_two()(这会导致TypeError: print_stuff_two() missing 1 required positional argument: 'event')。 -
是的,谢谢提示,也会在帖子代码中改一下。这只是使其正常工作的众多尝试之一。我还尝试了类似
self.available_images_lb.bind('<<ListboxSelect>>', lambda e, s= self: self.print_stuff_two(e))的方法。遗憾的是,这也没有解决问题。 -
@n00by0815 " 它绑定到 MultiListbox。":你误会了,
.available_images_lb.bind('<<ListboxSelect>>'绑定到Frame。Frame永远不会收到'<<ListboxSelect>>'事件。您已将callback传递给MultiListbox,它会从def _select(...内部调用。