在python 2.7中从线程化的Tk实例中打开菜单

时间:2019-05-12 12:44:36

标签: python python-2.7 tkinter

当我尝试运行该代码时,列表内的右键菜单将不会打开。 如果我将窗口从线程中移出,它将起作用”,但是在该类的实现中,它必须位于线程中。

将窗口移出线程是可行的,但是我需要在窗口中用于其他功能。

from Tkinter import *
from threading import *



class scrollbar_list:
    def __init__(self, frame, title):
        self.selected_item = ''
        self.colored = {}
        self.search_list = []
        self.full_list = []
        self.frame = frame
        self.title = Label(frame, text=title).grid(row=0, column=0, columnspan=3, sticky='EW')

        self.search_frame = Frame(frame)
        self.search_frame.grid(row=1, columnspan=3, sticky='EW')

        self.search_entry = Entry(self.search_frame, width=26)
        self.search_entry.grid(row=0, column=1, columnspan=2, sticky='EW')
        self.search_button = Button(self.search_frame, text='Search', width=9, command=self.search)
        self.search_button.grid(row=0, column=3, sticky='E')
        self.search_entry.bind('<Return>', self.start_search)

        self.listbox_Frame = Frame(self.frame)
        self.listbox_Frame.grid(row=3, column=0)
        self.scrollbar = Scrollbar(self.listbox_Frame)
        self.scrollbar.grid(row=2, column=1, sticky="NS")
        self.listbox = Listbox(self.listbox_Frame, width=35)
        self.listbox.grid(row=2, column=0, sticky="NS")

        self.scrollbar.config(command=self.listbox.yview)
        self.listbox.config(yscrollcommand=self.scrollbar.set)

        self.build_menu()

    def refresh(self):
        self.full_list.sort()
        self.listbox.delete(0, END)
        self.search_entry.delete(0, 'end')
        for line in self.full_list:
            self.listbox.insert(END, line)
        self.color_Table()

    def set_color(self, ITEM, COLOR):
        self.colored[ITEM] = {'bg': COLOR}

    def un_color(self, ITEM):
        self.colored.pop(ITEM, None)

    def color_Table(self):
        for item in self.colored:
            self.listbox.itemconfig(self.listbox.get(0, END).index(item), self.colored[item])

    def contain(self, query):
        for line in self.listbox.get(0, END):
            if query == line:
                return True
        return False

    def get_item(self, item):
        target = self.listbox.get(item)
        return target

    def insert(self, line):
        self.listbox.insert(END, line)
        self.full_list.append(line)
        self.sort()

    def remove(self, item):
        target = self.listbox.get(item)
        self.listbox.delete(item)
        for line in self.full_list:
            if line == target:
                self.full_list.remove(line)
        self.sort()

    def sort(self):
        self.list = []
        self.full_list.sort()
        for line in self.listbox.get(0, END):
            self.list.append(line)
        self.list.sort()
        self.listbox.delete(0, END)
        for line in self.list:
            self.listbox.insert(END, line)

    def start_search(self, EVENT):
        self.search()

    def search(self):
        query = self.search_entry.get()
        list = []
        for line in self.listbox.get(0, END):
            self.list.append(line)
            if query.lower() in line.lower():
                list.insert(0, line)
        list.sort()
        self.listbox.delete(0, END)
        for line in list:
            self.listbox.insert(END, line)
        self.search_entry.delete(0, 'end')

    def double_Click_Enable(self, FUNCTION):
        self.listbox.bind("<Double-Button-1>", FUNCTION)

    def build_menu(self):
        self.right_click_menu = Menu(self.listbox, tearoff=0)
        self.listbox.bind("<Button-3>", self.right_click_menu_bind)
        self.right_click_menu.add_command(label="refresh", command=self.refresh)

    def right_click_menu_bind(self, event):
        try:
            self.right_click_menu.tk_popup(event.x_root, event.y_root, 0)
            try:
                self.selected_item = self.listbox.get(self.listbox.curselection())
            except:
                pass
        finally:
            self.right_click_menu.grab_release()

if __name__ == '__main__':
    main=Tk()
    list=scrollbar_list(main,'hello')
    for i in range(101):
        list.insert('line -{}'.format(i))
    thread = Thread(target=main.mainloop)
    thread.start()
    thread.join()

除未打开的菜单外,所有其他功能均正常工作,因此我所需要的只是找到一种打开方法

编辑:

已解决,谢谢Nullman,这确实是一个很棒的解决方案,出于某种原因,我真的不认为可以像这样运行它

1 个答案:

答案 0 :(得分:0)

您不能在一个线程中创建Tk,而在另一个线程中运行它。制作一个可以开始整个过程​​并在线程中使用它的函数,如下所示:

def run():
    main = Tk()
    list = scrollbar_list(main, 'hello')
    for i in range(101):
        list.insert('line -{}'.format(i))
    main.mainloop()
if __name__ == '__main__':
    thread = Thread(target=run)
    thread.start()
    thread.join()