การจัดการวัตถุ GTK บนเธรดใน Python

ฉันกำลังสร้างแอปพลิเคชันใน Python ที่ใช้ GTK เพื่อสร้าง UI และฉันสับสนเล็กน้อยเกี่ยวกับการจัดการ GTK Objects บน Threads เช่น วัตถุ GtkProgressBar

นี่คือบริบท:

ฉันพยายามดาวน์โหลดบน Main Thread และฉันเพิ่ม GObject.timeout_add เพื่อกะพริบแถบจนกว่าการดาวน์โหลดจะสิ้นสุด แต่หลังจากชีพจรแรก UI ก็หยุดนิ่ง

จนกว่าจะตกลง เธรดจะค้างจนกว่าการดาวน์โหลดจะเสร็จสิ้น ดังนั้นส่วนประกอบใดๆ จะได้รับการอัปเดต วิธีแก้ไข: สร้างเธรดใหม่

ฉันได้สร้างหัวข้อใหม่นี้เพื่อทำการดาวน์โหลดและเรื่องอื่น ๆ ในกระทู้นี้ ฉันได้รับแถบความคืบหน้าเพื่อทำการอัปเดต แต่ในขณะที่การดาวน์โหลดกำลังทำงานอยู่ และฉันเพิ่ม GObject.timeout_add เพื่อให้แถบกะพริบ UI ก็ค้างอีกครั้ง แนวทางแก้ไขใหม่: สร้างเธรดที่สาม

ดังนั้นเธรดของฉันจึงมีลักษณะเช่นนี้:

Main-Thread
    '---- Thread 1
             '------Thread 2

ดังนั้นในวันที่ Thread 1 ฉันจึงทำอย่างอื่นและอัปเดต UI ในขณะที่ใน Thread 2 ฉันจะดาวน์โหลดและเพิ่ม GObject.timeout_add และในนั้น ฉันสามารถอัปเดตแถบความคืบหน้าได้ และใน Thread 1 ฉันจะเข้าร่วม Thread 2

ฉันจัดการ Gtk Objects โดยใช้ฟังก์ชัน GObject.idle_add

แต่ฉันสับสนมากว่าทำไมการดาวน์โหลดและการอัปเดตแถบความคืบหน้าจึงทำงานได้ดีบน Thread 2 และไม่ใช่บน Thread 1

บางคนสามารถอธิบายให้ฉันฟังว่าทำไมถึงเป็นเช่นนั้น หรือถ้าฉันพลาดบางอย่างเกี่ยวกับการจัดการวัตถุ GTK

ขอบคุณ


person Vitor Villar    schedule 29.10.2015    source แหล่งที่มา


คำตอบ (1)


หากคุณบล็อกลูปหลักของ Gtk หน้าต่างและวิดเจ็ตจะไม่ตอบสนอง นั่นเป็นสาเหตุที่คุณไม่สามารถทำการดาวน์โหลดในเธรดหลักได้ การอัปเดต Gtk.ProgressBar จากเธรดการดาวน์โหลดอาจทำงานได้ ขึ้นอยู่กับวิธีการใช้งาน

นี่เป็นวิธีหนึ่งในการดาวน์โหลดบางอย่างและมี ProgressBar ที่ใช้งานได้:

from gi.repository import Gtk, GLib
import threading
import urllib.request

class Window(Gtk.Window):
    def __init__(self):
        super().__init__()
        self.connect('delete-event', Gtk.main_quit)
        self.progress = Gtk.ProgressBar()
        self.add(self.progress)
        self.show_all()

        # Start download
        self.thread = threading.Thread(target=self.download)
        self.thread.start()
        GLib.timeout_add_seconds(1, self.download_pulse)

    def download(self):
        urllib.request.urlretrieve('<link>')

    def download_pulse(self):
        if self.thread.is_alive():
            self.progress.pulse()
            return True
        return False

win = Window()
Gtk.main()
person elya5    schedule 30.10.2015