{i} 请自由地添加文档或更正错误。如果你有什么想法,请发邮件给我(benjamin@sipsolutions.net),或者来到 #gnome-art on irc.gnome.org。 A list of widgets:

Things missing:

  • inheritance ie. style "button" = "default", but this is usually not neccessary because of merging, and needs a warning as it doesn't work correctly for engine options AFAIK

  • The GtkSettings properties are not mentioned here. See http://library.gnome.org/devel/gtk/stable/GtkSettings.html#id3227906 for a lit of properties that can be set (not all of them make sense from the gtkrc).

  • Need information about icon size handling and a list of icon sizes in GNOME (see also Redmond gtkrc that sets a bunch of icon sizes)
  • how theme engines are used, see comment in the section
  • Locale specific gtkrcs (gtkrc.de will for example be parsed in german locales). This will only be usefull in very rare cases (maybe for keybinding stuff, which is not the topic of this page).


GTK Theming Tutorial

简介

这篇指导阐述了使用GNOME 2.2及以上版本创建GTK+2主题的基础。 GTK+2 API的知识可以对复杂的主题有帮助;可以在这个地址找到文档 http://developer.gnome.org/doc/API/2.0/gtk/index.html. 其他人的主题也很有帮助,可以从这个链接资源找到更多的GTK主题 ../UsefulLinks.

主题通常在一个公共的目录(所有用户都可使用,如 /usr/share/themes/)或者在 ~/.themes/ (只为你自己准备)。一个放置所创建主题的方便的地方是 ~/.themes/YOUR_THEME_NAME/gtk-2.0/。 在这个gtk-2.0目录中可以放置所有与主题有关的文件。如果相同名字的主题被安装在公共目录以及 ~/.themes目录中, GNOME将会使用 ~/.themes目录中的那一个。

一个学习主题的好方法是检测别人的主题。在你安装GNOME的时候无疑会自带一些主题。更多主题可以在下面找到:

结构

Widgets

GTK拥有一套大量的widget集合,如按钮、滚动条、编辑框等,每一种组件的属性都可以单独进行配置。

所有的widget都是由GtkWidget派生出来的,也就是说,如果更改了GtkWidget的属性,所有的widgets都将会受到影响。此外,大多数widget有其"父类",比如GtkButton属性的改变同样会应用到GtkCheckButton上,除非对其进行单独的配置。

因此在应用风格的时候这个层次结构很重要,可以在这里找到 http://developer.gnome.org/doc/API/2.0/gtk/ch01.html

Styles

任何一种想改变的属性都可以通过所谓的"styles"来进行设置。设置的方式有两种,一种是使用GTK+的主题系统,但这种方式中只给出了一组有限的预定义好的风格属性,比如设置滚动条的宽度;另一种就是通过使用engines这种机制来实现,其中大多数的主题选择都是可行的。

GTK主题系统有趣的一部分就是将不同的styles合并在一起成为一个最终的主题,所以用户通常需要定义出一个基本的style,其包含所有的通用选项配置,然后在此基础上针对组件专有的属性进行修改,比如颜色的修改。

Engines

如上所述,engines给用户提供了很多有趣的风格选项,这些选项是engine特有的,如果你学习了一种引擎的选项,你也需要学习其它引擎提供的选项。如果没有任何engine,GTK将使用一个非常基础的主题,而这个主题只会提供一个非常单调的外表(Raleigh主题不使用engine)。

有很多不同的引擎,有些提供很多可能性,有些则只有固定的外表。 GTK+主题的重要部分是寻找基于主题的一个或多个引擎。

gtkrc文件

GTK主题在gtkrc文件内部。文件中的注释用 # 标记,多行注释与C类似,用 /* */.

下面通过一个简单的例子演示如何创建一个基础的主题。

style "default-style"
{
        # modify the x/ythickness, used for spacing all over the place
        xthickness = 3
        ythickness = 3

        # one can set so called "style properties"
        GtkRange::slider-width = 15

        # set the background to a light grey
        bg[NORMAL] = "#f6f6f6"
        # and the forground to black
        fg[NORMAL] = "#000000"
}

class "GtkWidget" style "default-style"

以上片段创建了一个名为"default-style"的style,紧接着把这个style应用到所有的widget上。

下面对style内部不同的选项做进一步的解读

The Style

上面的例子很短小,给出了简单的GTK+可能需要的每一部分。

x/ythickness

        xthickness = 3
        ythickness = 3

这个选项在很多地方使用,决定了文本与组件边界之间的填充宽度。更多细节请见特定组件的geometry文档。

Style Properties

        GtkRange::slider-width = 15

/GtkRange的风格属性之"滑块宽度"设置为15像素。

在GTK和一些应用程序中有更多类似的风格属性,它们使得用户能够改变widget的基本属性。请参考widget文档和 /StyleProperties中自动生成的风格属性列表。

风格属性通常的格式为

        WidgetName::style-property-name = VALUE

