Обработка объектов GTK в потоках в Python

я создаю приложение на Python, которое использует GTK для создания пользовательского интерфейса, и меня немного смущает обработка объектов GTK в потоках, например, объекта GtkProgressBar.

Вот контекст:

Я пытаюсь выполнить загрузку в основном потоке и добавляю GObject.timeout_add, чтобы пульсировать полосу, пока загрузка не закончится. Но после первого импульса интерфейс завис.

Пока все в порядке, поток завис до завершения загрузки, поэтому любой компонент будет обновлен. Решение: создать новый поток.

Я создал эту новую тему, чтобы сделать загрузку и другие вещи. В этой теме я получаю индикатор выполнения для обновлений. Но пока идет загрузка, и я добавляю GObject.timeout_add, чтобы пульсировать полосу, пользовательский интерфейс снова завис. Новое решение: создайте третий поток.

Итак, мои темы выглядят так:

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

Итак, в Thread 1 я делаю другие вещи и обновляю пользовательский интерфейс, а в Thread 2 я делаю загрузку и добавляю GObject.timeout_add, и там я могу обновить индикатор выполнения. А в Thread 1 я присоединяюсь к Thread 2

Я обрабатываю объекты Gtk, используя функцию 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