我是GTK的新手,我正在搞乱我的第一个“严肃的”GTK(gtk + -3)应用程序。我想借鉴别人的经验,了解何时适合定义新的GTK类,或者只使用“vanilla”GTK类,并通过信号处理程序实现行为。
到目前为止,我遇到过两个例子:
我正在创建一个新的小部件:基本上是一个GtkDrawingArea,我用它来显示一些数据。我原先假设实现这个的最好方法是使用G_DEFINE_TYPE
继承GtkDrawingArea,并提供我自己的绘制回调:
static void mywidget_class_init(MyWidgetClass *klass)
{
GTK_WIDGET_CLASS(klass)->draw = mywidget_draw;
}
然而,看起来我可以在不定义新类型的情况下实现完全相同的功能,只需创建一个vanilla GtkDrawingArea,并在初始化期间连接相应的信号。
[我的自定义小部件最终将提供的不仅仅是绘制回调,因为它需要是交互式的,但后来会......)
我的应用程序包含几个不同的窗口,目前是vanilla GtkWindows:
struct myapp_somewindow {
struct myapp *app;
GtkWindow *window;
GtkWidget *some_label_that_is_updated;
/*... other window-specific fields */
}
初始化myapp_somewindow结构时,我用gtk_window_new()
创建GtkWindow,并初始化小部件/布局/等,并连接信号。 [我最终可能会使用.ui文件来处理更复杂的案例,但是现在窗口很简单。]
这可以通过定义GtkWindow的新子类来完成,但我不确定定义新类的代码开销何时变得有价值。
我知道对于采用哪种方法可能没有严格的规则,但在做出这些设计决策时是否有任何一般指导原则?这两种方法都有任何重大缺陷吗?
答案 0 :(得分:7)
我使用GTK +和Clutter开展了一些项目,我总是大力推广将通用小部件/演员的子类化用于更具体的小部件。
按照惯例,您可以为每个类创建一个新文件,因此,如果您将与窗口小部件关联的行为和状态机制引入子类,则会将该代码拉入单独的文件中。这有助于更轻松地构建代码,并在其他人想要来阅读时提供帮助。
子类化策略还可以帮助您将封装强制实施为代码库的良好实践。如果您的小部件及其关联的状态和逻辑被很好地封装,那么这可以帮助重用。
使用此子类策略的项目的一个很好的例子是任务,特别是它的内部帮助库:http://git.gnome.org/browse/tasks/tree/libkoto这意味着当我们想要将应用程序移植到新平台或提供不同的查看数据很容易将现有的小部件和树模型以不同的方式粘合在一起。
如果您想使用C并且发现子类化有点乏味,那么您可以尝试使用此工具:http://git.gnome.org/browse/turbine/以帮助自动创建子类。
答案 1 :(得分:1)
当您需要为窗口小部件保存某些状态时,我会使用定义新类的准则。否则,您将最终创建持有该状态的自定义结构作为用户数据传递给信号处理程序,从而使您的代码更加复杂并为内存泄漏创造更多机会。
这表明对于你的第二个用例,应用程序窗口,你应该总是定义一个新的类。
这样做的一个原因是你的小部件可能开始很简单,你可以用信号处理程序纯粹实现的行为,但后来可能会变得更复杂。例如,假设您要将后备存储添加到绘图区域。将简单小部件重构为类的“感知成本”很高,但它会使您的代码比处理它更清晰。
另一个优点是类可以具有属性。您可以将这些属性绑定到其他类的属性或GSettings键,这是一个非常强大的机制,可以使您的代码非常简单。
如果您不喜欢所有类样板,请考虑在Vala中进行编程。