【发布时间】:2016-12-22 05:46:13
【问题描述】:
我正在尝试提供我自己的 GtkStyleProvider 实现,因为在我的情况下,“普通”CSS 提供程序需要大量工作和额外处理。
我希望能够提供基于某些内部状态的小部件样式,并且要在 CSS 中做到这一点,我必须写出一大串 CSS(将 Pango.FontDescriptions 之类的东西翻译成 CSS 样式的声明) 基于状态的任何变化,然后将其输入到GktCssProvider 中,该GktCssProvider 会将其返回到 Gtk-land。与自定义提供程序相比,它只会(以某种方式)发出信号,表明其客户端小部件应向其询问样式,并直接根据状态分发新样式。
GtkStyleProvider 似乎是实现这一目标的一种方式——我可以创建一个基于某种状态返回样式的提供程序,并将其作为样式提供程序添加到相关的GtkStyleContext。 (C)接口是
// deprecated - return NULL in new code
GtkIconFactory * gtk_style_provider_get_icon_factory (
GtkStyleProvider *provider,
GtkWidgetPath *path);)
// deprecated - return NULL in new code
GtkStyleProperties * gtk_style_provider_get_style (
GtkStyleProvider *provider,
GtkWidgetPath *path))
// return true if property found and has a value, else false
gboolean gtk_style_provider_get_style_property (
GtkStyleProvider *provider,
GtkWidgetPath *path,
GtkStateFlags state,
GParamSpec *pspec,
GValue *value);
为此,我写了这样的东西,我希望它可以工作,但什么也不做,因为它应该总是报告属性未设置:
# compile with: valac styleprov.vala --pkg gtk+-3.0 --pkg gdk-3.0
using Gtk;
using Gdk;
public class DerivedStyleProvider : Object, Gtk.StyleProvider
{
public unowned Gtk.IconFactory get_icon_factory (Gtk.WidgetPath path)
{
return (Gtk.IconFactory) null; // Evil cast to work around buggy declaration in VAPI file
}
public Gtk.StyleProperties get_style (Gtk.WidgetPath path)
{
return (Gtk.StyleProperties) null; // Evil cast to work around buggy declaration in VAPI file
}
public bool get_style_property (Gtk.WidgetPath path,
Gtk.StateFlags state,
GLib.ParamSpec pspec,
out GLib.Value value)
{
stdout.printf("get_style_property");
// Compiler happiness for testing
value = Value (typeof (string));
return false; //TODO
}
}
public class styleprov.MainWindow : Gtk.Window
{
construct {
DerivedStyleProvider styleProvider = new DerivedStyleProvider();
// but this would work
//Gtk.CssProvider styleProvider = new Gtk.CssProvider();
//styleProvider.load_from_data("*{ background-color: #ff0000; }");
StyleContext.add_provider_for_screen(this.get_screen(),
styleProvider,
Gtk.STYLE_PROVIDER_PRIORITY_USER);
}
}
class styleprov.Main : GLib.Object
{
public void run() {
styleprov.MainWindow mainWindow = new styleprov.MainWindow();
mainWindow.show_all();
}
public static int main (string[] args) {
Gtk.init (ref args);
Main app = new Main();
app.run();
Gtk.main ();
return 0;
}
}
这编译OK,运行起来,但几乎喷出警告:
(styleprov:32365): GLib-GObject-WARNING **: gsignal.c:2523: signal '-gtk-private-changed' is invalid for instance '0x1154ac0' of type 'DerivedStyleProvider'
(styleprov:32365): Gtk-WARNING **: (gtkstylecascade.c:256):gtk_style_cascade_lookup: code should not be reached
(styleprov:32365): Gtk-WARNING **: (gtkstylecascade.c:256):gtk_style_cascade_lookup: code should not be reached
...several of these....
尽管有警告,get_style_property() 方法似乎从未被调用,因此无法提供自定义样式。
将DerivedStyleProvider 替换为“普通”CSS 提供程序可以正常工作。
实现自定义GtkStyleProvider(任何语言)的正确方法是什么?
【问题讨论】:
-
我快速浏览了 GtkCssProvider,它实现了 两个 接口,
GtkStyleProvider和GtkStyleProviderPrivate。您可能还必须为第二个接口提供实现。虽然我不是 Gtk+ 专家... -
顺便说一句:为什么你必须大量自定义你的 ui 样式呢?我在这里闻到了XY problem。您可能想退后一步,重新考虑您的设计。使用 Clutter、Cairo 或类似的东西自己绘制 UI 可能是另一种选择。
-
它实际上并没有大量的样式或非常复杂,它只是将 CSS 构造为字符串,对我来说似乎是迂回的,我被
GtkStyleProvider的 API 承诺分心,结果是不能按我想象的方式使用。