在 Python GTK 中从 ListBox(绑定到 ListStore)获取选定对象

Get selected object from ListBox (binded to ListStore) in Python GTK

我用 ListBox(作为播放列表)制作了一个简单的 GTK 音乐播放器。

这是 GObject class,我用它绑定到 ListBox(使用 bind_model() 方法)和 ListStore。

import eyed3
from gi.repository import Gio, GObject

class Song(GObject.GObject):

    path = GObject.Property(type=str)
    name = GObject.Property(type=str)

    def __init__(self, path):
        GObject.GObject.__init__(self)
        self.path = path
        self.file = eyed3.load(path)
        self.name = self

    def __str__(self):
        return str(self.file.tag.artist) + ' - ' + str(self.file.tag.title)


playlist = Gio.ListStore().new(Song)

这就是我将 ListStore 绑定到 ListBox 的方式:

play_listbox.connect('row-selected', self.on_row_selected)

playlist.append(Song('/home/user/Downloads/Some album/01 - Song1.mp3'))
playlist.append(Song('/home/user/Downloads/Some album/02 - Song2.mp3'))

play_listbox.bind_model(playlist, self.create_song_label)

def create_song_label(self, song):
    return Gtk.Label(label=song.name)

到目前为止,一切正常。

问题是:是否可以根据选择检索歌曲对象(存储在播放列表中)?要检索存储在该对象中的路径 属性?

如果不能,是否可以至少检索选择文本?用

试试这个
def on_row_selected(self, container, row):
    print(row.widget.label)

给出回溯:

Traceback (most recent call last):
  File "/home/user/Documents/App/player.py", line 45, in on_row_selected
    print(row.widget.label) # or data, value, text - nothing works
RuntimeError: unable to get the value

行变量的类型是

<Gtk.ListBoxRow object at 0x7f9fe7604a68 (GtkListBoxRow at 0x5581a51ef7d0)>

所以我认为上面的代码应该很有魅力......但它没有。

非常感谢您提供的任何帮助!

因此您需要将选择分配给:

treeview_selection = treeview.get_selection()    

并将其与 'changed' 信号连接:

treeview_selection.connect('changed', on_tree_selection_changed)

然后您可以通过以下方式获取所需的数据:

def on_tree_selection_changed(self, treeview):
    model, treeiter = treeview.get_selected()
    if treeiter is not None:
        print(model[treeiter][0]) # you should a list index to get the data you require for each row - first column = [0], second column = [1] etc.

我建议您阅读 pgi docs and also the python Gtk docs

Is it possible to retrieve Song object (stored in playlist) based on selection? To retrieve path property stored in that object?

def on_row_selected(self, container, row):
    song = playlist.get_item(row.get_index())

If not, is it possible to at least retrieve selection text?

def on_row_selected(self, container, row):
    name = row.get_child().get_text()

这是一个例子。如果你必须处理多个选择,你也可以使用 selected-rows-changed 信号:

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio, GObject
import sys

class Song(GObject.GObject):

    path = GObject.Property(type=str)
    name = GObject.Property(type=str)

    def __init__(self, path, name):
        GObject.GObject.__init__(self)
        self.path = path
        self.name = name
class GUI:

    def __init__(self):        
        self.playlist = Gio.ListStore()
        self.playlist.append(Song("path1", "name1"))
        self.playlist.append(Song("path2", "name2"))
        self.playlist.append(Song("path3", "name3"))

        play_listbox = Gtk.ListBox()
        play_listbox.set_selection_mode(Gtk.SelectionMode.SINGLE)
        play_listbox.bind_model(self.playlist, self.create_widget_func)
        play_listbox.connect('row-selected', self.on_row_selected_1)
        play_listbox.connect('row-selected', self.on_row_selected_2)
        play_listbox.connect('selected-rows-changed', self.on_selected_rows_changed)

        window = Gtk.Window()
        window.add(play_listbox)
        window.connect("destroy", self.on_window_destroy)
        window.show_all()

    def create_widget_func(self, song):
        return Gtk.Label(label = song.name)

    def on_row_selected_1(self ,container, row):
        print("on_row_selected_1")
        song = self.playlist.get_item(row.get_index())
        print(song.path)

    def on_row_selected_2(self ,container, row):
        print("on_row_selected_2")
        print(row.get_child().get_text())

    def on_selected_rows_changed(self, container):      
        print("on_selected_rows_changed", len(container.get_selected_rows()), "item(s) selected")
        for row in container.get_selected_rows():
            song = self.playlist.get_item(row.get_index())
            print(song.name, song.path)
        print("---")

    def on_window_destroy(self, window):
        Gtk.main_quit()

def main():

    app = GUI()
    Gtk.main()

if __name__ == "__main__":
    sys.exit(main())