My Gtk Tutorial 2

我写这些其实我真的自己都不看的,有用还是没用只有我唯一的那个目标读者来评价。

那么我们来无聊的介绍下Gtk的一些Widget。

1、GtkBox

和 Qt 不同的是,Gtk一般实现一个自己的Widget,都是从一个具体的Widget而不是general的GtkWidget 开始的,其中很多则又是选择了 GtkBox。

当然这里所说的实现一个具体的Widget不是指连draw事件都override的那种widget,而是一组widget的组合,例如文件对话框这种。那么具体实现的时候只要找好你要的那个顶层的Widget作为基类就行了。

曾经的 GtkHBox 和 GtkVBox 已经成为了历史,取而代之的是以一个横纵作为属性的 GtkBox。

一般而言,任何你想要的复杂的布局都可以用GtkBox来实现,一个技巧就是占位符,看起来Gtk里面并没有Qt的Spacer这种专门的占位符,一般用来占位的就是GtkLabel。

例如你希望实现一个上下顶头有Widget的东西,中间是空的,那么你可以new一个Vertical的GtkBox出来,然后使用  gtk_box_pack_start 往里面扔东西。中间用一个GtkLabel来撑开位置。

2、大小

写UI控件最头疼的事情是什么?是大小。说他们的定位难度堪比HTML也不为过。尤其是在你没注意到的时候你把你的窗口设置成为可拖拽,或者进行i18n后出现了一些惨烈的情况(单从语言来说,同一个词,一般汉语最短,英语次之,某些西语会长的要命)。

不过在Gtk3中,GtkWidget终于增加了expand,align,这些用来标明Widget本身的大小和位置属性。

这下终于要谢天谢地了?哦,其实没有,如果你的界面够复杂你可能还是想要掀桌(不过如此的话你是不是应该先考虑下你的设计?),不过也比Gtk2时代好的多就是了。

在处理大小时要考虑到你在进行i18n之后界面可能产生的变化……

处理大小时,GtkBox的默认是参考内部的Widget的属性来确定的,而Gtk2的兼容类GtkHBox,GtkVBox还默认并非如此。

总之这两个属性也不难理解,就是给你一个较大的空间。你的Widget是保持较小状态,还是填满整个区域?是如何在这个区域内进行对齐的?

3、来实现个Widget吧

如果你了解GObject的继承,那么这一步对你来说基本是没有难度的。

如果你不了解GObject的继承,还是去看别的文章吧……

http://garfileo.is-programmer.com/categories/6934/posts

C语言模拟继承是采用了一个非常简单的方式,就是struct的嵌套,在所有模拟继承关系的代码中都采用了这样的方式,这样做的好处就是你可以强制转换子类的指针为基类的指针。

struct Derived {
     Parent parent;
};

这样你就可以简单的去访问parent的值了。至于如何实现private,这里也简单说下。

struct Derived {
     Parent parent;
     Private* priv;
};

然后采用前向声明声明Private,Private的定义则写在c文件里面,而不是h里面,这样就可以保护Private内部是不可见的。当然如果你的类压根就不会给别人用,你也没必要非要用Private。

实现自己的Widget基本上来说,就是定义一个你要的Class的子类的过程,过程非常简单,你大可找个GObject的Skelton的生成器来帮你生成主干代码。

然后在init部分老实填入你自己的内容,写一个自己的new函数(虽然里面无外乎就是g_object_new的wrapper)。

下次来讲个具体类的实现。

This entry was posted in Gtk. Bookmark the permalink.

13 Responses to My Gtk Tutorial 2

  1. SuperCat says:
    Firefox 13.0 GNU/Linux x64

    GtkBox属于要被淘汰的对象,在新的程序里面官方推荐使用的是GtkGrid,它是GtkBox和GtkTable的综合体。它才是完全依靠expand(包括hexpand和vexpand)和margin(margin-left, margin-right, margin-top, margin-bottom)属性来完成界面布局的。还有GTK+里面一般不需要占位控件,通过合适的expand属性设置即可完成任务。

  2. csslayer says:
    Firefox 14.0a2 Windows 7

    @SuperCat
    我自己用到占位的一个地方是:
    =====


    XXXXX
    YYYYY


    ====
    这样的,不过这个是gtk2时代写的。

    想想的话align加no expand可以做到,不过感觉怪怪的。还是有个占位的逻辑清晰……

  3. SuperCat says:
    Firefox 13.0 GNU/Linux x64

    很明显是受到Qt的编程逻辑的影响了嘛。其实用过Glade和Qt Creator就能知道它们界面设计上的差别了。

  4. csslayer says:
    Firefox 14.0a2 Windows 7

    @SuperCat 好吧,你来告诉我gtk2时代你怎么写出这样的布局?

  5. SuperCat says:
    Firefox 13.0 GNU/Linux x64

    GTK+ 2时代GtkBox的布局是通过那个gtk_box_pack_start的参数控制的。通过2个GtkBox的嵌套可以做出乃需要的那种界面(不过如果要精确坐标比较难)。

  6. csslayer says:
    Firefox 14.0a2 Windows 7

    @SuperCat ……不用你那么复杂吧
    我是 gtkbox 套label,button,button,label,两个label expand就完事了。

  7. Mike says:
    Firefox 12.0 GNU/Linux x64

    不得不说一下这个 private 的实现有点问题…………嗯,一笔带过,带过。

  8. csslayer says:
    Firefox 14.0a2 Windows 7

    @Mike 什么问题?

  9. SuperCat says:
    Firefox 13.0 GNU/Linux x64

    private如果要实现真正的隐藏一般是在class_init里面用g_type_class_add_private()加进去的,不需要在类的实例结构体中添加。访问的时候可以通过GET_PRIVATE宏(展开后调用的是G_TYPE_INSTANCE_GET_PRIVATE宏)来获得其内部数据。本文里面的写法是GTK+过去的用法了。

  10. csslayer says:
    Firefox 14.0a2 Windows 7

    @SuperCat 哦,我从来没说过我写的是glib的办法啊。只是举例而已

  11. garfileo says:
    Firefox 13.0 GNU/Linux x64

    supercat 说的那个严肃一点的 private,主要是为了 g_object_set/get 方便一些。如果没有 set/get 的需求,我个感觉还是直接扔在 .c 里面比较好 🙂

  12. hohos says:
    Firefox 12.0 Ubuntu x64

    惟一的读者噢。。。。。。。

    你在搞基吗。。。。cs slayer大婶。。。。

  13. csslayer says:
    Firefox 13.0 GNU/Linux x64

    @hohos 大婶不搞基,只能叫鸭…… XDDDDDDD

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.