GTK的RC----让动态的换皮肤立竿见影

GTK的RC----让动态的换皮肤立竿见影

《Apress.Foundations.of.GTK.plus.Development》作为一本入门级的书很好,但是要深入,这本书就有点力不从心了。最近在学习RC文件的编写时,我脑子里有这么一个概念:从GTK的设计上来看,它应该支持GTK程序换皮肤,那么在目前带有显示屏的电子设备中,它的前途真不能小看,特别是正在发展中的STB。
       学习完书中关于RC的内容后,感觉很简单,就一个gtk_rc_parse()函数就能搞定它,哪想我在实际实践中却是一波三折,从上周5开始,一有空便研究这个功能,始终抱着一个信念:既然GTK采用RC文档来管理它的style。那么这么强大的GTK不会连换皮肤都不能实现。一开始我是这么做的:
Fun1()
{
...
gchar *pRcFilePath;

pRcFilePath = RC文件//动态获取其中一个RC文件中
gtk_rc_parse(pRcFilePath );
...
}

以上只有当触发某个事件时才执行。当时我很激动的去触发那个事件,希望能看到我想要的结果,可是无论我怎么弄它都不动。一下找不到北,只有求助于GG,不知是国人太过于保守还是国人不屑这个问题,网上有人也碰到此问题,可是给出的回复没几个,且多半都是废话。后来求救于QQ群,也希望能给出点思路,因为我认为这个换皮肤这个功能在项目中肯定要用到的,在群里,有人很热心的跟我讨论了下,但还是没有得到解决。看来在国内还真是这句话中:求人不如求己。
       从上周5到今天,我白天在公司由于事情不是太多,我一有时间便去研究源码,可那个源码啊,我的个乖乖哟,好几十M呢!不好啃,但自生下来就没有服输过的我,决定啃。开始的几天我拿着那个源码东看看西看看,实在看不清楚个思路,但还是坚持了下来。现在回想起来开始那几天真的很有意义,尽管没有看懂,但是很多不明白的词已经印在我脑海里,为我今天质的变化提供了必要条件,今天真是一个五味瓶的日子,终于通过源码解决此问题;但今天也挨了老大一顿批,哎,认了。
先贴上可以实现换皮肤的源码:
Fun2()
{
...
gchar *pRcFilePath;
GtkSettings *pRootSettings;

pRcFilePath = RC文件//动态获取其中一个RC文件中
gtk_rc_parse(pRcFilePath );
gtk_rc_reparse_all();

pRootSettings = gtk_settings_get_default();
gtk_rc_reset_styles(pRootSettings);
...
}

好,闲话不说了,先说说我比较简单理解吧,首先我们要知道函数gtk_rc_parse()到底干了啥,一下是它的函数内容:
void gtk_rc_parse (const gchar *filename)
{
GSList *tmp_list;

g_return_if_fail (filename != NULL);//判断filename 是否存在

add_to_rc_file_list (&global_rc_files, filename, TRUE);//因为GTK是支持多个RC文件的,也就是支持换皮肤,所以它内核里面是通过链表来管理RC文件的。自然要先把RC文件添加到链表中。但不解析

for (tmp_list = rc_contexts; tmp_list; tmp_list = tmp_list->next)
    gtk_rc_context_parse_file (tmp_list->data, filename, GTK_PATH_PRIO_RC, TRUE);//上一个函数把RC文件添加到链表中时,它是还没有解析,这就是模块化的好处,这个函数就是解析filename,并把链表的一个reload置为TRUE,表示需要重新加载。
}

