如何将背景图像添加到GTK TreeView?

如何将背景图像添加到GTK TreeView?,gtk,pygtk,gtktreeview,Gtk,Pygtk,Gtktreeview,我想有一个GTK树视图与背景图像,如下图所示 我已经找到了设置小部件背景颜色的方法,但似乎没有一种方法可以设置背景pixbuf或其他图像格式 我将Python与PyGTK结合使用,但任何带有GTK绑定的语言的答案都是可以接受的 带背景图像的gtkTreeView模型: 第一次尝试 根据Jong Bor的建议,我尝试了以下方法: style = treeview.get_style().copy() img_pixbuf = gtk.gdk.pixbuf_new_from_file(image_f

我想有一个GTK树视图与背景图像,如下图所示

我已经找到了设置小部件背景颜色的方法,但似乎没有一种方法可以设置背景pixbuf或其他图像格式

我将Python与PyGTK结合使用,但任何带有GTK绑定的语言的答案都是可以接受的

带背景图像的gtkTreeView模型:

第一次尝试

根据Jong Bor的建议,我尝试了以下方法:

style = treeview.get_style().copy()
img_pixbuf = gtk.gdk.pixbuf_new_from_file(image_filename)
img_pixmap = img_pixbuf.render_pixmap_and_mask()[0]
for state in (gtk.STATE_NORMAL, gtk.STATE_ACTIVE, gtk.STATE_PRELIGHT,
              gtk.STATE_SELECTED, gtk.STATE_INSENSITIVE):
    style.bg_pixmap[state] = img_pixmap
treeview.set_style(style)
起初,这似乎没有任何效果,但在我的树状视图中选择一个项目后,我观察到以下情况:

style = treeview.get_style().copy()
img_pixbuf = gtk.gdk.pixbuf_new_from_file(image_filename)
img_pixmap = img_pixbuf.render_pixmap_and_mask()[0]
for state in (gtk.STATE_NORMAL, gtk.STATE_ACTIVE, gtk.STATE_PRELIGHT,
              gtk.STATE_SELECTED, gtk.STATE_INSENSITIVE):
    style.bg_pixmap[state] = img_pixmap
treeview.set_style(style)
选择行时,部分背景“显示通过”

请注意,我使用的是基于模型的背景图像,只是出于测试目的,它有一些蓝色

然后,我激活了GUI的一部分,该部分清除树视图的内容并重新绘制,并观察到:


但是,只要我向TreeView添加一些内容,背景就会消失,因此我仍然不确定这是否朝着正确的方向发展。

我怀疑,由于每个单元格都有一个控制其外观的渲染器,因此您必须以某种方式逐单元格修改TreeView单元格

无论如何,以下代码可能值得一试未经测试、不完整的代码:

# Get the treeview's style
style = treeview.get_style().copy()

# Change the bg_pixmap attribute
#   It's an array with one pixbuf for every widget state, so
#   you probably want to replace each of the default 
#   pixmap's with your own image(s)
#   

style.bg_pixmap[0] = your_pixmap
style.bg_pixmap[1] = your_pixmap
style.bg_pixmap[2] = your_pixmap
style.bg_pixmap[3] = your_pixmap
style.bg_pixmap[4] = your_pixmap

# Set the modified style
treeview.set_style(style)
bg_pixmap属性记录在中

我不确定数组位置如何映射到小部件状态。如果与C++相同,则为:

0 - STATE_NORMAL    
1 - STATE_ACTIVE    
2 - STATE_PRELIGHT  
3 - STATE_SELECTED  
4 - STATE_INSENSITIVE   

我怀疑,由于每个单元都有一个控制其外观的渲染器,因此您必须以某种方式逐个单元修改treeview单元

无论如何,以下代码可能值得一试未经测试、不完整的代码:

# Get the treeview's style
style = treeview.get_style().copy()

# Change the bg_pixmap attribute
#   It's an array with one pixbuf for every widget state, so
#   you probably want to replace each of the default 
#   pixmap's with your own image(s)
#   

style.bg_pixmap[0] = your_pixmap
style.bg_pixmap[1] = your_pixmap
style.bg_pixmap[2] = your_pixmap
style.bg_pixmap[3] = your_pixmap
style.bg_pixmap[4] = your_pixmap

# Set the modified style
treeview.set_style(style)
bg_pixmap属性记录在中

我不确定数组位置如何映射到小部件状态。如果与C++相同,则为:

0 - STATE_NORMAL    
1 - STATE_ACTIVE    
2 - STATE_PRELIGHT  
3 - STATE_SELECTED  
4 - STATE_INSENSITIVE   

使用GTK3和gtkmm可以使用CSS,但图像需要作为文件或资源提供

这里我假设treeview是子类:

class MyTreeView : public Gtk::TreeView { .. };
为您的treeview设置名称,然后向其添加CSS样式:

MyTreeView::MyTreeView () {

  set_name ("MyTreeView");
  auto css = Gtk::CssProvider::create ();
  auto sc  = get_style_context ();

  string path_to_img = "my-image.png";

  string css_data =
    ustring::compose (
                    "#MyTreeView  { background-image: url(\"%1\");"
                    "               background-repeat: no-repeat;"
                    "               background-position: 50%% 50%%;"
                    " }\n"
                    "#MyTreeView  .hide_bg { background-image: none; }",
                    path_to_img);

  try {
    css->load_from_data (css_data);
  } catch (Gtk::CssProviderError &e) {
    cout "error: attempted to set background image: " << path_to_img.c_str () << ": " << e.what () << endl;
  }

  auto screen = Gdk::Screen::get_default ();
  sc->add_provider_for_screen (screen, css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

}
到CSS

然后,可以使用以下方法隐藏或显示背景图像:

if (!hide) {
  auto sc = get_style_context ();
  if (!sc->has_class ("hide_bg")) sc->add_class ("hide_bg");
} else {
  auto sc = get_style_context ();
  if (sc->has_class ("hide_bg")) sc->remove_class ("hide_bg");
}

使用GTK3和gtkmm可以使用CSS,但图像需要作为文件或资源提供

这里我假设treeview是子类:

class MyTreeView : public Gtk::TreeView { .. };
为您的treeview设置名称,然后向其添加CSS样式:

MyTreeView::MyTreeView () {

  set_name ("MyTreeView");
  auto css = Gtk::CssProvider::create ();
  auto sc  = get_style_context ();

  string path_to_img = "my-image.png";

  string css_data =
    ustring::compose (
                    "#MyTreeView  { background-image: url(\"%1\");"
                    "               background-repeat: no-repeat;"
                    "               background-position: 50%% 50%%;"
                    " }\n"
                    "#MyTreeView  .hide_bg { background-image: none; }",
                    path_to_img);

  try {
    css->load_from_data (css_data);
  } catch (Gtk::CssProviderError &e) {
    cout "error: attempted to set background image: " << path_to_img.c_str () << ": " << e.what () << endl;
  }

  auto screen = Gdk::Screen::get_default ();
  sc->add_provider_for_screen (screen, css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

}
到CSS

然后,可以使用以下方法隐藏或显示背景图像:

if (!hide) {
  auto sc = get_style_context ();
  if (!sc->has_class ("hide_bg")) sc->add_class ("hide_bg");
} else {
  auto sc = get_style_context ();
  if (sc->has_class ("hide_bg")) sc->remove_class ("hide_bg");
}

谢谢你的建议。不幸的是,我尝试了这种方法,但没有任何明显的效果。我还尝试直接设置bg_pixmap值,而不是首先复制样式并将其设置回小部件上,但也不起作用。我认为bg_pixmap只影响窗口背景可见的小部件部分,但是TreeView小部件用白色填充覆盖窗口背景。这是意料之中的。在看到你的评论之前,我对答案进行了编辑,以表明这确实是一个遥远的目标。由于每个单元都有一个允许更改其外观的渲染器,所以蛮力方法是修改每个单元的背景。除非对Gtk的内部工作有更深入了解的人能够对这个问题有所了解……在进一步的调查中,我发现设置bg_pixmap属性确实有一些效果。我将bg_pixmap数组中的每个值设置为我的图像的pixmap,这会导致所选行的选择颜色成为我图像的一部分。有时图像甚至会以平铺方式显示为背景,但仅当树视图为空时。我会给我的问题添加一个截图。谢谢你的建议。不幸的是,我尝试了这种方法,但没有任何明显的效果。我还尝试直接设置bg_pixmap值,而不是首先复制样式并将其设置回小部件上,但也不起作用。我认为bg_pixmap只影响窗口背景可见的小部件部分,但是TreeView小部件用白色填充覆盖窗口背景。这是意料之中的。在看到你的评论之前,我对答案进行了编辑,以表明这确实是一个遥远的目标。由于每个单元都有一个允许更改其外观的渲染器,所以蛮力方法是修改每个单元的背景。除非对Gtk的内部工作有更深入了解的人能够对这个问题有所了解……在进一步的调查中,我发现设置bg_pixmap属性确实有一些效果。我将bg_pixmap数组中的每个值设置为我的图像的pixmap,这会导致所选行的选择颜色成为我图像的一部分。有时图像甚至会以平铺方式显示为背景,但仅当树视图为空时。我将在我的问题中添加一个屏幕截图。填充树视图后调用treeview.show_会使背景可见吗?还有一个不切实际的建议:既然选择了
行使背景可见,执行类似treeview.get_selection.select_all的操作以选择所有行。@Jong show_all似乎没有效果。此外,除非整个树视图已满,否则选择“全部”将无法显示背景,即使如此,该界面也无法为用户工作-/填充树视图后调用treeview.show_all是否会使背景可见?另外,还有一个粗俗的建议:因为选择一行会使背景可见,所以可以执行类似于treeview.get\u selection.select\u all的操作来选择所有行。@Jong show\u all似乎没有效果。此外,除非整个树视图已满,否则选择“全部”将无法显示背景,即使如此,该界面也无法为用户工作-/