Как опросить MPD из GTK с помощью mpd.idle () без блокировки - PullRequest
0 голосов
/ 29 января 2020

Я хочу использовать функцию ожидания MPD, чтобы ждать каких-либо изменений, а затем отображать их в GTK GUI, используя Python. Проблема в том, что GUI, кажется, блокируется и перестает отвечать на запросы, когда я использую функцию ожидания MPD (при смене песен окно GTK перестает отвечать на запросы). Когда я удаляю self.mpd.idle(), это работает, но затем функция продолжает работать все время, что я считаю ненужным.

Каков наилучший способ решить эту проблему?

Не работает Мой первоначальный подход:

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib
from mpd import MPDClient

class GUI:
    def __init__(self):
        self.mpd = MPDClient()
        self.mpd.timeout = 10
        self.mpd.connect("localhost", 6600)

        self.window = Gtk.Window()
        self.window.connect("delete-event", Gtk.main_quit)
        self.window.show_all()

        GLib.idle_add(self.get_current_song)
        Gtk.main()

    def get_current_song(self):
        self.mpd.idle()
        print(self.mpd.currentsong())
        return True

app = GUI()

Не работает Мой второй подход с использованием this . Все еще получаю те же результаты.

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib
from mpd import MPDClient
import threading

class GUI:
    def __init__(self):
        self.mpd = MPDClient()
        self.mpd.timeout = 1
        self.mpd.connect("localhost", 6600)

        self.window = Gtk.Window()
        self.window.connect("delete-event", Gtk.main_quit)

        self.window.show_all()
        self.thread = threading.Thread(target=self.idle_loop)
        self.thread.daemon = True
        self.thread.start()
        Gtk.main()

    def get_songs(self):
        print(self.mpd.currentsong())
        self.mpd.idle()
        return True

    def idle_loop(self):
        GLib.idle_add(self.get_songs)

app = GUI()

WORKING Выход из функции GLib.idle_add(), похоже, является решением. Но я не знаю, является ли это «правильным» способом. Он чувствует себя неправильно, не зная, почему GLib.idle_add() испортил его и не использовал, так как это упомянуто в документации.

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib
from mpd import MPDClient
import threading

class GUI:
    def __init__(self):
        self.mpd = MPDClient()
        self.mpd.timeout = 1
        self.mpd.connect("localhost", 6600)

        self.window = Gtk.Window()
        self.window.connect("delete-event", Gtk.main_quit)

        self.window.show_all()
        self.thread = threading.Thread(target=self.get_songs)
        self.thread.daemon = True
        self.thread.start()
        Gtk.main()

    def get_songs(self):
        self.mpd.idle()
        print(self.mpd.currentsong())

app = GUI()

1 Ответ

0 голосов
/ 29 января 2020

Давайте используем модуль threading здесь. Как описано в этой статье: https://pygobject.readthedocs.io/en/latest/guide/threading.html, мы можем сделать следующий код:

import gi
from threading import Thread
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib
from mpd import MPDClient

class GUI:
    def __init__(self):
        self.mpd = MPDClient()
        self.mpd.timeout = 10
        self.mpd.connect("localhost", 6600)

        self.window = Gtk.Window()
        self.window.connect("delete-event", Gtk.main_quit)
        self.window.show_all()

        thread = Thread(target=self.get_current_song, args=())
        thread.start()
        Gtk.main()

    def get_current_song(self):
        self.mpd.idle()
        print(self.mpd.currentsong())
        return True

app = GUI()
...