如何创建包含文本和图像的 Python GTK3 TreeView 列

问题描述 投票:0回答:1

我有一个带有 TreeView 的 GTK3 Python 程序,我想要一个主要包含文本的列,但也可以包含图像。我一直在询问 ChatGPT,但这已经是我能得到的最接近的了:

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GdkPixbuf

class TreeViewExample(Gtk.Window):
    def __init__(self):
        super().__init__(title="TreeView Table Example")
        self.set_default_size(400, 300)

        # Create a ListStore model with two columns
        self.model = Gtk.ListStore(object, str)  # Using 'object' type for the first column
        self.model.append([self.load_image("path/to/your/image.png"), "Value A"])  # First row with an image
        self.model.append(["Row 2", "Value B"])  # Second row with text
        self.model.append(["Row 3", "Value C"])

        # Create a TreeView
        self.treeview = Gtk.TreeView(model=self.model)

        # Create the first column with custom cell renderers
        column1 = Gtk.TreeViewColumn("Column 1")
        self.treeview.append_column(column1)

        # Create a text renderer for the first column
        cell_renderer_text = Gtk.CellRendererText()
        column1.pack_start(cell_renderer_text, expand=True)
        column1.add_attribute(cell_renderer_text, "text", 1)  # Display text
        column1.set_cell_data_func(cell_renderer_text, self.render_first_column)  # Custom rendering function

        # Create an image renderer for the first column
        cell_renderer_pixbuf = Gtk.CellRendererPixbuf()
        column1.pack_start(cell_renderer_pixbuf, expand=True)
        column1.add_attribute(cell_renderer_pixbuf, "pixbuf", 0)  # Display image

        # Create the second column with a text renderer
        cell_renderer2 = Gtk.CellRendererText()
        column2 = Gtk.TreeViewColumn("Column 2", cell_renderer2, text=1)
        self.treeview.append_column(column2)

        # Add the TreeView to the window
        self.add(self.treeview)

    def load_image(self, image_path):
        # Load an image from file and return a GdkPixbuf.Pixbuf
        try:
            pixbuf = GdkPixbuf.Pixbuf.new_from_file(image_path)
            return pixbuf
        except GLib.Error:
            print(f"Error loading image from {image_path}")
            return None

    def render_first_column(self, column, cell, model, iter_, data=None):
        # Custom rendering function for the first column
        value = model.get_value(iter_, 0)
        if isinstance(value, GdkPixbuf.Pixbuf):
            cell.set_property("pixbuf", value)  # Display the image
        else:
            cell.set_property("text", str(value))  # Display text

if __name__ == "__main__":
    app = TreeViewExample()
    app.connect("destroy", Gtk.main_quit)
    app.show_all()
    Gtk.main()

第一个模型列是一个“对象”,因此它可以是 str 或 pixbuf,这似乎是正确的。但是set_cell_data_func的调用有一个cell_renderer_text参数,所以当调用self.render_first_column函数时,cell参数总是看起来是一个CellRendererText,所以当值为pixbuf并且运行命令时:

cell.set_property("pixbuf", value)

如果失败:

builtins.TypeError: object of type `GtkCellRendererText' does not have property `pixbuf'

这篇文章(如何在 GtkTreeview 中制作带有字符串和 pixbuf 的列?)似乎在不使用 cell_data_func 的情况下将两个 CellRenderer 放在一起,但我在这些方面的尝试也没有成功。

有人可以帮我把它变成工作代码吗?

我也希望能帮助您理解column.pack_start 和column.add_attribute 方法。看起来 pack_start 方法是为了在同一个单元格中拥有多个 CellRenderer,但是它如何知道使用哪一个呢?

谢谢, 杰夫

python treeview gtk3
1个回答
0
投票

我能够使用 pack_start 从同一列中显示的模型中获取两列数据,但它不会将它们放在相同的位置 - 第一项出现在左侧,第二项出现在右侧(有点像列中的两列)。看起来是这样的:

这不是很有帮助...我希望图像出现在与其他行中的文本相同的位置。

这是产生此输出的代码(您必须提供适当的图像):

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GdkPixbuf

class TreeViewExample(Gtk.Window):
    def __init__(self):
        super().__init__(title="TreeView Table Example")
        self.set_default_size(400, 300)

        # Create a ListStore model with two columns
        self.model = Gtk.ListStore(str, str, GdkPixbuf.Pixbuf)  # Using 'object' type for the first column
        self.model.append(["", "Value A", self.load_image("mypic.png")])  # First row with an image
        self.model.append(["Row 2", "Value B", None])
        self.model.append(["Row 3", "Value C", None])

        # Create a TreeView
        self.treeview = Gtk.TreeView(model=self.model)

        # Create the first column
        column1 = Gtk.TreeViewColumn("Column 1")
        self.treeview.append_column(column1)
        
        cell_renderer_pixbuf = Gtk.CellRendererPixbuf()
        column1.pack_start(cell_renderer_pixbuf, expand=True);
        column1.add_attribute(cell_renderer_pixbuf, "pixbuf", 2);

        cell_renderer_text = Gtk.CellRendererText()
        column1.pack_start(cell_renderer_text, expand=True);
        column1.add_attribute(cell_renderer_text, "text", 0);

        # Create the second column with another text renderer
        cell_renderer2 = Gtk.CellRendererText()
        column2 = Gtk.TreeViewColumn("Column 2", cell_renderer2, text=1)
        self.treeview.append_column(column2)

        # Add the TreeView to the window
        self.add(self.treeview)

    def load_image(self, image_path):
        # Load an image from file and return a GdkPixbuf.Pixbuf
        try:
            pixbuf = GdkPixbuf.Pixbuf.new_from_file(image_path)
            return pixbuf
        except GLib.Error:
            print(f"Error loading image from {image_path}")
            return None

if __name__ == "__main__":
    app = TreeViewExample()
    app.connect("destroy", Gtk.main_quit)
    app.show_all()
    Gtk.main()

所以我仍在寻找答案,也许模型中可以有一个“对象”,可以是文本或pixbuf,并且TreeView将正确显示模型中的任何内容。

© www.soinside.com 2019 - 2024. All rights reserved.