value的格式决定于风格属性的类型。通常可能的values来自GTK+的枚举如 GTK_SHADOW_IN、整数以及颜色值(如下所示的格式)。注意 TRUEFALSE 不能在主题中使用,可以用 1 和 0 代替。

风格属性的一些例子:

Property

Description

Example

GtkWidget::focus-line-width

Width of the focus line

GtkWidget::focus-line-width = 2

GtkWidget::link-color

Color of unvisited links, that is supposed to be used by applications

GtkWidget::link-color = "#0000ff"

...

一个有趣的特征是你可以只在子类上简单地设置风格属性。所以对于在风格上设置只应用于 GtkScaleGtkRange::trough-side-details,可以只在scale上设置。

style "default" {
        GtkScale::trough-side-details = 1
}

class "GtkWidget" style "default"

这将只影响 /GtkScale,而不影响scrollbars。

Colors

bg[NORMAL] = "#f6f6f6"

bg 代表背景。有四种类型如下:

Category

Usage

fg

Foreground color. Used for text on buttons. Also used for the button borders in some engines.

bg

Background color. This is the background color of windows and buttons.

text

Text color for text input widgets and lists (/GtkTreeView).

base

Background color of text widgets and lists.

NORMAL 是颜色使用的状态。 GTK内部有5种状态:

State

Usage

NORMAL

The normal color, nothing special happening.

PRELIGHT

Prelight means mouse over effects. Usually the background will be slightly lighter.

ACTIVE

This state is used for buttons while the mouse is pressed.

INSENSITIVE

Used for widgets that are insensitive and cannot be used at that point.

SELECTED

This state is used for example for selected text.

有5种描述颜色的不同方法,最常用的可能是上面例子中使用的十六进制法。

hexadecimal

"#RGB", "#RRGGBB", "#RRRGGGBBB" and "#RRRRGGGGBBBB"

floating point

{R, B, G} where R, B and G are floating point numbers between and including 0.0 and 1.0 (That is 1.0 not simply 1 as that will be interpreted as an integer)

integer values

{R, B, G} where R, B and G are values between and including 0 and 65535

color strings from X

eg. "Red", "Magenta", etc. These are shipped with the X server, and can often be found in /etc/X11/rgb.txt

Symbolic colors and color expressions

For example lighter(@color_name). Please see /SymbolicColors for details.

Applying the Style

在开头的代码段中我们用颜色定义了一个风格,而GTK需要知道这个风格应该用到哪里。如下:

class "GtkWidget" style "default-style"

应用"default-style"到每个基于GtkWidget的组件。由于每个组件都基于 GtkWidget,所以它被应用到每个地方。

GTK内有三种应用风格的方式,分别是 classwidget_class 以及 widget搞清楚风格以什么样的方式被应用是理解整个GTK主题系统的关键,所以一个细致的希望不那么乏味的阐述将在下面展开。

The different matching lines

class