从上面的注释可以明白该函数只是添加RC并解析RC文件,但是没有加载在应用软件中去,所以我刚开始写的Fun1()自然就不能实现。
函数gtk_rc_reparse_all从函数名可以明白它是用来重新解析所有RC文件的。但是它只能加载在你创建新的对话框或控件中,而原窗体却纹丝不动。那么怎么要让原窗体也发生变化呢,而此时为什么不变化呢,我是这么理解的,因为每一个控件都有一块内存池管理它,但是它的属性应该在内存池里面。尽管你加载了RC,但是这块内存池里面的RC属性却还是原来的属性。
函数gtk_rc_reset_styles从GTK对它注释如下:
/**
* gtk_rc_reset_styles:
* @settings: a #GtkSettings
*
* This function recomputes the styles for all widgets that use a
* particular #GtkSettings object. (There is one #GtkSettings object
* per #GdkScreen, see gtk_settings_get_for_screen()); It is useful
* when some global parameter has changed that affects the appearance
* of all widgets,
because when a widget gets a new style, it will
* both redraw and recompute any cached information about its
* appearance. As an example, it is used when the default font size
* set by the operating system changes. Note that this function
* doesn't affect widgets that have a style set explicitely on them
* with gtk_widget_set_style().
*
* Since: 2.4
**/

这个函数是对所有空间的styles重新设置并重绘。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码介绍 MetroForWinForm(win8风格模版) using System; using System.Drawing; using System.Globalization; using System.Windows.Forms; using MetroFramework.Forms; namespace MetroFramework.Demo { public partial class MainForm : MetroForm { public MainForm() { InitializeComponent(); metroStyleManager.Theme = MetroThemeStyle.Default; metroStyleManager.Style = MetroColorStyle.Teal; } private void metroTileSwitch_Click(object sender, EventArgs e) { var m = new Random(); int next = m.Next(0, 13); metroStyleManager.Style = (MetroColorStyle)next; } private void metroTile1_Click(object sender, EventArgs e) { metroStyleManager.Theme = metroStyleManager.Theme == MetroThemeStyle.Light ? MetroThemeStyle.Dark : MetroThemeStyle.Light; } private void metroButton1_Click(object sender, EventArgs e) { MetroTaskWindow.ShowTaskWindow(this, "SubControl in TaskWindow", new TaskWindowControl(), 10); } private void metroButton2_Click(object sender, EventArgs e) { MetroMessageBox.Show(this, "Do you like this metro message box?", "Metro Title", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk); } private void metroButton5_Click(object sender, EventArgs e) { metroContextMenu1.Show(metroButton5, new Point(0, metroButton5.Height)); } private void metroButton6_Click(object sender, EventArgs e) { MetroMessageBox.Show(this, "This is a sample MetroMessagebox `OK` only button", "MetroMessagebox", MessageBoxButtons.OK, MessageBoxIcon.Information); } private void metroButton10_Click(object sender, EventArgs e) { MetroMessageBox.Show(this, "This is a sample MetroMessagebox `OK` and `Cancel` button", "MetroMessagebox", MessageBoxButtons.OKCancel, MessageBoxIcon.Information); } private void metroButton7_Click(object sender, EventArgs e) { MetroMessageBox.Show(this, "This is a sample MetroMessagebox `Yes` and `No` button", "MetroMessagebox", MessageBoxButtons.YesNo, MessageBoxIcon.Question); } private void metroButton8_Click(object sender, EventArgs e) { MetroMessageBox.Show(this, "This is a sample MetroMessagebox `Yes`, `No` and `Cancel` button", "MetroMessagebox", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); } private void metroButton11_Click(object sender, EventArgs e) { MetroMessageBox.Show(this, "This is a sample MetroMessagebox `Retry` and `Cancel` button. With warning style.", "MetroMessagebox", MessageBoxButtons.RetryCancel, MessageBoxIcon.Warning); } private void metroButton9_Click(object sender, EventArgs e) { MetroMessageBox.Show(this, "This is a sample MetroMessagebox `Abort`, `Retry` and `Ignore` button. With Error style.", "MetroMessagebox", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error); } private void metroButton12_Click(object sender, EventArgs e) { MetroMessageBox.Show(this, "This is a sample `default` MetroMessagebox ", "MetroMessagebox"); } private void metroButton4_Click(object sender, EventArgs e) { var testform = new TestForm1(); testform.ShowDialog(); } private void metroButton4_Click_1(object sender, EventArgs e) { metroTextBox2.Focus(); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值