gtkmm 3.10.1 中带有 CSS 的 Gtk::Box 样式问题

Posted

技术标签:

【中文标题】gtkmm 3.10.1 中带有 CSS 的 Gtk::Box 样式问题【英文标题】:Problem styling Gtk::Box with CSS in gtkmm 3.10.1 【发布时间】:2019-12-18 12:40:31 【问题描述】:

我必须使用 gtkmm 编写一个程序,该程序在具有 GTK 3.10.1 的旧系统上运行。所以我必须避开之后添加的任何功能。

我在使用 CSS 为 Gtk::Box 实例设置样式时遇到了一些问题。它在具有 gtkmm 3.18.0 的 Ubuntu 16.04 机器上正常工作,但在具有 3.10.1 的 Ubuntu 14.04 上,CSS 不适用于 Gtk::Box 实例。

下面是一个简化的示例。以下是示例如何分别在 Ubuntu 16.04/gtkmm 3.18.0 和 Ubuntu 14.04/gtkmm 3.10.1 上呈现的屏幕截图。

可以看出,包含“YEP”标签的 Gtk::Box 在 gtkmm 3.10.1 上没有设置样式(边框和背景)。

    我是否遗漏了一些明显的东西? 这是 3.10.1 的已知问题吗? 关于如何在 Ubuntu 14.04/gtkmm 3.10.1 上达到预期结果的任何建议?

谢谢!

代码:

// styletest.cpp

#include <gtkmm.h>

class StyleTestWindow : public Gtk::Window

public:
  StyleTestWindow();
  virtual ~StyleTestWindow() = default;

protected:
  Gtk::Box    mainbox;
  Gtk::Label  label;
;

StyleTestWindow::StyleTestWindow() :
  mainbox(Gtk::ORIENTATION_VERTICAL)

  set_size_request(300, 200);
  set_position(Gtk::WIN_POS_CENTER);
  set_border_width(50);
  set_decorated(false);

  auto css = Gtk::CssProvider::create();
  css->load_from_path("./styletest.css");
  get_style_context()->add_provider_for_screen(Gdk::Screen::get_default(), 
                                               css, 
                                               GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
  get_style_context()->add_class("mainwin");

  label.get_style_context()->add_class("yeplabel");
  label.set_halign(Gtk::ALIGN_CENTER);
  label.set_valign(Gtk::ALIGN_CENTER);
  label.set_text("YEP!");

  mainbox.get_style_context()->add_class("mainbox");
  mainbox.pack_start(label);
  add(mainbox);

  show_all_children();


int
main(int argc, char *argv[])

  Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "com.example.styletest");

  StyleTestWindow mainWindow;
  return app->run(mainWindow);

CSS:

/* styletest.css */

.mainwin 
    background: #DEB887;
    border: 5px solid #996600;


.mainbox 
    background: #cc9900;
    border: 5px solid #C00000;


.yeplabel 
    color: #FFFFFF;
    background: #A52A2A;
    font: Comic Sans MS 16;
    padding: 10px;

构建:

g++ -std=c++11 styletest.cpp -o styletest `pkg-config gtkmm-3.0 --cflags --libs`

【问题讨论】:

见gitlab.gnome.org/GNOME/gtk/commit/698488ddc4 同样的事情,对于 GtkGrid,已经完成得更早了,但我认为它从 Gtk 3.10.3 开始就包含在内。 gitlab.gnome.org/GNOME/gtk/commit/144a92ef1144 我自己不是 Ubuntu 用户,但看起来你可以升级到 gtk3 3.10.8? launchpad.net/ubuntu/trusty/+source/gtk+3.0 @lb90 非常感谢您提供这些提交链接!使用这些信息,我能够通过自己实现一个绘制处理程序来使示例正常工作,该处理程序以相同的方式呈现背景和框架。 好吧,我无法更改程序运行的系统(它不是 Ubuntu)。而且我也不能发布我自己的 GTK 版本。但如上所述,我可以在绘图处理程序中解决它。 :-) 现在我将在实际应用中尝试相同的技术。 【参考方案1】:

@lb90 的评论让我找到了解决方案。

使用样式上下文引入 Gtk::Box 背景和边框缺失渲染的提交在这里:https://gitlab.gnome.org/GNOME/gtk/commit/698488ddc4

使用上述提交中的技术,我能够解决这个问题。我介绍了一个派生自 Gtk::Box 并覆盖 on_draw() 处理程序的 StyleBox 类。在 on_draw() 中渲染背景和边框。

在示例代码 StyleTestWindow.cpp 中,只需将 mainbox 的类型从 Gtk::Box 更改为 StyleBox。

StyleBox.h

class StyleBox : public Gtk::Box

public:
  explicit StyleBox(Gtk::Orientation orientation =  Gtk::ORIENTATION_HORIZONTAL, int spacing =  0) :
    Gtk::Box(orientation, spacing)
  
  

  virtual ~StyleBox() = default;

protected:
  virtual bool on_draw(const ::Cairo::RefPtr< ::Cairo::Context>& cr) override
  
    GtkWidget *widget = GTK_WIDGET(gobj());
    GtkStyleContext *context;
    GtkAllocation alloc;
    cairo_t *ccr = const_cast<cairo_t*>(cr->cobj());

    context = gtk_widget_get_style_context (widget);
    gtk_widget_get_allocation (widget, &alloc);

    gtk_render_background(context, ccr, 0, 0, alloc.width, alloc.height);
    gtk_render_frame(context, ccr, 0, 0, alloc.width, alloc.height);

    return Box::on_draw(cr);
  
;

【讨论】:

以上是关于gtkmm 3.10.1 中带有 CSS 的 Gtk::Box 样式问题的主要内容,如果未能解决你的问题,请参考以下文章

将 css 样式应用于 Gtk::ToolButton 不适用于 gtkmm 中的选择器

Tailwind css中带有文本的圆圈

IE 9 中带有渐变背景的 CSS 菜单上的 Z 索引或溢出问题

JS中带有传单的地理位置

$.each() 中带有 CSS 变量的样式

需要有关 gtkmm 中的多线程的帮助