class 匹配是基于widget类层次结构的(again see http://developer.gnome.org/doc/API/2.0/gtk/ch01.html).

当寻找与当前组件相关的风格时,它会沿着widget类层次结构进行,检查其中的widget类的名称是否与被应用风格的组件名称匹配,然后以此来应用风格。 拿上面的例子来说明,与 GtkToggleButton 一起。

它将按照这个顺序检查到以下名称:

  • GtkWidget <- match found here

  • GtkContainer, no match

  • GtkBin, no match

  • GtkButton, no match

  • GtkToggleButton, no match

这里不仅可以使用像GtkWidget这样的名称,也可以使用"Gt?T*"这样的表达式,其中'*'表示若干字符,'?'表示一个字符,它们都将和点在路径中配合使用。

widget_class matches

假定有一个简单的“Hello World!”程序,程序有一个 GtkWindow,其上有一个 GtkButtonGtkButton上面有一个 GtkLabel,其内容是"Hello World"。

让我们看看下面的例子:

widget_class "*.GtkButton.*" style "button-content"

Classpath

the window

GtkWindow

the button inside the window

GtkWidget.GtkButton

the label inside the button

GtkWidget.GtkButton.GtkLabel

由于"*.GtkButton.*"只能匹配"GtkWidget.GtkButton.GtkLabel",所以在程序中只有标签会应用"button-content"风格。若想要GtkToggleButton也应用"button-content"风格,可以按下面的方法进行匹配:

widget_class "*.*Button.*" style "button-content"

从GTK+ 2.10开始使用另一种方法:

widget_class "*.<GtkButton>.*" style "button-content"

这里尖括号的作用类似于前面提到的class matches,因此,如果有一个 GtkToggleButtonGTK会检测到它是继承自 GtkButton 的,从而将该风格应用到标签上。

如果想在程序中设置特定的组件,那么指出不同的路径是比较困难的,一个可能的方法是使用eXperience engine并且在命令行中设置 EXPERIENCE_PRINT_WIDGET_PATH=TRUE

widget matches

widget matches 是基于组件的名称进行匹配的,如果程序中某个指定的组件需要被改动,这种匹配方式将会很有效。与 widget_class matches类似,在组件的名称中会以“.”为分隔进行匹配。如果某个组件没有名称,会用它的组件类的名称来替代。

仍然以上面的程序为例,其窗口被命名为"my-app",按钮被命名为"my-button",而标签没有名称,则它进行匹配的路径如下:

widget path

the window

my-app

the button

my-app.my-button

the label

my-app.my-button.GtkLabel

如果只想针对按钮应用风格,可以按照下面的写法:

widget "my-app.my-button" style "my-app button fix"

Order of the Merge

GTK按顺序合并在上面提及的不同"matches"。风格合并会在之后覆盖之前的设置。 class matches很广泛,而 widget match则针对特定的组件。 widget_classwidget matches的顺序和文件中的一致,后面的会覆盖前面的。

class matches则不同,匹配的类在层次结构中的位置越高其优先级就越高,举例如下:

class "*" style "default"
class "GtkButton" style "button"

对于通常的button来说,button风格覆盖了default风格,而对于GtkToggleButton则不是如此,因为再次匹配时,"*""GtkButton" 具有更高的优先级,其风格合并的次序如下:

Test against

styles merged in

GtkWidget

"default"

GtkContainer

"default"

GtkBin

"default"

GtkButton

first "default", then "button" (order in the gtkrc)

GtkToggleButton

"default" again, which overrides the settings from "button"

正如我们所看到的,"default" 风格多次被合并,因此,使用 "*" 来为widget指定默认风格并不是一个好主意,GTK+需要做额外的工作,而且我们有可能得不到想要的效果。

{i} 事实上,gtk也将匹配 classGObject上,但是实际中并没有任何不同。

Priority

/!\ The following is here for completeness sake. It is only needed in very seldom cases to override applications settings. Examples for this are the nautilus "more" widget (ie. the thing at the top that is shown in the trash and when buring CDs/DVDs) or to override GIMP settings.

可以对上面任一种"matches"添加优先级。

class "SomeWidget" style : PRIORITY "some-style"

PRIORITY 是下面的一种:

Priority

lowest

gtk

Priority of the buildin theme

application

dunno what this is for, if application use this they will be overriden by the theme.

theme

Default priority of themes

rc

gtkrc files set in the GTK2_RC_FILES enviroment variable and the standard files ~/.gtkrc-2.0 and /etc/gtk-2.0/gtkrc

highest

Engines

/!\ 呃,我不太情愿写这部分。它所涉及的东西不多,因此感觉它太少了。

如前所述,engines被用来定义外观及扩展风格。用Clearlooks engine为例,可以按下面的做法:

style "some-style" {
        engine "clearlooks" {
                # engine specific settings go here
        }
}

这意味着Clearlooks engine将使用它自己默认的设置。可以在其块中改变engine的设置。不同engines的可能选项的描述请参考 ../GtkEngines 中的文档。

Tips

有一些预览程序如 "The Widget Factory"。在 ../UsefulLinks中去看一看。

可以通过使用 include 选项将 gtkrc 文件分成多个文件。所以你可以为叫作 button-styles 的button风格做一个额外的文件并简单地包含一下即可。

# include the button-styles file
include "button-styles"

Previous chapter: Icon Themes

Back to Tutorial start page

Next chapter: GDM Themes

Check List

Engine

  • Have a good GTK+ hacker give a once-over look at the theme engine's code. Is it sane? Does it do anything obviously stupid? Does it leak cairo contexts, GCs, pixmaps, regions, etc.?
  • Check the implementation of the GtkStyleClass virtual methods. Do they handle the "detail" argument correctly (null detail, unexpected string in detail)? Do they handle the "widget" argument correctly (may be null as well)? What happens if you draw very small elements (2x2 pixel boxes, 0x0 pixel boxes, etc.)?

    • gtk-engines has a "torturetest" application. This program basically brute forces almost all code paths in an engine.

Theme

  • Check that all the core desktop apps look correct with the theme. "Look correct" means, for example, that there are no sharp/ugly transitions in gradient backgrounds - this may be a bug in the app's widget structure. At least checking for this will help in finding bugs somewhere.

  • Check apps that do funny stuff with widgets. Check the toolbars in Evolution and its message composer; those go through libbonoboui, not GTK+, and this has been known to cause problems with gradient-y themes.
  • Check that flipped widgets in RTL locales are correctly drawn.
  • Check that foreign toolkits using gtk engines for rendering work with your engine. The big apps to try this are OpenOffice and Firefox.

  • Does the theme have enough contrast on crappy laptop displays? Industrial has problems with this, for example.
  • Does the theme look correct if you increase (and decrease) the font size? (In addition to text readability take note of Menu and SpinButton Arrows which change according to font size)

  • Does the theme have acceptable performance on low-end machines? This is hard to test, but have someone with a low-memory Pentium II give the theme a try.

Attic/GnomeArt/Tutorials/GtkThemesZhCN (last edited 2013-11-27 14:33:52 by WilliamJonMcCann)