在 gtkmm 3.10.1 中使用 CSS 设置样式问题 Gtk::Box
Problem styling Gtk::Box with CSS in gtkmm 3.10.1
我必须使用 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`
@lb90 的评论让我找到了解决方案。
使用样式上下文引入 Gtk::Box 背景和边框缺失渲染的提交位于:https://gitlab.gnome.org/GNOME/gtk/commit/698488ddc4
使用上述提交中的技术,我能够解决这个问题。我引入了一个 StyleBox class,它派生自 Gtk::Box 并覆盖了 on_draw() 处理程序。在 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 编写一个程序,该程序在具有 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`
@lb90 的评论让我找到了解决方案。
使用样式上下文引入 Gtk::Box 背景和边框缺失渲染的提交位于:https://gitlab.gnome.org/GNOME/gtk/commit/698488ddc4
使用上述提交中的技术,我能够解决这个问题。我引入了一个 StyleBox class,它派生自 Gtk::Box 并覆盖了 on_draw() 处理程序。在 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);
}
};