简体   繁体   English

每秒刷新 GTK3 python 中的小部件/网格

[英]Refresh A Widget/Grid in GTK3 python every second

So this is my first GTK3 python app, and what I am trying to do is display the track art, song name, and artist of my currently playing Spotify song.所以这是我的第一个 GTK3 python 应用程序,我想做的是显示我当前播放的 Spotify 歌曲的曲目艺术、歌曲名称和艺术家。

This works, but I need it to refresh every few seconds so the app will switch the song info.这可行,但我需要它每隔几秒刷新一次,以便应用程序切换歌曲信息。

This is my code so far:到目前为止,这是我的代码:

import gi
import os
import subprocess
import urllib.request as ur
from PIL import Image

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, GdkPixbuf
if os.path.exists("art.png"):
    os.remove("art.png")
else:
    print("")

class Window(Gtk.Window):
    def __init__(self):
        super().__init__(title="current song playing")
        artist = subprocess.Popen("playerctl metadata artist", shell=True, stdout=subprocess.PIPE).communicate()[0]
        artist = artist.strip().decode('ascii')

        print(Gtk.events_pending())

        song   = subprocess.Popen("playerctl metadata title", shell=True, stdout=subprocess.PIPE).communicate()[0]
        song   = song.strip().decode('ascii')

        art    = subprocess.Popen("playerctl metadata mpris:artUrl", shell=True, stdout=subprocess.PIPE).communicate()[0]
        art    = art.strip().decode('ascii')

        ur.urlretrieve(art, "art.png")
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
        filename="art.png",
        width=200,
        height=200,
        preserve_aspect_ratio=True)
        self.image = Gtk.Image.new_from_pixbuf(pixbuf)

        self.main_box = Gtk.Box()
        self.label = Gtk.Label()
        self.label.set_markup("<big>%s - %s</big>\n" % (artist, song))
        self.label.set_justify(Gtk.Justification.CENTER)

        self.label.set_hexpand(True)
        self.image.set_hexpand(True)
        self.label.set_vexpand(True)
        self.image.set_vexpand(True)

        grid = Gtk.Grid()
        grid.add(self.image)
        grid.attach_next_to(self.label, self.image, Gtk.PositionType.BOTTOM, 1, 2)

        self.main_box.pack_start(self.image, True, True, 0)
        self.main_box.pack_start(self.label, True, True, 0)

        self.add(grid)
        self.show_all()

def main():
    win=Window()
    win.show()
    win.connect("destroy", Gtk.main_quit)
    Gtk.main()

if __name__ == "__main__":
    main()

If tried different methods of doing this, and looking at the docs, neither have worked/helped.如果尝试了不同的方法来执行此操作,并查看文档,都没有工作/帮助。

gtk4 drawing-modelgtk4绘图模型

There are multiple ways to drive the clock, at the lowest level you can request a particular phase with gdk_frame_clock_request_phase() which will schedule a clock beat as needed so that it eventually reaches the requested phase.有多种方法可以驱动时钟,在最低级别,您可以使用 gdk_frame_clock_request_phase() 请求特定阶段,这将根据需要安排时钟节拍,以便最终达到请求的阶段。 However, in practice most things happen at higher levels:然而,在实践中,大多数事情都发生在更高的层次上:

  • If you are doing an animation, you can use gtk_widget_add_tick_callback() which will cause a regular beating of the clock with a callback in the Update phase until you stop the tick.如果您正在制作动画,则可以使用 gtk_widget_add_tick_callback() ,这将导致时钟定期跳动并在更新阶段回调,直到您停止滴答。
  • If some state changes that causes the size of your widget to change you call gtk_widget_queue_resize() which will request a Layout phase and mark your widget as needing relayout.如果某些状态更改导致您的小部件的大小发生变化,您调用 gtk_widget_queue_resize() 它将请求布局阶段并将您的小部件标记为需要重新布局。
  • If some state changes so you need to redraw some area of your widget you use the normal gtk_widget_queue_draw() set of functions.如果某些状态发生变化,因此您需要重绘小部件的某些区域,则使用普通的 gtk_widget_queue_draw() 函数集。 These will request a Paint phase and mark the region as needing redraw.这些将请求 Paint 阶段并将该区域标记为需要重绘。

GLib provides timeout_add to run a task every x time. GLib 提供timeout_add以每 x 次运行一个任务。 If the method called by timeout_add returns True, will be called again after the defined timeout如果timeout_add调用的方法返回 True,将在定义的 timeout 后再次调用

Your code would looks something like:您的代码将类似于:

import gi
import os
import subprocess
import urllib.request as ur

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, GdkPixbuf
if os.path.exists("art.png"):
    os.remove("art.png")


class MainWindow(Gtk.Window):

    def __init__(self):
        super().__init__(title="current song playing")

        self.main_box = Gtk.Box()
        self.label = Gtk.Label()
        self.label.set_justify(Gtk.Justification.CENTER)

        self.image = Gtk.Image()
        self.label.set_hexpand(True)
        self.image.set_hexpand(True)
        self.label.set_vexpand(True)
        self.image.set_vexpand(True)
        self.art_url = None

        grid = Gtk.Grid()
        grid.add(self.image)
        grid.attach_next_to(self.label, self.image, Gtk.PositionType.BOTTOM, 1, 2)

        self.main_box.pack_start(self.image, True, True, 0)
        self.main_box.pack_start(self.label, True, True, 0)

        self.add(grid)
        self.show_all()

    def update_image(self):
        artist = subprocess.Popen("playerctl metadata artist", shell=True, stdout=subprocess.PIPE).communicate()[0]
        artist = artist.strip().decode('utf8')
        song   = subprocess.Popen("playerctl metadata title", shell=True, stdout=subprocess.PIPE).communicate()[0]
        song   = song.strip().decode('utf8')
        art    = subprocess.Popen("playerctl metadata mpris:artUrl", shell=True, stdout=subprocess.PIPE).communicate()[0]
        art    = art.strip().decode('utf8')
        if art and art != self.art_url:
            print("downloading %s" % art)
            self.art_url = art
            ur.urlretrieve(art, "art.png")
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                filename="art.png",
                width=200,
                height=200,
                preserve_aspect_ratio=True)
            self.image.set_from_pixbuf(pixbuf)

        self.label.set_markup("<big>%s - %s</big>\n" % (artist, song))
        return True

    def start_timer(self):
        GLib.timeout_add(1000, self.update_image)


win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
win.start_timer()
Gtk.main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM