簡體   English   中英

在tkinter中使用Queue(線程,Python 3)

[英]Using Queue with tkinter (threading, Python 3)

我在Python 3中有一個腳本,我正在嘗試使用tkinter為其創建GUI。

這是工作代碼的完整示例:

#!/usr/bin/python
# coding: utf-8

import pickle
import openpyxl

from tkinter import *
import threading
import queue


class Worker():

    def __init__(self):
        self.one_name_list = []
        self.dic = {}

        self.root = Tk()
        self.root.title("GUI Python")
        self.root.geometry("820x350")

        self.thread_queue = queue.Queue()

        self.btn1 = Button(text="start counting", width = '20', height = '1', background = "#555", foreground = "#ccc", command=self.start_working)
        self.btn1.grid(row=0, column=0, columnspan=2, ipadx=10, ipady=6, padx=5, pady=5, sticky=N)
        self.btn2 = Button(text="stop counting", width = '20', height = '1', background = "#555", foreground = "#ccc", command=self.stop_running)
        self.btn2.grid(row=1, column=0, columnspan=2, ipadx=10, ipady=6, padx=5, pady=5, sticky=N)
        self.btn5 = Button(text="clear window", width = '10', height = '1', background = "#555", foreground = "#ccc", command=self.tex_clear)
        self.btn5.grid(row=3, column=0, columnspan=2, ipadx=10, ipady=6, padx=5, pady=5, sticky=N)

        self.tex = Text(self.root, width = 72, height = 20, font="Verdana 10", wrap=WORD)
        self.tex.grid(row=0, column=2, rowspan=4, ipadx=10, ipady=6, padx=5, pady=5)

        self.S = Scrollbar(self.root, orient="vertical", command=self.tex.yview)
        self.S.grid(row=0, column=4, rowspan=4,  ipady=143, pady=5, sticky=W)
        self.tex.config(yscrollcommand=self.S.set)

        self.root.after(100, self.listen_for_result)

        self.root.mainloop()


    def read_from_pickle_file(self, filename):
        """ Reads python object from pickle file. """

        # with open(filename, 'rb') as handle:
        #     obj = pickle.load(handle)

        self.thread_queue.put('Got list file.\n')
        return True

    def get_boxes(self, xlsx_filename, txt_filename=None):

        pass # does some job
        self.thread_queue.put('Got boxes list.\n')

    def tex_clear(self):

        self.tex.delete('1.0', END)
        self.tex.see("end")

    def stop_running(self):

        pass # stops somehow\

    def _print(self, text):
        self.tex.insert(END, text)
        self.tex.see("end")

    def start_working(self):

        t = threading.Thread(target=self.start_working_2)
        t.start()

    def start_working_2(self):

        self.one_name_list = self.read_from_pickle_file('1.pickle')
        self.root.after(100, self.listen_for_result)

        self.boxes_list = self.get_boxes('1.xlsx')
        self.root.after(100, self.listen_for_result)

        self.thread_queue.put('Getting files\n')
        self.root.after(100, self.listen_for_result)

    def listen_for_result(self):
        """ Check if there is something in the queue. """

        try:
            self.res = self.thread_queue.get(0)
            self._print(self.res)
        except queue.Empty:
            self.root.after(100, self.listen_for_result)


if __name__ == '__main__':

    se = Worker()

您可以運行它並查看工作窗口。

我是tkinter的新手,所以我有幾個問題,將不勝感激。 謝謝。

此GUI的想法-有3個按鈕-開始運行,停止運行和清除文本窗口。 文本窗口-應該替代控制台-所有消息都應在文本窗口而不是控制台中打印。

現在,我正在使用隊列來打印消息。 但是我想我使用的方式有誤-因為每次在其中放置東西后,我都需要手動檢查隊列。

因此,問題:

1)有沒有一種方法可以一直自動檢查隊列-並將進入隊列的所有內容立即打印到文本窗口,無論它來自哪個線程? (我在每次放置東西之后都可以忍受每次檢查隊列,但是會有幾個函數無法預測他們將多少東西發送到隊列中-因此我將無法檢查隊列中的未知對象次數。)


如果您回答第一個問題,我將考慮回答的問題。 其他問題是可選的。 謝謝。

2)我可以正確啟動GUI嗎? 應該在init ()還是其他地方?

3)如何隱藏控制台窗口? (嘗試重命名為.pyw-控制台和GUI均未顯示。嘗試將self.root.withdraw()放在self.root = Tk()之后-結果:控制台顯示,GUI-未顯示。)

4)此代碼中是否有笨拙或愚蠢的地方(GUI,線程,隊列)? 正如我所說的-我是tkinter的新手,並由幾本手冊編寫了此代碼-因此我可能會誤解其中的一部分或全部,並且以錯誤的方式進行。

在此先感謝您的幫助。

它看起來很簡單:在此函數中

def listen_for_result(self):
        """ Check if there is something in the queue. """

        try:
            self.res = self.thread_queue.get(0)
            self._print(self.res)
        except queue.Empty:
            self.root.after(100, self.listen_for_result)

應該再增加一個調用-即使在成功打印之后。 此后-我可以從任何地方發送文本到隊列,並且在將文本發送到隊列后無需調用此函數就可以打印文本。

def listen_for_result(self):
        """ Check if there is something in the queue. """

        try:
            self.res = self.thread_queue.get(0)
            self._print(self.res)
            self.root.after(100, self.listen_for_result)
        except queue.Empty:
            self.root.after(100, self.listen_for_result)

所以現在

self.thread_queue.put('Getting files\n')

可以在任何線程中使用。 代替

 self.thread_queue.put('Getting files\n')
 self.root.after(100, self.listen_for_result)

像以前一樣雙線。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM