gtkmm-documentation master - en to zh_CN translation catalogue (1604 entries)

en: Programming with <application>gtkmm</application> 4
zh_CN: <application>gtkmm</application>4 程序设计

en: <firstname>Bernhard</firstname> <surname>Rieder</surname> <contrib>Chapter on "Timeouts".</contrib>
zh_CN: <firstname>Bernhard</firstname> <surname>Rieder</surname><contrib>编写"Timeouts"部分。</contrib>

en: <firstname>Jonathon</firstname> <surname>Jongsma</surname> <contrib>Chapter on "Drawing with Cairo".</contrib> <contrib>Chapter on "Working with gtkmm's Source Code".</contrib> <contrib>Chapter on "Recent Files".</contrib>
zh_CN: <firstname>Jonathon</firstname> <surname>Jongsma</surname><contrib>编写使用开罗绘图章节。</contrib><contrib>编写使用gtkmm源代码章节。</contrib><contrib>编写"最近的文件"。</contrib>

en: <firstname>Ole</firstname> <surname>Laursen</surname> <contrib>Parts of chapter on "Internationalization".</contrib>
zh_CN: <firstname>Ole</firstname> <surname>Laursen</surname> <contrib>编写"国际化"章节的一部分。</contrib>

en: <firstname>Marko</firstname> <surname>Anastasov</surname> <contrib>Chapter on "Printing".</contrib> <contrib>Parts of chapter on "Internationalization".</contrib>
zh_CN: <firstname>Marko</firstname> <surname>Anastasov</surname> <contrib>编写"打印"章节。</contrib> <contrib>编写"国际化"章节的一部分。</contrib>

en: <firstname>Daniel</firstname> <surname>Elstner</surname> <contrib>Section "Build Structure" of chapter on "Wrapping C Libraries with gmmproc".</contrib>
zh_CN: <firstname>Daniel</firstname> <surname>Elstner</surname>编写《使用 gmmproc 封装 C 库》〈构建结构〉章节。

en: <firstname>Chris</firstname> <surname>Vine</surname> <contrib>Chapter on "Multi-threaded programs".</contrib>
zh_CN: <firstname>Chris</firstname> <surname>Vine</surname><contrib>编写"多线程编程"章节。</contrib>

en: <firstname>David</firstname> <surname>King</surname> <contrib>Section on Gtk::Grid.</contrib>
zh_CN: <firstname>David</firstname> <surname>King</surname><contrib>编写Gtk::Grid部分。</contrib>

en: <firstname>Pedro</firstname> <surname>Ferreira</surname> <contrib>Chapter on Keyboard Events.</contrib>
zh_CN: <firstname>Pedro</firstname> <surname>Ferreira</surname><contrib>编写键盘事件章节。</contrib>

en: <firstname>Kjell</firstname> <surname>Ahlstedt</surname> <contrib>Update from gtkmm 3 to gtkmm 4.</contrib> <contrib>Chapter on "Building applications".</contrib>
zh_CN: <firstname>Kjell</firstname> <surname>Ahlstedt</surname> <contrib>编写从gtkmm迁移到gtkmm4指南。</contrib> <contrib>编写"构建应用"章节。</contrib>

en: This book explains key concepts of the <application>gtkmm</application> C++ API for creating user interfaces. It also introduces the main user interface elements ("widgets").
zh_CN: 本书说明了使用<application>gtkmm</application> C++ API 创建用户界面的重要概念，并且介绍了主要的用户界面元素(“widget”)。

en: Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. You may obtain a copy of the GNU Free Documentation License from the Free Software Foundation by visiting their Web site or by writing to: Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
zh_CN: 根据由自由软件基金发布的 GNU 自由文档协议版本1.2或更高版本的条款，授权复制、分发和/或修改此文档；并且，没有不可变章节，没有封面文本，并且没有封底文本。您可以通过访问自由软件基金(FSF)的网站或写邮件至：Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 来获得一份 GNU 自由文档协议。

en: Introduction
zh_CN: 序言

en: This book
zh_CN: 本书

en: This book explains key concepts of the <application>gtkmm</application> C++ API for creating user interfaces. It also introduces the main user interface elements ("widgets"). Although it mentions classes, constructors, and methods, it does not go into great detail. Therefore, for full API information you should follow the links into the reference documentation.
zh_CN: 本书说明了使用<application>gtkmm</application> C++ API 创建用户界面的重要概念，并且介绍了主要的用户界面元素(“widget”)。虽然提到了类、构造函数和方法，但是并不会深入其细节。因此，如果需要完整的 API 信息，您应当顺着链接访问参考文档。

en: This book assumes a good understanding of C++, and how to create C++ programs.
zh_CN: 本书假定读者拥有对 C++ 良好的理解，并且知道如何去创建一个 C++ 程序。

en: We would very much like to hear of any problems you have learning <application>gtkmm</application> with this document, and would appreciate input regarding improvements. Please see the <link linkend="chapter-contributing">Contributing</link> section for further information.
zh_CN: 我们非常愿意聆听您在使用此文档学习 <application>gtkmm</application> 时碰到的任何问题，并且感激对此作出的改进。请访问 <link linkend="chapter-contributing">贡献</link> 节以获得进一步的信息。

en: This book describes <application>gtkmm</application> 4, but some sections have not been fully updated. There are paragraphs that describe <application>gtkmm</application> 3 rather than <application>gtkmm</application> 4. All shown example programs are compatible with <application>gtkmm</application> 4, though.
zh_CN: 本书介绍了<application>gtkmm</application>4, 但是有些部分还没有完成更新 以下是描述<application>gtkmm</application>3而不是<application>gtkmm</application>4的段落。不过显式的所有示例都与<application>gtkmm</application>4兼容。

en: <application>gtkmm</application> is a C++ wrapper for <ulink url="http://www.gtk.org/">GTK</ulink>, a library used to create graphical user interfaces. It is licensed using the LGPL license, so you can develop open software, free software, or even commercial non-free software using <application>gtkmm</application> without purchasing licenses.
zh_CN: <application>gtkmm</application> 是一个 <ulink url="http://www.gtk.org/">GTK</ulink> 的 C++ 封装，GTK+ 是一个用于创建图形用户界面的软件库。它使用 LGPL 协议，因此您可以使用 <application>gtkmm</application> 开发开放软件、自由软件，甚至商业非免费软件而不需支付任何版权费用。

en: <application>gtkmm</application> was originally named gtk-- because GTK was originally named GTK+ and had a + in the name. However, as -- is not easily indexed by search engines, the package generally went by the name <application>gtkmm</application>, and that's what we stuck with.
zh_CN: <application>gtkmm</application> 曾经被称为 gtk--，那是因为 GTK+ 的名字中已经有了一个加号。但是，由于 -- 不容易被搜索引擎索引，所以项目名字就渐渐的变成了<application>gtkmm</application>，后来我们就一直使用这个名字。

en: Why use <application>gtkmm</application> instead of GTK?
zh_CN: 为什么要使用 <application>gtkmm</application> 而不是 GTK？

en: <application>gtkmm</application> allows you to write code using normal C++ techniques such as encapsulation, derivation, and polymorphism. As a C++ programmer you probably already realise that this leads to clearer and better organized code.
zh_CN: <application>gtkmm</application> 允许你使用常用的 C++ 技术来撰写代码，比如封装、继承和多态。作为一个 C++ 程序员，你可能已经意识到这会让代码更加清晰、更加良好的管理代码。

en: <application>gtkmm</application> is more type-safe, so the compiler can detect errors that would only be detected at run time when using C. This use of specific types also makes the API clearer because you can see what types should be used just by looking at a method's declaration.
zh_CN: <application>gtkmm</application> 更加类型安全，因此编译器可以检测出一些 C 只能在运行时才能检测出来的错误。这种使用特定类型的方法同样使得 API 更加清晰，因为你只需要通过看一下函数声明就可以知道应该使用什么类型了。

en: Inheritance can be used to derive new widgets. The derivation of new widgets in GTK C code is so complicated and error prone that almost no C coders do it. As a C++ developer you know that derivation is an essential Object Orientated technique.
zh_CN: 可以使用继承来衍生新的部件。在 GTK 中使用 C 代码来衍生新部件是非常复杂的，并且很容易出错，因此几乎没有 C 的程序员这么做。作为 C++ 开发人员，你知道继承是一个基本的面向对象技术。

en: Member instances can be used, simplifying memory management. All GTK C widgets are dealt with by use of pointers. As a C++ coder you know that pointers should be avoided where possible.
zh_CN: 可以使用成员实例，简化了内存管理。所有的 GTK 的 C 部件都是使用指针进行操作的。作为 C++ 程序员，你知道指针应当尽量避免使用。

en: <application>gtkmm</application> involves less code compared to GTK, which uses prefixed function names and lots of cast macros.
zh_CN: <application>gtkmm</application> 比 GTK 的代码更加简短，GTK 使用了大量带前缀的函数名以及大量的转型宏。

en: <application>gtkmm</application> compared to Qt
zh_CN: <application>gtkmm</application> 对比 Qt

en: Trolltech's Qt is the closest competition to <application>gtkmm</application>, so it deserves discussion.
zh_CN: Trolltech 公司的 Qt 是和 <application>gtkmm</application> 最相似的有竞争力的产品，所以应该对其进行一下讨论。

en: <application>gtkmm</application> developers tend to prefer <application>gtkmm</application> to Qt because <application>gtkmm</application> does things in a more C++ way. Qt originates from a time when C++ and the standard library were not standardised or well supported by compilers. It therefore duplicates a lot of stuff that is now in the standard library, such as containers and type information. Most significantly, Trolltech modified the C++ language to provide signals, so that Qt classes cannot be used easily with non-Qt classes. <application>gtkmm</application> was able to use standard C++ to provide signals without changing the C++ language. See the <ulink url="https://wiki.gnome.org/Projects/gtkmm/FAQ">FAQ</ulink> for more detailed differences.
zh_CN: <application>gtkmm</application> 开发人员更倾向于使用 <application>gtkmm</application> 而不是 Qt，因为 <application>gtkmm</application> 的使用更加符合 C++ 的方式。Qt 是诞生自 C++ 及其库尚未标准化或尚未被大多数编译器所支持的年代。它重复了大量的现存于标准库中的东西，比如容器、类型信息等等。最重要的是，Trolltech 修改了 C++ 语言以提供信号的功能，这样 Qt 的类无法很容易的与非 Qt 类共同使用。<application>gtkmm</application> 则可以使用标准 C++ 提供信号功能，而无需修改 C++ 语言。请看<ulink url="https://wiki.gnome.org/Projects/gtkmm/FAQ">常见问题</ulink>以了解具体差异。

en: <application>gtkmm</application> is a wrapper
zh_CN: <application>gtkmm</application> 是一个封装

en: <application>gtkmm</application> is not a native C++ toolkit, but a C++ wrapper of a C toolkit. This separation of interface and implementation has advantages. The <application>gtkmm</application> developers spend most of their time talking about how <application>gtkmm</application> can present the clearest API, without awkward compromises due to obscure technical details. We contribute a little to the underlying GTK code base, but so do the C coders, and the Perl coders and the Python coders, etc. Therefore GTK benefits from a broader user base than language-specific toolkits - there are more implementers, more developers, more testers, and more users.
zh_CN: <application>gtkmm</application> 并不是一个原生的 C++ 工具集，而是一个对于 C 工具集的 C++ 封装。这种分离接口和实现的方式存在诸多优势。<application>gtkmm</application> 开发人员用了他们大量的时间来讨论如何让 <application>gtkmm</application> 提供一个最清晰的 API，而不必为模糊的技术细节尴尬的进行妥协。我们想其他的 C 程序员、Perl 程序员和 Python 程序员等等一样，对底层的 GTK 代码库进行了一点点贡献。因此，GTK 可以从比某个语言特定的工具集更广泛的用户群中获得好处，有更多的实现、更多的开发人员、更多的测试人员以及更多的用户。

en: Installation
zh_CN: 安装

en: Dependencies
zh_CN: 依赖关系

en: Before attempting to install <application>gtkmm</application><application>-4.0</application>, you might first need to install these other packages.
zh_CN: 在试图安装 <application>gtkmm</application><application>-4.0</application>之前，你必须已经安装了这些包。

en: <application>gtk4</application>
zh_CN: <application>gtkmm4</application>

en: These dependencies have their own dependencies, including the following applications and libraries:
zh_CN: 这些依赖有它们自己所依赖的软件包，包括下列应用程序和软件库：

en: Unix and Linux
zh_CN: Unix 和 Linux

en: Prebuilt Packages
zh_CN: 预编译的包

en: Recent versions of <application>gtkmm</application> are packaged by nearly every major Linux distribution these days. So, if you use Linux, you can probably get started with <application>gtkmm</application> by installing the package from the official repository for your distribution. Distributions that include <application>gtkmm</application> in their repositories include Debian, Ubuntu, Red Hat, Fedora, Mandriva, Suse, and many others.
zh_CN: <application>gtkmm</application> 最新的版本的软件包几乎存在于今天每一个主流的 Linux 发布版本中。所以，如果你使用 Linux，你可能只需要从官方的软件库安装相应的软件包，然后就可以开始使用 <application>gtkmm</application> 了。已经在它们的软件库里面包含了 <application>gtkmm</application> 的发布版本有：Debian、Ubuntu、Red Hat、Fedora、Mandriva、SuSE 等等。

en: The names of the <application>gtkmm</application> packages vary from distribution to distribution (e.g. <application>libgtkmm-4.0-dev</application> on Debian and Ubuntu or <application>gtkmm40-devel</application> on Red Hat Fedora), so check with your distribution's package management program for the correct package name and install it like you would any other package.
zh_CN: <application>gtkmm</application> 软件包的名字可能在不同的发行版中所不同 (例如，在 Debian 和 Ubuntu 上的名字是<application>libgtkmm-4.0-dev</application>，而在 Red Hat Fedora 上则是 <application>gtkmm40-devel</application>)，因此，在你的发行版的软件包管理程序中查一下正确的名字，然后像其它软件包一样的安装它。

en: The package names will not change when new API/ABI-compatible versions of <application>gtkmm</application> are released. Otherwise they would not be API/ABI-compatible. So don't be surprised, for instance, to find <application>gtkmm</application> 4.8 supplied by Debian's <application>libgtkmm-4.0-dev</application> package.
zh_CN: 当新的 API/ABI 兼容的 <application>gtkmm</application> 版本发布后，其包的名称将不会改变。否则的话，就说明 API/ABI 不兼容。所以，如果在 Debian 的 <application>libgtkmm-4.0-dev</application> 包中发现提供的实际上是 <application>gtkmm</application> 4.8 的话不要太惊讶。

en: Installing From Source
zh_CN: 从源代码安装

en: If your distribution does not provide a pre-built <application>gtkmm</application> package, or if you want to install a different version than the one provided by your distribution, you can also install <application>gtkmm</application> from source. The source code for <application>gtkmm</application> can be downloaded from <ulink url="https://download.gnome.org/sources/gtkmm/"/>.
zh_CN: 如果你的发行版没提供预编译的 <application>gtkmm</application> 包，或者如果你想安装一个和发行版所提供的不同的版本，那么你也可以从源代码安装 <application>gtkmm</application>。可以从 <ulink url="https://download.gnome.org/sources/gtkmm/"/> 中下载 <application>gtkmm</application> 的源代码。

en: After you've installed all of the dependencies, download the <application>gtkmm</application> source code, unpack it, and change to the newly created directory. <application>gtkmm</application> can be built with Meson. See the <filename>README</filename> file in the <application>gtkmm</application> version you've downloaded.
zh_CN: 在安装了所有依赖的库后，下载 <application>gtkmm</application> 源代码、解压缩，并且切换到新创建的目录。<application>gtkmm</application>可以使用Meson构建。 参见你所下载的<application>gtkmm</application>源代码中的<filename>README</filename>。

en: Remember that on a Unix or Linux operating system, you will probably need to be <literal>root</literal> to install software. The <command>su</command> or <command>sudo</command> command will allow you to enter the <literal>root</literal> password and have <literal>root</literal> status temporarily.
zh_CN: 记住，在 Unix 或 Linux 操作系统上，你也许需要 <literal>root</literal> 权限以安装软件。<command>su</command>或者<command>sudo</command> 命令允许你输入 <literal>root</literal> 密码，并且临时拥有 <literal>root</literal> 权限。

en: The <filename>configure</filename> script or <command>meson</command> will check to make sure all of the required dependencies are already installed. If you are missing any dependencies, it will exit and display an error.
zh_CN: <filename>configure</filename>脚本或者<command>meson</command>将会检查以确认所有必须的依赖软件包都已经正确的安装了。如果你遗漏了某个依赖软件包的话，它会退出并提示错误信息。

en: By default, <application>gtkmm</application> if built with Autotools, will be installed under the <filename>/usr/local</filename> directory. On some systems you may need to install to a different location. For instance, on Red Hat Linux systems you might use the <literal>--prefix</literal> option with configure, like so: <_:screen-1/>
zh_CN: 默认情况下，如果使用Autotools构建<application>gtkmm</application> 则其将会被安装在 <filename>/usr/local</filename> 目录。在有些系统中，你也许需要安装到不同的位置。比如，在 Red Hat Linux 系统中，你也许需要使用 <literal>--prefix</literal> 选项进行配置，例如：<_:screen-1/>

en: You should be very careful when installing to standard system prefixes such as <filename>/usr</filename>. Linux distributions install software packages to <filename>/usr</filename>, so installing a source package to this prefix could corrupt or conflict with software installed using your distribution's package-management system. Ideally, you should use a separate prefix for all software you install from source.
zh_CN: 在安装到标准系统前缀时，如 <filename>/usr</filename>，你必须非常小心。Linux 发行版会安装软件到 <filename>/usr</filename>，所以安装源代码包到这个位置可能会破坏或与使用软件包管理器安装的软件冲突。理想情况下，你应当将从源代码安装的软件都安装到一个独立位置。

en: If you want to help develop <application>gtkmm</application> or experiment with new features, you can also install <application>gtkmm</application> from git. Most users will never need to do this, but if you're interested in helping with <application>gtkmm</application> development, see the <link linkend="chapter-working-with-source">Working with gtkmm's Source Code</link> appendix.
zh_CN: 如果你想帮助开发 <application>gtkmm</application>，或实验一些新的功能，你也可以直接从 Git 安装 <application>gtkmm</application>。大多数用户绝对不需要这么做，但是如果你对帮助 <application>gtkmm</application> 开发感兴趣，请看附录：<link linkend="chapter-working-with-source">使用 gtkmm 源代码</link>。

en: GTK and <application>gtkmm</application> were designed to work well with Microsoft Windows, and the developers encourage its use on the win32 platform. However, Windows has no standard installation system for development libraries. Please see the <ulink url="https://wiki.gnome.org/Projects/gtkmm/MSWindows">Windows Installation</ulink> page or the <link linkend="sec-windows-installation"><application>gtkmm</application> and Win32</link> appendix for Windows-specific installation instructions and notes.
zh_CN: GTK和<application>gtkmm</application>被设计成在Microsoft Windows上也能很好地工作，而且开发者们鼓励在win32平台上使用它们。但是目前还有没为Windows平台的开发库提供标准的安装方法。请参阅 <ulink url="https://wiki.gnome.org/Projects/gtkmm/MSWindows">Windows Intallation</ulink>或者<link linkend="sec-windows-installation"><application>gtkmm</application>和Win32</link>以得到关于Windows相关的安装方法和注意事项。

en: Basics
zh_CN: 基础

en: This chapter will introduce some of the most important aspects of <application>gtkmm</application> coding. These will be demonstrated with simple working example code. However, this is just a taster, so you need to look at the other chapters for more substantial information.
zh_CN: 这一章将介绍 <application>gtkmm</application> 编程中一些重要的方面。这些将由一些可以运行的示例代码来演示。然而，这仅仅是一种尝试，你还需要继续看其它章节，以得到更实质性的信息。

en: Your existing knowledge of C++ will help you with <application>gtkmm</application> as it would with any library. Unless we state otherwise, you can expect <application>gtkmm</application> classes to behave like any other C++ class, and you can expect to use your existing C++ techniques with <application>gtkmm</application> classes.
zh_CN: 你现有的 C++ 知识将会帮助你使用 <application>gtkmm</application>，因为它可以和任何库一同工作。除非我们额外声明，你可以期待 <application>gtkmm</application> 类会像任何其它 C++ 类一样，并且你可以期待在 <application>gtkmm</application> 类上使用你现有的知识。

en: Simple Example
zh_CN: 简单的例子

en: To begin our introduction to <application>gtkmm</application>, we'll start with the simplest program possible. This program will create an empty 200 x 200 pixel window.
zh_CN: 在开始介绍 <application>gtkmm</application> 之前，我们将以一个尽可能简单的程序开始。这个程序创建一个 200 x 200 像素大小的空窗口。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/base">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/base">源代码</ulink>

en: We will now explain each part of the example
zh_CN: 我们将会对这个例子的每个部分都进行讲解

en: All <application>gtkmm</application> programs must include certain <application>gtkmm</application> headers; <literal>gtkmm.h</literal> includes the entire <application>gtkmm</application> kit. This is usually not a good idea, because it includes a megabyte or so of headers, but for simple programs, it suffices.
zh_CN: 所有的 <application>gtkmm</application> 程序都需要包含一些特定的 <application>gtkmm</application> 头文件；<literal>gtkmm.h</literal> 包含了所有 <application>gtkmm</application> 的内容。通常来说，这并不是一个好主意，因为它包括了一兆左右的头文件。当然，对于这个简单的程序，这就够了。

en: The next part of the program:
zh_CN: 这个程序的下一部分：

en: defines the <classname>MyWindow</classname> class. Its default constructor sets the window's title and default (initial) size.
zh_CN: 定义<classname>MyWindow</classname>类。这个类的构造函数设置了窗口标题和窗口的初始默认尺寸。

en: The <function>main()</function> function's first statement:
zh_CN: <function>main()</function>函数的第一条语句：

en: creates a <classname>Gtk::Application</classname> object, stored in a <classname>Glib::RefPtr</classname> smartpointer. This is needed in all <application>gtkmm</application> applications. The <methodname>create()</methodname> method for this object initializes <application>gtkmm</application>.
zh_CN: 创建一个<classname>Gtk::Application</classname>对象，将其储存在一个<classname>Glib::RefPtr</classname>智能指针中。所有的<application>gtkmm</application>应用都需要如此做。该对象的<methodname>create()</methodname>方法将初始化<application>gtkmm</application>。

en: The last line creates and shows a window and enters the <application>gtkmm</application> main processing loop, which will finish when the window is closed. Your <function>main()</function> function will then return with an appropriate success or error code. The <parameter>argc</parameter> and <parameter>argv</parameter> arguments, passed to your application on the command line, can be checked when <methodname>make_window_and_run()</methodname> is called, but this simple application does not use those arguments.
zh_CN: 最后一行显示窗口并进入<application>gtkmm</application>主循环，当窗口被关闭。你的<function>main()</function>函数将会返回成功或者适当的错误码。<parameter>argc</parameter>和<parameter>argv</parameter>参数会将命令行传递给你的应用程序，可以在<methodname>make_window_and_run()</methodname>被调用时对其进行检查，不过这个简单的应用程序并不会如此做。

en: After putting the source code in <literal>simple.cc</literal> you can compile the above program with <application>gcc</application> using:
zh_CN: 将源代码放入<literal>simple.cc</literal>后你可以使用以下<application>gcc</application>命令编译上述程序：

en: Note that you must surround the <literal>pkg-config</literal> invocation with backquotes. Backquotes cause the shell to execute the command inside them, and to use the command's output as part of the command line. Note also that <literal>simple.cc</literal> must come before the <literal>pkg-config</literal> invocation on the command line. <literal>-std=c++17</literal> is necessary only if your compiler is not C++17 compliant by default.
zh_CN: 注意，你必须将 <literal>pkg-config</literal> 的调用包含在一对反单引号中。反单引号会导致其内的命令由 shell 执行，并且将命令的输出做为该命令行的一部分来使用。另外请注意，在命令行中<literal>simple.cc</literal>必须位于<literal>pkg-config</literal>调用之前。<literal>-std=c++17</literal>只在你的编译器默认不启用C++17标准的时候才需要。

en: Headers and Linking
zh_CN: 头文件和链接

en: This section describes building with Autotools. The newer <ulink url="https://mesonbuild.com/">Meson build system</ulink> is a good alternative.
zh_CN: 本小节介绍了如何使用Autotools进行构建。而较新的<ulink url="https://mesonbuild.com/">Meson构建系统</ulink>是一个不错的替代选项。

en: Although we have shown the compilation command for the simple example, you really should use the automake and autoconf tools, as described in "Autoconf, Automake, Libtool", by G. V. Vaughan et al. The examples used in this book are included in the <application>gtkmm-documentation</application> package, with appropriate build files, so we won't show the build commands in future. You'll just need to find the appropriate directory and type <literal>make</literal>.
zh_CN: 虽然我们已经给出了这个简单的例子的编译命令，但是你最好还是使用 automake 和 autoconf 工具，就像 G. V. Vaughan 等在《Autoconf, Automake, Libtool》中所描述的那样。本书中用到的例子都包含在 <application>gtkmm-documentation</application> 包内，同时附有适当的编译构建的文件，所以我们以后不会再给出任何编译命令。你只需要找到恰当的目录然后键入 <literal>make</literal>。

en: To simplify compilation, we use <literal>pkg-config</literal>, which is present in all (properly installed) <application>gtkmm</application> installations. This program 'knows' what compiler switches are needed to compile programs that use <application>gtkmm</application>. The <literal>--cflags</literal> option causes <literal>pkg-config</literal> to output a list of include directories for the compiler to look in; the <literal>--libs</literal> option requests the list of libraries for the compiler to link with and the directories to find them in. Try running it from your shell-prompt to see the results on your system.
zh_CN: 为了简化编译的过程，我们使用了 <literal>pkg-config</literal>，它存在于所有的(也许已经安装的) <application>gtkmm</application> 安装文件中。这个程序“知道”编译使用了 <application>gtkmm</application> 的程序所需要的编译器选项。<literal>--cflags</literal> 选项使 <literal>pkg-config</literal> 输出一个包含编译时需要用到的头文件的目录列表；而使用 <literal>--libs</literal> 选项将得到一个需要编译器去链接的库列表和一个用于寻找它们的目录列表。试着在你的命令行提示符下运行它，看看在你的系统上会有什么样的结果。

en: However, this is even simpler when using the <function>PKG_CHECK_MODULES()</function> macro in a standard configure.ac file with autoconf and automake. For instance: <_:programlisting-1/> This checks for the presence of gtkmm and defines MYAPP_LIBS and MYAPP_CFLAGS for use in your Makefile.am files.
zh_CN: 然而，在标准的 configure.ac 中使用 <function>PKG_CHECK_MODULES()</function> 宏，并且运行 autoconf 和 automake 后，这变的更加简单。例如：<_:programlisting-1/> 这将会检查是否存在 gtkmm，并且定义了可以在你的 Makefile.am 文件中使用的 MYAPP_LIBS 和 MYAPP_CFLAGS 变量。

en: gtkmm-4.0 is the name of the current stable API. There are older APIs called gtkmm-2.4 and gtkmm-3.0 which install in parallel when they are available. There are several versions of gtkmm-2.4, such as gtkmm 2.10 and there are several versions of the gtkmm-3.0 API. Note that the API name does not change for every version because that would be an incompatible API and ABI break. There might be a future gtkmm-5.0 API which would install in parallel with gtkmm-4.0 without affecting existing applications.
zh_CN: gtkmm-4.0 是当前稳定 API 的名字。更早期的 API 叫做 gtkmm-2.4和gtkmm-3.0，如果需要的话它可以和 gtkmm-2.4 ，gtkmm-3.0 同时安装到系统。gtkmm-2.4 有许多版本，例如，gtkmm-2.10，还有多个版本gtkmm-3.0的api。注意，API 的名字并不会随着每个版本变化而发生变化，因为如果这个发生变化了，则意味着 API 和 ABI 不再同以前保持兼容。理论上，将来可以有 gtkmm-5.0 API 与现在的 gtkmm-4.0 同时安装到系统，而现有应用程序不会受到影响。

en: Note that if you mention extra modules in addition to gtkmm-4.0, they should be separated by spaces, not commas.
zh_CN: 注意，如果你提到了除 gtkmm-4.0 之外的模块，它们需要以空格分开，而不是逗号。

en: The GNU site has more information about <ulink url="https://www.gnu.org/software/autoconf/">autoconf</ulink> and <ulink url="https://www.gnu.org/software/automake/">automake</ulink>.
zh_CN: GNU网站上拥有更多<ulink url="https://www.gnu.org/software/autoconf/">autoconf</ulink>和<ulink url="https://www.gnu.org/software/automake/">automake</ulink>的相关信息。

en: If you start by experimenting with a small application that you plan to use just for yourself, it's easier to start with a Makefile similar to the <filename>Makefile.example</filename> files in the <link linkend="chapter-building-applications">Building applications</link> chapter.
zh_CN: 如果你打算自己从小型应用程序开始试验，那么使用<link linkend="chapter-building-applications">构建应用程序</link>章节的<filename>Makefile.example</filename>文件从MakeFile开始比较容易。

en: Widgets
zh_CN: 部件

en: <application>gtkmm</application> applications consist of windows containing widgets, such as buttons and text boxes. In some other systems, widgets are called "controls". For each widget in your application's windows, there is a C++ object in your application's code. So you just need to call a method of the widget's class to affect the visible widget.
zh_CN: <application>gtkmm</application> 应用程序由一系列包含了如按钮、文本框之类部件的窗口构成。在一些其它的系统上，部件可能被称为“控件”。对于你的应用程序窗口中的每个部件，在你的代码里就会有一个对应的 C++ 对象。所以当你想控制部件行为的时候，只需要调用这个部件对象的相应方法即可。

en: Widgets are arranged inside container widgets such as frames and notebooks, in a hierarchy of widgets within widgets. Some of these container widgets, such as <classname>Gtk::Grid</classname>, are not visible - they exist only to arrange other widgets. Here is some example code that adds 2 <classname>Gtk::Button</classname> widgets to a <classname>Gtk::Box</classname> container widget: <_:programlisting-1/> and here is how to add the <classname>Gtk::Box</classname>, containing those buttons, to a <classname>Gtk::Frame</classname>, which has a visible frame and title: <_:programlisting-2/>
zh_CN: 部件被安置在褚如 frame、notebook 这样的容器部件中，以一种部件包含部件的层次结构的形式。其中一些容器部件，像 <classname>Gtk::Grid</classname> 这样的容器部件是不可见的，它们只是被用来安置其它部件的。这里有一些示例代码，将两个 <classname>Gtk::Button</classname> 部件放到一个 <classname>Box</classname> 容器部件中：<_:programlisting-1/> 接下来是如何把这个包含两个按钮的 <classname>Gtk::Box</classname> 添加到一个 <classname>Gtk::Frame</classname> 中，它包含一个可视的边框和标题：<_:programlisting-2/>

en: Most of the chapters in this book deal with specific widgets. See the <link linkend="chapter-container-widgets">Container Widgets</link> section for more details about adding widgets to container widgets.
zh_CN: 本书中的大部分章节都是讲解特定的部件。要得到更多关于添加部件到容器部件的信息，请看 <link linkend="chapter-container-widgets">容器部件</link> 这一章。

en: Although you can specify the layout and appearance of windows and widgets with C++ code, you will probably find it more convenient to design your user interfaces with <literal>Glade</literal> and load them at runtime with <literal>Gtk::Builder</literal>. See the <link linkend="chapter-builder">Glade and Gtk::Builder</link> chapter.
zh_CN: 尽管你可以使用 C++ 代码来指定窗口和部件的外观和布局，但你可能会发现使用 Glade 来设计你的界面，并且使用 <literal>Gtk::Builder</literal> 在运行时动态加载界面是更方便。请参考 <link linkend="chapter-builder">Glade 与 Gtk::Builder</link> 这一章。

en: Although <application>gtkmm</application> widget instances have lifetimes and scopes just like those of other C++ classes, <application>gtkmm</application> has an optional time-saving feature that you will see in some of the examples. The <function>Gtk::make_managed()</function> allows you to create a new widget and state that it will become owned by the container into which you place it. This allows you to create the widget, add it to the container and not be concerned about deleting it, since that will occur when the parent container (which may itself be managed) is deleted. You can learn more about <application>gtkmm</application> memory management techniques in the <link linkend="chapter-memory">Memory Management chapter</link>.
zh_CN: 尽管 <application>gtkmm</application> 部件实例拥有像其它 C++ 类那样的生存时间和作用域，<application>gtkmm</application> 还是有一些可选的节省时间的特性，接下来你会在接下来的一些例子中看到。<function>Gtk::make_managed()</function> 允许你创建一个新的部件并声明该部件由放置它的容器部件所拥有。这将允许你创建部件然后将其添加到容器中，而不必承担记住删除它的心智负担，因为当它的父容器被删除时它将被一并删除。如果你需要了解更多关于 <application>gtkmm</application> 内存管理技术的话，请看 <link linkend="chapter-memory">内存管理</link> 章节。

en: Signals
zh_CN: 信号

en: <application>gtkmm</application>, like most GUI toolkits, is <emphasis>event-driven</emphasis>. When an event occurs, such as the press of a mouse button, the appropriate signal will be <emphasis>emitted</emphasis> by the Widget that was pressed. Each Widget has a different set of signals that it can emit. To make a button click result in an action, we set up a <emphasis>signal handler</emphasis> to catch the button's "clicked" signal.
zh_CN: 像大多数GUI工具包一样，<application>gtkmm</application> 是<emphasis>事件驱动</emphasis>的。当一个事件发生时，比如说一个鼠标按键被按下，那么所点击的部件就会<emphasis>发出</emphasis>一个合适的信号。每种部件都可以发出一套不同的信号。为了使这个按钮点击产生一个动作，我们可以设置一个<emphasis>信号处理函数(signal handler)</emphasis>来捕捉这个“clicked”信号。

en: <application>gtkmm</application> uses the libsigc++ library to implement signals. Here is an example line of code that connects a Gtk::Button's "clicked" signal with a signal handler called "on_button_clicked":
zh_CN: <application>gtkmm</application> 使用 libsigc++ 来实现信号操作。下面这个例子演示怎样把 Gtk::Button 的“clicked” 信号连接到命名为“on_button_clicked”的信号处理函数上：

en: For more detailed information about signals, see the <link linkend="chapter-signals">appendix</link>.
zh_CN: 要得到更多关于信号的信息，请参考<link linkend="chapter-signals">附录</link>。

en: For information about implementing your own signals rather than just connecting to the existing <application>gtkmm</application> signals, see the <link linkend="chapter-custom-signals">appendix</link>.
zh_CN: 要想知道如何实现你自己的信号，而不仅仅是连接到现有的 <application>gtkmm</application> 信号，请参考 <link linkend="chapter-custom-signals">附录</link>。

en: You might be surprised to learn that <application>gtkmm</application> doesn't use <classname>std::string</classname> in its interfaces. Instead it uses <classname>Glib::ustring</classname>, which is so similar and unobtrusive that you could actually pretend that each <classname>Glib::ustring</classname> is a <classname>std::string</classname> and ignore the rest of this section. But read on if you want to use languages other than English in your application.
zh_CN: 当你得知<application>gtkmm</application>没有在它的接口上使用<classname>std::string</classname>而是使用了<classname>Glib::ustring</classname>的时候一定很惊讶。<classname>Glib::ustring</classname>与<classname>std::string</classname>非常相似，在某些场合，你甚至可以直接把它当做<classname>std::string</classname>来使用，并忽略本节后面的内容。但是如果你希望在你的应用程序中使用英语以外的语言的话，那么请继续读下去。

en: std::string uses 8 bits per character, but 8 bits aren't enough to encode languages such as Arabic, Chinese, and Japanese. Although the encodings for these languages have been specified by the <ulink url="http://www.unicode.org/">Unicode Consortium</ulink>, the C and C++ languages do not yet provide any standardised Unicode support for UTF-8 encoding. GTK and GNOME chose to implement Unicode using UTF-8, and that's what is wrapped by Glib::ustring. It provides almost exactly the same interface as std::string, along with automatic conversions to and from std::string.
zh_CN: std::string 对每个字符使用8位编码，但是这对于像阿拉伯语、汉语和日语这样的语言来说，8位是不够的。尽管<ulink url="http://www.unicode.org/">Unicode 协会</ulink>已经详细定义了这些语言的编码，但是C和C++尚未为UTF-8编码提供任何标准化的Unicode支持。GTK 和 GNOME 采用 UTF-8 编码来实现 Unicode，这就是 Glib::ustring 所包装的东西。它提供了和 std::string 几乎相同的接口，以及和 std::string 的自动类型转换的功能。

en: One of the benefits of UTF-8 is that you don't need to use it unless you want to, so you don't need to retrofit all of your code at once. <classname>std::string</classname> will still work for 7-bit ASCII strings. But when you try to localize your application for languages like Chinese, for instance, you will start to see strange errors, and possible crashes. Then all you need to do is start using <classname>Glib::ustring</classname> instead.
zh_CN: UTF-8 编码的优点之一是，如果不需要你可以不使用它，所以你不需要一次性的翻新你的代码。<classname>std::string</classname> 还可以继续使用7位的 ASCII 字符串。但是一旦你想本地化你的程序，比如说汉化，那你就会开始遇到各种奇怪的问题，可能还会崩溃。那时，你所需要做的就是开始使用 <classname>Glib::ustring</classname> 来取而代之。

en: Note that UTF-8 isn't compatible with 8-bit encodings like ISO-8859-1. For instance, German umlauts are not in the ASCII range and need more than 1 byte in the UTF-8 encoding. If your code contains 8-bit string literals, you have to convert them to UTF-8 (e.g. the Bavarian greeting "Grüß Gott" would be "Gr\xC3\xBC\xC3\x9F Gott").
zh_CN: 要注意的是 UTF-8 和其它一些8位的编码如 ISO-8859-1 并不兼容。比如，德语中的元音变音并不在 ASCII 码的编码范围内，在 UTF-8 编码中需要额外的一个字节来表示。如果你的代码中包含8位的字符串文字，你需要把它们转变成 UTF-8 编码 (比如，巴伐利亚的问候语“Grüß Gott”可能会显示成“Gr\xC3\xBC\xC3\x9F Gott”)。

en: You should avoid C-style pointer arithmetic, and functions such as strlen(). In UTF-8, each character might need anywhere from 1 to 6 bytes, so it's not possible to assume that the next byte is another character. <classname>Glib::ustring</classname> worries about the details of this for you so you can use methods such as Glib::ustring::substr() while still thinking in terms of characters instead of bytes.
zh_CN: 你应该尽量避免 C 风格的指针算法，以及像 strlen() 这样的函数。在 UTF-8 编码中，每个字符可能占1到6个字节，所以你并不能假定下一个字节一定是另一个字符。所有的这些细节 <classname>Glib::ustring</classname> 都已经帮你考虑到了，所以你可以从字符的层面上考虑使用 Glib::ustring::substr() 这样的函数，而不用再去考虑字节这样的细节了。

en: Unlike the Windows UCS-2 Unicode solution, this does not require any special compiler options to process string literals, and it does not result in Unicode executables and libraries which are incompatible with ASCII ones.
zh_CN: 不像 Windows 的 UCS-2 Unicode 解决方案，这并不需要编译器提供特别的选项来处理这样字符串，也不会导致为 Unicode 编译的可执行文件或库与含为 ASCII 的不兼容之类的问题。

en: <ulink url="http://developer.gnome.org/glibmm/unstable/classGlib_1_1ustring.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/glibmm/unstable/classGlib_1_1ustring.html">参考</ulink>

en: See the <link linkend="chapter-internationalization">Internationalization</link> section for information about providing the UTF-8 string literals.
zh_CN: 要得到更多关于 UTF-8 字符的信息，请参考<link linkend="chapter-internationalization">国际化</link>这一节。

en: Mixing C and C++ APIs
zh_CN: 混合使用 C 和 C++ API

en: You can use C APIs which do not yet have convenient C++ interfaces. It is generally not a problem to use C APIs from C++, and <application>gtkmm</application> helps by providing access to the underlying C object, and providing an easy way to create a C++ wrapper object from a C object, provided that the C API is also based on the <classname>GObject</classname> system.
zh_CN: 你可以使用那些尚未提供 C++ 接口的 C API。对于 C++ 而言这一般不是什么问题，<application>gtkmm</application> 可以提供帮助访问底层的 C 对象，并且也提供了一个简单的方式来从一个 C 对象创建一个 C++ 封装的对象，当然，这个 C API 是需要基于 <classname>GObject</classname> 系统的。

en: To use a <application>gtkmm</application> instance with a C function that requires a C <classname>GObject</classname> instance, use the C++ instance’s <function>gobj()</function> function to obtain a pointer to the underlying C instance. For example:
zh_CN: 要用 C 函数使用一个 <application>gtkmm</application> 实例需要一个 C <classname>GObject</classname> 实例，使用C++的<function>gobj()</function>接口函数可以得到一个底层 GObject 实例的指针。例如：

en: it's a widget or other class that inherits from <classname>Gtk::Object</classname>, and
zh_CN: 它是一个部件或者是继承自<classname>Gtk::Object</classname>的其他类，并且

en: the C instance has a floating reference when the wrapper is created, and
zh_CN: 当封装被创建的时候C示例拥有一个浮动引用，并且

en: <function>Gtk::manage()</function> has not been called on it (which includes if it was created with <function>Gtk::make_managed()</function>), or
zh_CN: 并未在其上调用<function>Gtk::manage()</function>(包括使用<function>Gtk::make_managed()</function>创建的) ，或者

en: <function>Gtk::manage()</function> was called on it, but it was never added to a parent.
zh_CN: 在其上调用了<function>Gtk::manage()</function>，但是从未将其加入到父项中。

en: To obtain a <application>gtkmm</application> instance from a C <classname>GObject</classname> instance, use one of the many overloaded <function>Glib::wrap()</function> functions. The C instance’s reference count is not incremented, unless you set the optional <parameter>take_copy</parameter> argument to <literal>true</literal>. For example: <_:programlisting-1/> The C++ wrapper shall be explicitly deleted if <_:itemizedlist-2/> <function>Glib::wrap()</function> binds the C and C++ instances to each other. Don't delete the C++ instance before you want the C instance to die.
zh_CN: 要从C的<classname>GObject</classname>实例获得一个<application>gtkmm</application>，请使用许多个<function>Glib::wrap()</function>函数的其中一个重载。除非你将可选的<parameter>take_copy</parameter>参数设置为<literal>true</literal>，否则C实例的引用计数将不会增加。例如：<_:programlisting-1/> 如果<_:itemizedlist-2/> <function>Glib::wrap()</function>将C和C++示例相互绑定，则应明确删除C++包装器。请不要在C示例死亡前删除C++实例。

en: In all other cases the C++ instance is automatically deleted when the last reference to the C instance is dropped. This includes all <function>Glib::wrap()</function> overloads that return a <classname>Glib::RefPtr</classname>.
zh_CN: 在所有其他情况下，当删除对C实例的最后一个引用时，C++实例将会自动被删除。这包括所有的<function>Glib::wrap()</function>所返回的<classname>Glib::RefPtr</classname>。

en: Hello World in <application>gtkmm</application>
zh_CN: 用 <application>gtkmm</application> 写 Hello World

en: We've now learned enough to look at a real example. In accordance with an ancient tradition of computer science, we now introduce Hello World, a la <application>gtkmm</application>:
zh_CN: 目前我们已经可以自己所学的知识来写一个真正的程序了。根据计算机科学的传统，我们现在以 <application>gtkmm</application> 的方式来介绍 Hello World 程序：

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/helloworld">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/helloworld">源代码</ulink>

en: Try to compile and run it before going on. You should see something like this:
zh_CN: 在继续讲解之前，可以尝试着编译并运行这个程序，你会看到这样的结果：

en: Pretty thrilling, eh? Let's examine the code. First, the <classname>HelloWorld</classname> class:
zh_CN: 真让人激动，不是吗？让我们回过头来看一下代码。首先看一下 <classname>HelloWorld</classname> 类：

en: This class implements the "Hello World" window. It's derived from <classname>Gtk::Window</classname>, and has a single <classname>Gtk::Button</classname> as a member. We've chosen to use the constructor to do all of the initialisation work for the window, including setting up the signals. Here it is, with the comments omitted:
zh_CN: 这个类实现了“Hello World”窗口。它由 <classname>Gtk::Window</classname> 派生，并且只有一个 <classname>Gtk::Button</classname> 成员。我们已经使用构造函数为该窗口完成了所有的初始化工作，包括挂接消息。在这，已经去掉注释的代码：

en: Notice that we've used an initialiser statement to give the <literal>m_button</literal> object the label "Hello World".
zh_CN: 注意，我们使用初始化列表的方式给 <literal>m_button</literal> 对象添加了一个“Hello World”的标签。

en: Next we call the Button's <methodname>set_margin()</methodname> method. This sets the amount of space around the button.
zh_CN: 接下来调用 Button 类的 <methodname>set_margin()</methodname> 方法。这将设置按钮周围空间的大小。

en: We then hook up a signal handler to <literal>m_button</literal>'s <literal>clicked</literal> signal. This prints our friendly greeting to <literal>stdout</literal>.
zh_CN: 然后，把 <literal>m_button</literal> 的 <literal>clicked</literal> 信号挂接到信号处理函数上。这会向 <literal>stdout</literal> (标准输出) 打印出友好的问候语。

en: Next, we use the Window's <methodname>set_child()</methodname> method to put <literal>m_button</literal> in the Window. The <methodname>set_child()</methodname> method places the Widget in the Window.
zh_CN: 接下来调用 Windows 类的 <methodname>set_child()</methodname> 方法将<literal>m_button</literal>放入窗口。<methodname>set_child()</methodname>方法会将部件放入窗口中。

en: Now let's look at our program's <function>main()</function> function. Here it is, without comments:
zh_CN: 现在让我们来看看程序中没有注释过的 <function>main()</function> 函数：

en: First we instantiate an object stored in a <classname>Glib::RefPtr</classname> smartpointer called <literal>app</literal>. This is of type <classname>Gtk::Application</classname>. Every <application>gtkmm</application> program must have one of these.
zh_CN: 我们首先实例化一个储存在名为<literal>app</literal>的<classname>RefPtr</classname>智能指针对象，它的类型为<classname>Gtk::Application</classname> 。每一个<application>gtkmm</application>程序都有这样的一个东西。

en: Next we call <methodname>make_window_and_run()</methodname> which creates an object of our <classname>HelloWorld</classname> class, shows that Window and starts the <application>gtkmm</application> <emphasis>event loop</emphasis>. During the event loop <application>gtkmm</application> idles, waiting for actions from the user, and responding appropriately. When the user closes the Window, <methodname>make_window_and_run()</methodname> will return, causing our <function>main()</function> function to return. The application will then finish.
zh_CN: 接着我们调用<methodname>make_window_and_run()</methodname>创建了我们的<classname>HelloWorld</classname>类对象，显示这个窗口并进入<application>gtkmm</application><emphasis>消息循环</emphasis>。在消息循环中，<application>gtkmm</application>是空闲的，它等待用户的操作并作出相应的反应。当用户关闭窗口时，<methodname>run()</methodname> 函数将返回，导致<function>main()</function>函数的最后一行将被执行。然后程序就结束了。

en: Like the simple example we showed earlier, this Hello World program does not use the command-line parameters.
zh_CN: 就像我们之前显示的简单示例一样，这个Hello World程序不使用命令行参数。

en: Changes in <application>gtkmm</application> 3
zh_CN: <application>gtkmm</application>3中的变更

en: <application>gtkmm</application>-3.0 is an old version of the <application>gtkmm</application> API that installs in parallel with the still older <application>gtkmm</application>-2.4 API and the new <application>gtkmm</application>-4.0 API. The last version of the <application>gtkmm</application>-2.4 API was <application>gtkmm</application> 2.24. <application>gtkmm</application> 3 has no major fundamental differences to <application>gtkmm</application> 2 but does make several small changes that were not possible while maintaining binary compatibility. If you never used the <application>gtkmm</application>-2.4 API then you can safely ignore this chapter.
zh_CN: <application>gtkmm</application>-3.0是<application>gtkmm</application> API的旧版本它依旧能与<application>gtkmm</application>-2.4和新的<application>gtkmm</application>-4.0 API并行安装。<application>gtkmm</application>-2.4 API的最新版本是<application>gtkmm</application> 2.24。<application>gtkmm</application>3于<application>gtkmm</application>2之间并没有重大的改变，但确实存在一些微小的变动，这些变动导致无法做到令他们保持二进制兼容。如果你从未用过<application>gtkmm</application>-2.4 API 则你可以放心的忽略本章。

en: <application>gtkmm</application> 3's library is called <literal>libgtkmm-3.0</literal> rather than <literal>libgtkmm-2.4</literal> and installs its headers in a similarly-versioned directory, so your pkg-config check should ask for <literal>gtkmm-3.0</literal> rather than <literal>gtkmm-2.4</literal>.
zh_CN: <application>gtkmm</application>3库调用<literal>libgtkmm-3.0</literal>而不是<literal>libgtkmm-2.4</literal> 并将其的头文件安装于类似的目录下，所以你的pkg-config应该检索<literal>gtkmm-3.0</literal>而不是<literal>gtkmm-2.4</literal>。

en: <application>gtkmm</application> 3 added some new classes:
zh_CN: <application>gtkmm</application>3添加了一些新的类：

en: <classname>Gtk::AppChooser</classname>, <classname>Gtk::AppChooserButton</classname>, <classname>Gtk::AppChooserDialog</classname> allow the user to select an installed application to open a particular type of content.
zh_CN: <classname>Gtk::AppChooser</classname>，<classname>Gtk::AppChooserButton</classname>,<classname>Gtk::AppChooserDialog</classname>允许用户选择已安装的应用程序用以打开特定类型的内容。

en: <classname>Gtk::Grid</classname> is a new container widget that will eventually replace <classname>Gtk::Box</classname> and <classname>Gtk::Table</classname>. It arranges its children according to properties of those children rather than its own layout details.
zh_CN: <classname>Gtk::Grid</classname>是一个新的容器部件他将在未来完全替换<classname>Gtk::Box</classname>和<classname>Gtk::Table</classname>。它根据它的子项的属性而不是自身的布局属性对子项进行排列。

en: <classname>Gtk::Switch</classname> displays On/Off states more explictly than <classname>Gtk::CheckButton</classname>. It may be useful, for instance, when allowing users to activate hardware.
zh_CN: 与<classname>Gtk::CheckButton</classname>相比<classname>Gtk::Switch</classname>更明确的显示开/关状态。例如，在允许用户激活硬件的时候，他可能很有用。

en: <application>gtkmm</application> 3 also made several small changes to the API, which you will probably encounter when porting code that used <application>gtkmm</application>-2.4. Here is a short list:
zh_CN: <application>gtkmm</application>3还对API进行了一些小的变更，在移植<application>gtkmm</application>-2.4的代码的时候你可能会遇到这些变更。这是一个简短的清单：

en: <classname>Gtk::CellLayout</classname>, used by <classname>Gtk::IconView</classname>, <classname>Gtk::TreeView::Column</classname> and <classname>Gtk::ComboBox</classname>, now has a <classname>Gtk::CellArea</classname> which can be used to specify more details of how the <classname>CellRenderer</classname>s are arranged and aligned.
zh_CN: <classname>Gtk::IconView</classname>， <classname>Gtk::TreeView::Column</classname>和<classname>Gtk::ComboBox</classname>使用<classname>Gtk::CellLayout</classname>，现在有<classname>Gtk::CellArea</classname>可以用于指示<classname>CellRenderer</classname>的排列与对齐方式的详情。

en: Gtk::ComboBox now derives from CellLayout, allowing easier layout and alignment of its <classname>Gtk::CellRenderer</classname>s.
zh_CN: Gtk::ComboBox现在从CellLayout派生，从而使更容易对<classname>Gtk::CellRenderer</classname>进行布局与对齐。

en: <classname>Gtk::Adjustment</classname> and <classname>IconSet</classname> and <classname>Gdk::Cursor</classname> are now used via <classname>Glib::RefPtr</classname>.
zh_CN: <classname>Gtk::Adjustment</classname>和<classname>Gtk::IconSet</classname>类和<classname>Gdk::Cursor</classname>类现在通过<classname>Glib::RefPtr</classname>使用。

en: <classname>Gtk::Box</classname>, <classname>Gtk::ButtonBox</classname>, <classname>Gtk::IconView</classname>, <classname>Gtk::Paned</classname>, <classname>Gtk::ProgressBar</classname>, <classname>Gtk::ScaleButton</classname>, <classname>Gtk::Scrollbar</classname> and <classname>Gtk::Separator</classname> now derive from <classname>Gtk::Orientable</classname>, allowing their orientation (vertical or horizontal) to be specified without requiring the use of a derived class such as <classname>Gtk::HBox</classname>.
zh_CN: <classname>Gtk::Box</classname>, <classname>Gtk::ButtonBox</classname>,<classname>Gtk::IconView</classname>, <classname>Gtk::Paned</classname>, <classname>Gtk::ProgressBar</classname>, <classname>Gtk::ScaleButton</classname>, <classname>Gtk::Scrollbar</classname>和<classname>Gtk::Separator</classname>现在从<classname>Gtk::Orientable</classname>派生，允许在不使用派生类(例如<classname>Gtk::HBox</classname>)的情况指定其方向(垂直或者水平)。

en: <classname>Gtk::IconView</classname>, <classname>Gtk::TextView</classname>, <classname>Gtk::TreeView</classname> and other widgets derive from Scrollable instead of having their own methods such as <methodname>get_vadjustment()</methodname> and instead of having their own set_scroll_adjustments signal.
zh_CN: <classname>Gtk::IconView</classname>, <classname>Gtk::TextView</classname>, <classname>Gtk::TreeView</classname>和其他部件派生自Scrollable而不使用他们自己的方法，例如<methodname>get_vadjustment()</methodname>拥有自己的set_scroll_adjustments信号。

en: <classname>Gtk::Style</classname> and <classname>Gtk::Rc</classname> were removed, replaced by <classname>Gtk::StyleContext</classname>, and <classname>Gtk::StyleProvider</classname>s, such as <classname>Gtk::CssProvider</classname>.
zh_CN: <classname>Gtk::Style</classname>和<classname>Gtk::Rc</classname>已被删除，由<classname>Gtk::StyleContext</classname>和<classname>Gtk::StyleProvider</classname>替换，例如<classname>Gtk::CssProvider</classname>。

en: Widget::on_expose_event() was replaced by Widget::on_draw(), which assumes that cairomm is used for drawing, via the provided <classname>Cairo::Context</classname> and does not require you to call <methodname>Cairo::Context::clip()</methodname>.
zh_CN: Widget::on_expose_event()被Widget::on_draw()取代，通过提供的<classname>Cairo::Context</classname>使用cairomm进行绘制，并且不需要你自己调用<methodname>Cairo::Context::clip()</methodname>。

en: <classname>Gdk::RGBA</classname> replaces <classname>Color</classname>, adding an alpha component for opacity. <classname>Colormap</classname> was removed, along with its awkward use to allocate colors.
zh_CN: <classname>Color</classname>被<classname>Gdk::RGBA</classname>替代，添加alpha分量以支持透明度。<classname>Colormap</classname>与其笨拙的颜色分配方式一并被删除。

en: <classname>Gdk::Pixmap</classname> and <classname>Gdk::Bitmap</classname> were removed in favour of <classname>Gdk::Pixbuf</classname>.
zh_CN: <classname>Gdk::Pixmap</classname>和<classname>Gdk::Bitmap</classname>现在被<classname>Gdk::Pixbuf</classname>所取代。

en: <classname>Gdk::Drawable</classname> was removed, with its methods moving into <classname>Gdk::Window</classname>.
zh_CN: <classname>Gdk::Drawable</classname>被删除，与其有关的方法被移动到了<classname>Gdk::Window</classname>。

en: We now use std::vector in several methods instead of the intermediate *Handle types to make the API clearer.
zh_CN: 我们现在使用std::vector而不是使用中间类型(*Handle)以使API更加的清晰。

en: All deprecated API was removed in <application>gtkmm</application> 3.0, though there have been new deprecations in later <application>gtkmm</application> 3.x versions.
zh_CN: 在<application>gtkmm</application> 3.0中我们删除了所有弃用的API，尽管在<application>gtkmm</application> 3.x版本中出现了新的被弃用的API。

en: As a first step to porting your source code to <application>gtkmm</application>-3.0 you should probably ensure that your application builds with the deprecated <application>gtkmm</application>-2.4 API disabled, by defining macro such as GTKMM_DISABLE_DEPRECATED. There are some autotools macros that can help with this by defining them optionally at build time. See the <ulink url="https://wiki.gnome.org/Projects/gtkmm/PortingToGtkmm3">gtkmm 3 porting wiki page</ulink> for more details.
zh_CN: 将源代码迁移到<application>gtkmm</application>-3.0的第一步，你应该通过定义GTKMM_DISABLE_DEPRECATED宏以检查你是否使用了在<application>gtkmm</application>-2.4中被弃用的API,然后删除他们。有一些autotools宏可以在编译时帮助你通过构建。访问<ulink url="https://wiki.gnome.org/Projects/gtkmm/PortingToGtkmm3">gtkmm3移植Wiki</ulink>了解更多详情。

en: Changes in <application>gtkmm</application>-4.0 and <application>glibmm-2.68</application>
zh_CN: <application>gtkmm</application>-4.0和<application>glibmm-2.68</application>中的变更。

en: <application>gtkmm</application>-4.0 is a new version of the <application>gtkmm</application> API that installs in parallel with the older <application>gtkmm</application>-2.4 and <application>gtkmm</application>-3.0 APIs. The last version of the <application>gtkmm</application>-3.0 API is <application>gtkmm</application> 3.24. <application>gtkmm</application> 4 has no major fundamental differences to <application>gtkmm</application> 3 but does make several changes (both small and large ones) that were not possible while maintaining binary compatibility. If you never used the <application>gtkmm</application>-3.0 API then you can safely ignore this chapter.
zh_CN: <application>gtkmm</application>-4.0是<application>gtkmm</application> API的新版本。它可以与较早发行的<application>gtkmm</application>-2.4和<application>gtkmm</application>-3.0并行安装。<application>gtkmm</application>-3.0 API的最新版本是<application>gtkmm</application> 3.24。<application>gtkmm</application> 4与<application>gtkmm</application> 3没有根本性的区别，虽然有些变更但是保持了二进制兼容。如果你从未使用过<application>gtkmm</application>-3.0 API则你可以放心的忽略本章。

en: <application>gtkmm</application> 4's library is called <literal>libgtkmm-4.0</literal> rather than <literal>libgtkmm-3.0</literal> and installs its headers in a similarly-versioned directory, so your <application>pkg-config</application> check should ask for <literal>gtkmm-4.0</literal> rather than <literal>gtkmm-3.0</literal>.
zh_CN: <application>gtkmm</application> 4库调用<literal>libgtkmm-4.0</literal>而不是<literal>libgtkmm-3.0</literal>，并将其的头文件安装于类似的目录下，所以你的<application>pkg-config</application>应该检索<literal>gtkmm-4.0</literal>而不是<literal>gtkmm-3.0</literal>。

en: <application>gtkmm</application>-4.0 is used in combination with <application>glibmm-2.68</application>, which sets the global locale for your program. The older <application>glibmm-2.4</application> does not do that, and <application>gtkmm</application>-3.0 does it only to some extent. What this means is briefly that if your <application>gtkmm</application>-3.0 program contains a call to <function>std::locale::global(std::locale(""))</function>, you can probably remove it. If you don't want <application>glibmm</application> or <application>gtkmm</application> to set the global locale for you, you should add a call to <function>Glib::set_init_to_users_preferred_locale(false)</function> before any call to <function>Glib::init()</function> or <methodname>Gtk::Application::create()</methodname>.
zh_CN: <application>gtkmm</application>-4.0与<application>glibmm-2.68</application>结合使用，将设置程序的全局语言环境。较旧的<application>glibmm-2.4</application>不会这样做，而<application>gtkmm</application>-3.0只在一定程度上做到了。简而言之，如果你的<application>gtkmm</application>-3.0应用包含了对<function>std::locale::global(std::locale(""))</function>的调用，则你大概率可以直接将其删除。如果你不希望<application>glibmm</application>或者<application>gtkmm</application>为你设置程序的全局语言环境，则应该在调用任何<function>Glib::init()</function>函数或<methodname>Gtk::Application::create()</methodname>方法之前添加对<function>Glib::set_init_to_users_preferred_locale(false)</function>的调用。

en: <ulink url="http://developer.gnome.org/glibmm/unstable/namespaceGlib.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/glibmm/unstable/namespaceGlib.html">参考</ulink>

en: There are lots and lots of differences between <application>gtkmm</application>-3.0 and <application>gtkmm</application>-4.0. The following lists are not complete.
zh_CN: <application>gtkmm</application>-3.0和<application>gtkmm</application>-4.0之间有很多不同之处。以下是不完整的列表。

en: Some new classes were added in <application>gtkmm</application> 4 and <application>glibmm</application> 2.68:
zh_CN: 在<application>gtkmm</application> 4和<application>glibmm</application> 2.68中添加了一些新的类：

en: <classname>Glib::ExtraClassInit</classname> and <classname>Gtk::Snapshot</classname>: These classes are needed only for writing custom widgets. See the <link linkend="sec-custom-widgets">Custom Widgets</link> section.
zh_CN: <classname>Glib::ExtraClassInit</classname>和<classname>Gtk::Snapshot</classname>：这些类只用于编写自定义的窗口小部件。参见<link linkend="sec-custom-widgets">自定义部件</link>小节。

en: <classname>Gtk::EventControllerKey</classname>, <classname>Gtk::EventControllerMotion</classname>, <classname>Gtk::EventControllerScroll</classname> and <classname>Gtk::GestureStylus</classname>
zh_CN: <classname>Gtk::EventControllerKey</classname>, <classname>Gtk::EventControllerMotion</classname>, <classname>Gtk::EventControllerScroll</classname>和<classname>Gtk::GestureStylus</classname>

en: <classname>Gdk::Paintable</classname>, <classname>Gdk::Texture</classname>, <classname>Gtk::Picture</classname> and <classname>Gtk::WidgetPaintable</classname>
zh_CN: <classname>Gdk::Paintable</classname>, <classname>Gdk::Texture</classname>, <classname>Gtk::Picture</classname>和<classname>Gtk::WidgetPaintable</classname>

en: <classname>Gdk::Window</classname> has been renamed to <classname>Gdk::Surface</classname>. (<classname>Gtk::Window</classname> keeps its name.)
zh_CN: <classname>Gdk::Window</classname>被重命名为<classname>Gdk::Surface</classname>(<classname>Gtk::Window</classname>名称保持不变)。

en: <classname>Gdk::DrawContext</classname> and <classname>Gdk::CairoContext</classname> are new. <classname>Gdk::DrawingContext</classname> has been removed.
zh_CN: 新添加了<classname>Gdk::DrawContext</classname>和<classname>Gdk::CairoContext</classname>。<classname>Gdk::DrawingContext</classname>已被删除。

en: <classname>Gtk::Clipboard</classname> has been replaced by the new <classname>Gdk::Clipboard</classname>.
zh_CN: <classname>Gtk::Clipboard</classname>被新的<classname>Gdk::Clipboard</classname>替换。

en: <classname>Gdk::DragContext</classname> has been split into <classname>Gdk::Drag</classname> and <classname>Gdk::Drop</classname>.
zh_CN: <classname>Gdk::DragContext</classname>现在被拆分为<classname>Gdk::Drag</classname>和<classname>Gdk::Drop</classname>。

en: There have also been several changes to the API, which you will probably encounter when porting code that used <application>gtkmm</application>-3.0 and <application>glibmm</application>-2.4. Here is a short list:
zh_CN: API也进行了一些更改，在移植<application>gtkmm</application>-3.0和<application>glibmm</application>-2.4代码时你可能会遇到这些更改。以下是一个简短的变更列表：

en: A C++17 compiler is required.
zh_CN: 需要支持C++17的编译器

en: <classname>Gtk::Button</classname>, <classname>Gtk::ToolButton</classname>, <classname>Gtk::MenuItem</classname> and <classname>Gtk::Switch</classname> implement the <classname>Gtk::Actionable</classname> interface instead of the removed <classname>Gtk::Activatable</classname> interface.
zh_CN: <classname>Gtk::Button</classname>，<classname>Gtk::ToolButton</classname>，<classname>Gtk::MenuItem</classname>和<classname>Gtk::Switch</classname> 实现了<classname>Gtk::Actionable</classname>接口而不是已被删除的<classname>Gtk::Activatable</classname>接口。

en: <classname>Gtk::FontButton</classname> implements the <classname>Gtk::FontChooser</classname> interface.
zh_CN: <classname>Gtk::FontButton</classname>实现了<classname>Gtk::FontChooser</classname>接口。

en: <classname>Gtk::Widget</classname>: The <methodname>get_preferred_*_vfunc()</methodname>s have been replaced by <methodname>measure_vfunc()</methodname>. This change only affects custom widgets.
zh_CN: <classname>Gtk::Widget</classname>：<methodname>get_preferred_*_vfunc()</methodname>方法已被<methodname>measure_vfunc()</methodname>方法替代。此变更只影响自定义部件。

en: <classname>sigc::slot</classname>s use the <classname>sigc::slot&lt;R(Args...)&gt;</classname> syntax. Example: <classname>sigc::slot&lt;void(int, int)&gt;</classname> instead of <classname>sigc::slot&lt;void, int, int&gt;</classname>.
zh_CN: <classname>sigc::slot</classname>使用<classname>sigc::slot&lt;R(Args...)&gt;</classname>语法。 例如： <classname>sigc::slot&lt;void(int, int)&gt;</classname>而不是使用<classname>sigc::slot&lt;void, int, int&gt;</classname>。

en: <classname>Gtk::DrawingArea</classname> uses a draw function instead of the draw signal.
zh_CN: <classname>Gtk::DrawingArea</classname>使用绘制函数替代绘制信号。

en: <classname>Glib::ArrayHandle</classname>, <classname>Glib::StringArrayHandle</classname>, <classname>Glib::ListHandle</classname> and <classname>Glib::SListHandle</classname> have been removed. They were used in <application>glibmm</application>-2.4, but not used in <application>gtkmm</application>-3.0. If you've ever used these classes, replace them with a standard C++ container, such as <classname>std::vector</classname>.
zh_CN: <classname>Glib::ArrayHandle</classname>, <classname>Glib::StringArrayHandle</classname>, <classname>Glib::ListHandle</classname>和<classname>Glib::SListHandle</classname>已被删除。他们曾在<application>glibmm</application>-2.4中被使用，而<application>gtkmm</application>-3.0并未使用他们。如果你曾经使用过他们，则将他们替换为标准C++容器，例如<classname>std::vector</classname>。

en: <classname>Gtk::Container</classname> has been removed.
zh_CN: <classname>Gtk::Container</classname>已被删除。

en: <methodname>Gtk::Widget::show_all()</methodname> has been removed. The default value of <methodname>Gtk::Widget::property_visible()</methodname>has been changed from <literal>false</literal> to <literal>true</literal>.
zh_CN: <methodname>Gtk::Widget::show_all()</methodname>已被删除。<methodname>Gtk::Widget::property_visible()</methodname>的默认值从<literal>false</literal>改为<literal>true</literal>。

en: All event signals have been removed from <classname>Gtk::Widget</classname>. In most cases you can use one of the subclasses of <classname>Gtk::EventController</classname> as a replacement. For instance, use <classname>Gtk::GestureMultiPress</classname> instead of <methodname>signal_button_press_event()</methodname> and <methodname>signal_button_release_event()</methodname>, and <classname>Gtk::EventControllerKey</classname> instead of <methodname>signal_key_press_event()</methodname> and <methodname>signal_key_release_event()</methodname>.
zh_CN: <classname>Gtk::Widget</classname>上的所有事件信号均已被删除。 大多数时候你可以使用<classname>Gtk::EventController</classname>的子类之一进行替换。例如, 使用<classname>Gtk::GestureMultiPress</classname>替代<methodname>signal_button_press_event()</methodname>以及<methodname>signal_button_release_event()</methodname>，使用<classname>Gtk::EventControllerKey</classname>替代<methodname>signal_key_press_event()</methodname>和<methodname>signal_key_release_event()</methodname>。

en: <classname>Glib::RefPtr</classname> is an alias for <classname>std::shared_ptr</classname>. If you make your own <classname>Glib::ObjectBase</classname>-derived classes with <methodname>create()</methodname> methods that return a <classname>Glib::RefPtr</classname>, you must use <methodname>Glib::make_refptr_for_instance()</methodname> in your <methodname>create()</methodname> methods.
zh_CN: <classname>Glib::RefPtr</classname>是<classname>std::shared_ptr</classname>的别名。如果你使用返回<classname>Glib::RefPtr</classname>的<methodname>create()</methodname>方法用以创建派生自<classname>Glib::ObjectBase</classname>的类，则你必须在你的<methodname>create()</methodname>方法中调用<methodname>Glib::make_refptr_for_instance()</methodname>。

en: <methodname>Gtk::Box::pack_start()</methodname> and <methodname>Gtk::Box::pack_end()</methodname> have been removed. Use the new <classname>Gtk::Box</classname> methods <methodname>append()</methodname>, <methodname>prepend()</methodname>, <methodname>insert_child_after()</methodname> and <methodname>insert_child_at_start()</methodname>.
zh_CN: <methodname>Gtk::Box::pack_start()</methodname>和<methodname>Gtk::Box::pack_end()</methodname>已被删除。现在<classname>Gtk::Box</classname>使用新的<methodname>append()</methodname>，<methodname>prepend()</methodname>，<methodname>insert_child_after()</methodname>和<methodname>insert_child_at_start()</methodname>方法。

en: <classname>Gtk::ButtonBox</classname> has been removed.
zh_CN: <classname>Gtk::ButtonBox</classname>已被删除

en: <classname>Gtk::RadioButton</classname> and <classname>Gtk::RadioButtonGroup</classname> have been removed. Use <classname>Gtk::CheckButton</classname> or <classname>Gtk::ToggleButton</classname> with <methodname>set_group()</methodname>.
zh_CN: <classname>Gtk::RadioButton</classname>和<classname>Gtk::RadioButtonGroup</classname>已被删除。改为使用<classname>Gtk::CheckButton</classname>或者是<classname>Gtk::ToggleButton</classname>的<methodname>set_group()</methodname>。

en: All deprecated API was removed in <application>gtkmm</application> 4.0 and <application>glibmm</application> 2.68, though there will be new deprecations in future versions.
zh_CN: <application>gtkmm</application>和<application>glibmm</application> 2.68移除了所有之前标记为弃用的API，未来还会有新的API被标记为弃用。

en: As a first step to porting your source code to <application>gtkmm</application>-4.0 you should probably ensure that your application builds with the deprecated <application>gtkmm</application>-3.0 and <application>glibmm-2.4</application> API disabled, by defining the macros GTKMM_DISABLE_DEPRECATED, GDKMM_DISABLE_DEPRECATED, GLIBMM_DISABLE_DEPRECATED and GIOMM_DISABLE_DEPRECATED. There are some autotools macros that can help with this by defining them optionally at build time. See the <ulink url="https://wiki.gnome.org/Projects/gtkmm/PortingToGtkmm3">Porting from gtkmm-2.4 to gtkmm-3.0</ulink> wiki page for more details.
zh_CN: 将源代码移植到<application>gtkmm</application>-4.0的第一步，通过定义GTKMM_DISABLE_DEPRECATED，GDKMM_DISABLE_DEPRECATED，GLIBMM_DISABLE_DEPRECATED和GIOMM_DISABLE_DEPRECATED宏禁用所有在<application>gtkmm</application>-3.0和<application>glibmm-2.4</application>中弃用的API，有一些autotools宏可以帮助你在编译时定义他们。更多有关详情请参见<ulink url="https://wiki.gnome.org/Projects/gtkmm/PortingToGtkmm3">从gtkmm-2.4迁移到gtkmm-3.0</ulink>Wiki页面。

en: See also <ulink url="https://developer.gnome.org/gtk4/unstable/gtk-migrating-3-to-4.html"> Migrating from GTK 3.x to GTK 4</ulink>.
zh_CN: 另请参见<ulink url="https://developer.gnome.org/gtk4/unstable/gtk-migrating-3-to-4.html">从GTK3.X迁移到GTK 4</ulink>。

en: Buttons
zh_CN: 按钮(Buttons)

en: <application>gtkmm</application> provides four basic types of buttons:
zh_CN: <application>gtkmm</application> 提供以下四种基本按钮控件：

en: Push buttons
zh_CN: 按钮类

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Button.html"><classname>Gtk::Button</classname></ulink>. Standard buttons, usually marked with a label or picture. Pushing one triggers an action. See the <link linkend="sec-pushbuttons">Button</link> section.
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Button.html"><classname>Gtk::Button</classname></ulink>。这是标准按钮，通常标有文字标签或者图片。按一下就会触发一个动作。参看 <link linkend="sec-pushbuttons">Button</link> 小节。

en: Toggle buttons
zh_CN: 开关按钮(ToggleButton)

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ToggleButton.html"><classname>Gtk::ToggleButton</classname></ulink>. Unlike a normal Button, which springs back up, a ToggleButton stays down until you press it again. It might be useful as an on/off switch. See the <link linkend="sec-toggle-buttons">ToggleButton</link> section.
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ToggleButton.html"><classname>Gtk::ToggleButton</classname></ulink>。和一般按下后会自动弹起的按钮不一样，ToggleButton 需要你再按一次才会弹起。它作为一个开关可能比较有用。参看 <link linkend="sec-toggle-buttons">ToggleButton</link> 小节。

en: Check buttons
zh_CN: 复选按钮(CheckButtons)

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1CheckButton.html"><classname>Gtk::CheckButton</classname></ulink>. These act like ToggleButtons, but show their state in small squares, with their label at the side. They should be used in most situations which require an on/off setting. See the <link linkend="sec-checkbuttons">CheckButton</link> section.
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1CheckButton.html"><classname>Gtk::CheckButton</classname></ulink>。它们用起来和 ToggleButtons 很像，只不过它们用一个小方块来显示自己的状态，而且旁边还有一个文字标签。在大多数需要布尔值设置的情况都可以使用它。参看 <link linkend="sec-checkbuttons">CheckButton</link> 小节。

en: Radio buttons
zh_CN: 单选按钮(RadioButton)

en: Named after the station selectors on old car radios, these buttons are used in groups for options which are mutually exclusive. Pressing one causes all the others in its group to turn off. They are similar to ToggleButtons or CheckButtons (a small widget with a label at the side), but usually look different. There is no separate radio button class. Check buttons and toggle buttons can act as radio buttons. See the <link linkend="sec-radio-buttons">Radio Button</link> section.
zh_CN: 它是根据老式汽车内的收音机的选台器来命名的，选台器是一组选择按钮并且它们是互斥的。按下其中任何一个都会使这一组中的其它按钮都弹起。它们的布局和 CheckButton (一个旁边有标签的小部件)很相似，但是通常看起来不太一样。没有单独的单选按钮类。复选按钮和开关按钮可以充当单选按钮。参见<link linkend="sec-radio-buttons">RadioButton</link> 小节。

en: Note that, due to GTK's theming system, the appearance of these widgets will vary. In the case of check buttons and radio buttons, they may vary considerably.
zh_CN: 请注意，由于GTK的主题不同，这些控件外观可能会不同。特别是复选按钮和单选按钮可能会很不一样。

en: Button
zh_CN: 按钮(Button)

en: There are two ways to create a Button. You can specify a label string in the <classname>Gtk::Button</classname> constructor, or set it later with <methodname>set_label()</methodname>.
zh_CN: 可以通过两种方式来创建按钮，你可以在 <classname>Gtk::Button</classname> 构造函数中指定标签字符串，或者以后调用 <methodname>set_label()</methodname> 来指定标签。

en: To define an accelerator key for keyboard navigation, place an underscore before one of the label's characters and specify <literal>true</literal> for the optional <literal>mnemonic</literal> parameter. For instance:
zh_CN: 如果你想为按钮定义一个快捷键，那么可以在标签字符串中的某个字符前面加上一个下划线，并且指定可选的参数助记符(mnemonic)为 true。例如：

en: <classname>Gtk::Button</classname> is also a container so you could put any other widget, such as a <classname>Gtk::Image</classname> into it.
zh_CN: <classname>Gtk::Button</classname> 同时也是一个容器，因此你可以在其中放任何其它的部件，比如放一个 <classname>Gtk::Image</classname> 在里面。

en: The <classname>Gtk::Button</classname> widget has the <literal>clicked</literal> signal which is emitted when the button is pressed and released.
zh_CN: <classname>Gtk::Button</classname>部件具有<literal>clicked</literal>信号，当按下或释放按钮时将会发出该信号。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Button.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Button.html">参考</ulink>

en: Example
zh_CN: 示例

en: This example creates a button with a picture and a label.
zh_CN: 这个示例创建了一个有图片和文字标签的按钮。

en: buttons example
zh_CN: 按钮示例

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buttons/button">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buttons/button">源代码</ulink>

en: ToggleButton
zh_CN: 开关按钮(ToggleButton)

en: <classname>ToggleButton</classname>s are like normal <classname>Button</classname>s, but when clicked they remain activated, or pressed, until clicked again.
zh_CN: <classname>ToggleButton</classname> 和普通的 <classname>Button</classname> 相似，但是它们在点击后会保持激活(或称为按下的)状态，直到再次点击它为止。

en: To retrieve the state of the <classname>ToggleButton</classname>, you can use the <methodname>get_active()</methodname> method. This returns <literal>true</literal> if the button is "down". You can also set the toggle button's state, with <methodname>set_active()</methodname>. Note that, if you do this, and the state actually changes, it causes the "clicked" signal to be emitted. This is usually what you want.
zh_CN: 要得到 <classname>ToggleButton</classname> 的状态，你可以使用 <methodname>get_active()</methodname> 方法。如果按钮被按下了，就返回 true。当然，你也可以通过 <methodname>set_active()</methodname> 来设置开关按钮的状态。请注意，如果你这样做了，并且它的状态的确改变了，那么这将会引发“clicked”信号。当然，一般来说，这就是你希望看到的结果。

en: You can use the <methodname>toggled()</methodname> method to toggle the button, rather than forcing it to be up or down: This switches the button's state, and causes the <literal>toggled</literal> signal to be emitted.
zh_CN: 你可以使用 <methodname>toggled()</methodname> 方法来改变按钮的状态，而不要强行的是设置它是开还是关：这个方法将会改变按钮的状态，并会引发 <literal>toggled</literal> 信号。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ToggleButton.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ToggleButton.html">参考</ulink>

en: CheckButton
zh_CN: 多选按钮(CheckButton)

en: <classname>Gtk::CheckButton</classname> inherits directly from <classname>Gtk::Widget</classname>. It is similar to <classname>Gtk::ToggleButton</classname>. The only real difference between the two is <classname>Gtk::CheckButton</classname>'s appearance. You can check and set a check button using the same member methods as for <classname>Gtk::ToggleButton</classname>.
zh_CN: <classname>Gtk::CheckButton</classname> 继承自 <classname>Gtk::Widget</classname>。它与<classname>Gtk::ToggleButton</classname>类似，二者只有外观不同。因此你可以像<classname>Gtk::ToggleButton</classname>一样使用同样的方法来检查、设置和转换多选按钮的状态。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1CheckButton.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1CheckButton.html">参考</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buttons/checkbutton">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buttons/checkbutton">源代码</ulink>

en: Radio Button
zh_CN: 单选按钮(RadioButton)

en: There is no separate class for radio buttons. Check buttons and toggle buttons act as radio buttons when they form a group. Only one button in a group can be selected at any one time.
zh_CN: 单选按钮没有单独的类。当复选按钮和开关按钮在一个组中的时候它们充当单选按钮。任何时候只能选择一个组中的一个按钮。

en: Groups
zh_CN: 组

en: You create the buttons, and set up their group afterwards. In the following example, we put 3 radio buttons in a group:
zh_CN: 你创建了三个按钮，然后为他们设置了组。在下面的例子中，我们将三个单选按钮放入一个组中。

en: We told <application>gtkmm</application> to put all three <classname>CheckButton</classname>s in the same group by using <methodname>set_group()</methodname> to tell the other <classname>CheckButton</classname>s to share group with the first <classname>CheckButton</classname>.
zh_CN: 我们告诉<application>gtkmm</application>把三个<classname>CheckButton</classname>都放到一个组内，通过<methodname>get_group()</methodname>来得到这个组，然后使用<methodname>set_group()</methodname>告诉其它的<classname>CheckButton</classname>与第一个<classname>CheckButton</classname>共享这个组。

en: Methods
zh_CN: 方法

en: <classname>CheckButton</classname>s and <classname>ToggleButton</classname>s are "off" when created; this means that when you first make a group of them, they will all be off. Don't forget to turn one of them on using <methodname>set_active()</methodname>.
zh_CN: 当<classname>CheckButton</classname>和<classname>ToggleButton</classname>创建后默认是未选中的，也就是说当你第一次创建一组单选按钮的时候，它们都会是未选中的。所以别忘了使用<methodname>set_active()</methodname>来选中一个。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1RadioButton.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1RadioButton.html">参考</ulink>

en: The following example demonstrates the use of grouped <classname>CheckButton</classname>s:
zh_CN: 接下来的例子中演示了对<classname>CheckButton</classname>进行分组的用法：

en: RadioButton
zh_CN: 单选按钮(RadioButton)

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buttons/radiobutton">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buttons/radiobutton">源代码</ulink>

en: Range Widgets
zh_CN: 范围(Range)部件

en: <classname>Gtk::Scale</classname> and <classname>Gtk::Scrollbar</classname> both inherit from <classname>Gtk::Range</classname> and share much functionality. They contain a "trough" and a "slider" (sometimes called a "thumbwheel" in other GUI environments). Dragging the slider with the pointer moves it within the trough, while clicking in the trough advances the slider towards the location of the click, either completely, or by a designated amount, depending on which mouse button is used. This should be familiar scrollbar behaviour.
zh_CN: <classname>Gtk::Scale</classname> 和 <classname>Gtk::Scrollbar</classname> 都是继承自 <classname>Gtk::Range</classname>，并且共享了很多功能。他们都有一个“滑轨(trough)”和“滑块(slider)”(在其它 GUI 环境中可能被称为“指轮(thumbwheel)”)。在滑轨内可以用鼠标拖动滑块，而在滑轨上点击的话则会让滑块向点击的位置移动，可能是移动到终点，也可能是移动一段距离，这取决于你用的是鼠标的哪个按键。这和滚动条的行为很类似。

en: As will be explained in the <link linkend="chapter-adjustment">Adjustments</link> section, all Range widgets are associated with an <classname>Adjustment</classname> object. To change the lower, upper, and current values used by the widget you need to use the methods of its <classname>Adjustment</classname>, which you can get with the <methodname>get_adjustment()</methodname> method. The <classname>Range</classname> widgets' default constructors create an <classname>Adjustment</classname> automatically, or you can specify an existing <classname>Adjustment</classname>, maybe to share it with another widget. See the <link linkend="chapter-adjustment">Adjustments</link> section for further details.
zh_CN: 就象将在后面的<link linkend="chapter-adjustment">调整</link>小节要谈到的那样，所有的 Range 部件都有一个关联的 <classname>Adjustment</classname> 对象。如果你想修改部件的最小值、最大值以及当前值，你需要调用该部件关联的 <classname>Adjustment</classname> 对象的方法，该对象可以通过调用 <methodname>get_adjustment()</methodname> 方法来得到。<classname>Range</classname> 部件默认构造函数会自动的创建一个 <classname>Adjustment</classname>，当然，你也可以指定一个现有的 <classname>Adjustment</classname>，而且还可以和其它部件共享。请参看 <link linkend="chapter-adjustment">调整</link>部分以得到更详细的信息。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Range.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Range.html">参考</ulink>

en: Scrollbar Widgets
zh_CN: 滚动条部件 (Scrollbar)

en: These are standard scrollbars. They should be used only to scroll another widget, such as a <classname>Gtk::Entry</classname> or a <classname>Gtk::Viewport</classname>, though it's usually easier to use the <classname>Gtk::ScrolledWindow</classname> widget in most cases.
zh_CN: 这些是标准的滚动条。它们应该只被用于滚动其它部件，比如 <classname>Gtk::Entry</classname> 或 <classname>Gtk::Viewport</classname>，当然，通常使用 <classname>Gtk::ScrolledWindow</classname> 会更容易一些。

en: The orientation of a <classname>Gtk::Scrollbar</classname> can be either horizontal or vertical.
zh_CN: <classname>Gtk::Scrollbar</classname>的方向可以是水平的也可以是垂直的。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Scrollbar.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Scrollbar.html">参考</ulink>

en: Scale Widgets
zh_CN: 比例部件 (Scale)

en: <classname>Gtk::Scale</classname> widgets (or "sliders") allow the user to visually select and manipulate a value within a specific range. You might use one, for instance, to adjust the magnification level on a zoomed preview of a picture, or to control the brightness of a colour, or to specify the number of minutes of inactivity before a screensaver takes over the screen.
zh_CN: <classname>Gtk::Scale</classname> 部件 (或者说“滑块”) 可以让用户在指定范围内直观地调节它的值。例如，你可以用它来调节一副预览图片的放大率、或者控制颜色的亮度，或者指定多少分钟后执行屏幕保护。

en: As with <classname>Scrollbar</classname>s, the orientation can be either horizontal or vertical. The default constructor creates an <classname>Adjustment</classname> with all of its values set to <literal>0.0</literal>. This isn't useful so you will need to set some <classname>Adjustment</classname> details to get meaningful behaviour.
zh_CN: 像 <classname>Scrollbar</classname> 一样，也分别有水平和垂直两种方向。默认构造函数会创建一个 <classname>Adjustment</classname>，并且所有值都设为 <literal>0.0</literal>。当然，这显然没有意义，所以你需要设置一些 <classname>Adjustment</classname> 的细节来让它获得有意义的行为。

en: Useful methods
zh_CN: 一些有用的方法

en: <classname>Scale</classname> widgets can display their current value as a number next to the trough. By default they show the value, but you can change this with the <methodname>set_draw_value()</methodname> method.
zh_CN: <classname>Scale</classname> 可以在滑轨旁显示它们的当前值。默认情况下是显示这个数值的，但是你可以通过调用 <methodname>set_draw_value()</methodname> 方法来设置是否显示该值。

en: The value displayed by a scale widget is rounded to one decimal point by default, as is the <literal>value</literal> field in its <classname>Gtk::Adjustment</classname>. You can change this with the <methodname>set_digits()</methodname> method.
zh_CN: 默认情况下，Scale 部件会显示 <classname>Gtk::Adjustment</classname> 的 <literal>value</literal> 的数值，并且会被四舍五入到一位小数。你可以通过 <methodname>set_digits()</methodname> 方法来改变显示的小数位数。

en: Also, the value can be drawn in different positions relative to the trough, specified by the <methodname>set_value_pos()</methodname> method.
zh_CN: 另外，通过使用 <methodname>set_value_pos()</methodname>，可以使值显示在相对于滑块不同的位置。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Scale.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Scale.html">参考</ulink>

en: This example displays a window with three range widgets all connected to the same adjustment, along with a couple of controls for adjusting some of the parameters mentioned above and in the section on adjustments, so you can see how they affect the way these widgets work for the user.
zh_CN: 这个示例显示了一个窗口，其中有三个关联到同一个调整对象，还有几个控制部件用来调整前文讨论过的一些参数，这样你可以很清楚地看到那些参数是如何影响这些部件的行为方式的。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/range_widgets">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/range_widgets">源代码</ulink>

en: Miscellaneous Widgets
zh_CN: 杂项部件

en: Label
zh_CN: 标签(Label)

en: Labels are the main method of placing non-editable text in windows, for instance to place a title next to an <classname>Entry</classname> widget. You can specify the text in the constructor, or later with the <methodname>set_text()</methodname> or <methodname>set_markup()</methodname> methods.
zh_CN: 标签是用于在窗口中放置不可编辑文本的主要方法，例如将标题放于<classname>Entry</classname>部件旁。你可以直接在构造函数中指定文本，也可以于稍后调用<methodname>set_text()</methodname>或<methodname>set_markup()</methodname>方法设置想要显示的文本。

en: The width of the label will be adjusted automatically. You can produce multi-line labels by putting line breaks ("\n") in the label string.
zh_CN: 标签会自动调整宽度。你也可以通过在标签锁显示的字符串中放置换行符("\n")来生成多行标签。

en: The label text can be justified using the <methodname>set_justify()</methodname> method. The widget is also capable of word-wrapping, which can be activated with <methodname>set_line_wrap()</methodname>.
zh_CN: 标签文本可以使用<methodname>set_justify()</methodname>方法进行对齐。这个部件还具有自动换行功能，你可以使用<methodname>set_line_wrap()</methodname>激活它。

en: Gtk::Label supports some simple formatting, for instance allowing you to make some text bold, colored, or larger. You can do this by providing a string to <methodname>set_markup()</methodname>, using the <ulink url="http://developer.gnome.org/pango/unstable/PangoMarkupFormat.html">Pango Markup syntax</ulink>. For instance, <code> &lt;b&gt;bold text&lt;/b&gt; and &lt;s&gt;strikethrough text&lt;/s&gt; </code> .
zh_CN: Gtk::Label支持简单的格式，例如，允许你将某些文本设置成粗体，彩色，或者更大的字号。你也可以使用<ulink url="http://developer.gnome.org/pango/unstable/PangoMarkupFormat.html">Pango 标记语法</ulink>。例如， <code> &lt;b&gt;bold text&lt;/b&gt; and &lt;s&gt;strikethrough text&lt;/s&gt; </code> 。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Label.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Label.html">参考</ulink>

en: Below is a short example to illustrate these functions. This example makes use of the Frame widget to better demonstrate the label styles. (The Frame widget is explained in the <link linkend="sec-frame">Frame</link> section.) It is possible that the first character in <literal>m_Label_Normal</literal> is shown underlined only when you press the <keycap>Alt</keycap> key.
zh_CN: 下面是一个用于说明这些功能的简短示例。这个样例使用框架(Frame)部件以更好的演示标签样式。(框架部件的教程: <link linkend="sec-frame">框架(Frame)部件</link>)仅当你按<keycap>Alt</keycap>键时，<literal>m_Label_Normal</literal>的第一个字符才显示为下划线的样式。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/label">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/label">源代码</ulink>

en: Entry
zh_CN: 条目(Entry)

en: Simple Use
zh_CN: 简易用法

en: Entry widgets allow the user to enter text. You can change the contents with the <methodname>set_text()</methodname> method, and read the current contents with the <methodname>get_text()</methodname> method.
zh_CN: 条目部件允许用户输入文本。你可以使用<methodname>set_text()</methodname>方法更改部件当前的内容，还可以使用<methodname>get_text()</methodname>方法读取当前的内容。

en: Occasionally you might want to make an <classname>Entry</classname> widget read-only. This can be done by passing <literal>false</literal> to the <methodname>set_editable()</methodname> method.
zh_CN: 有时你可能想使<classname>Entry</classname>部件变为只读的。你可以通过向<methodname>set_editable()</methodname>方法传递<literal>false</literal>做到这点。

en: For the input of passwords, passphrases and other information you don't want echoed on the screen, calling <methodname>set_visibility()</methodname> with <literal>false</literal> will cause the text to be hidden.
zh_CN: 对于不想在屏幕上回显的密码、密语或者其他信息，你可以通过向<methodname>set_visibility()</methodname>方法传递<literal>false</literal>使输入文本被隐藏。

en: You might want to be notified whenever the user types in a text entry widget. <classname>Gtk::Entry</classname> provides two signals, <literal>activate</literal> and <literal>changed</literal>, for this purpose. <literal>activate</literal> is emitted when the user presses the <keycap>Enter</keycap> key in a text-entry widget; <literal>changed</literal> is emitted when the text in the widget changes. You can use these, for instance, to validate or filter the text the user types. Moving the keyboard focus to another widget may also signal that the user has finished entering text. The <literal>focus_out_event</literal> signal that <classname>Gtk::Entry</classname> inherits from <classname>Gtk::Widget</classname> can notify you when that happens. The <link linkend="sec-comboboxentry">ComboBox with an Entry</link> section contains example programs that use these signals.
zh_CN: 当用户在条目部件上输入文本时你可能想要收到通知。为此<classname>Gtk::Entry</classname>提供了两个信号，他们分别是<literal>activate</literal>和<literal>changed</literal>。当用户在条目部件上按下<keycap>Enter</keycap>键时，部件将发出<literal>activate</literal>信号；当部件上的文本发生更改的时候，部件将会发出<literal>changed</literal>信号。你可以利用这些信号对用户的输入进行校验或者是过滤。将键盘焦点移动到其他的部件可能表示用户已经完成了文本输入。这种时候<classname>Gtk::Entry</classname>将会发出继承自<classname>Gtk::Widget</classname>的<literal>focus_out_event</literal>信号提醒你。<link linkend="sec-comboboxentry">带有条目的组合框</link>小结包含了使用这些信号的示例程序。

en: If you pass <literal>true</literal> to the <methodname>set_activates_default()</methodname> method, pressing <keycap>Enter</keycap> in the <classname>Gtk::Entry</classname> will activate the default widget for the window containing the <classname>Gtk::Entry</classname>. This is especially useful in dialog boxes. The default widget is usually one of the dialog buttons, which e.g. will close the dialog box. To set a widget as the default widget, use <methodname>Gtk::Widget::set_can_default()</methodname> and <methodname>Gtk::Widget::grab_default()</methodname>.
zh_CN: 如果你将<literal>true</literal>传递给<methodname>set_activates_default()</methodname>方法，那么当你在<classname>Gtk::Entry</classname>中按下<keycap>Enter</keycap>的时候包含这个<classname>Gtk::Entry</classname>的窗口将会激活其默认部件。这在对话框中特别的有用。默认部件通常会是对话框的按钮之一，例如对话框的关闭按钮。若你想主动的将某个部件设置为默认部件，请使用<methodname>Gtk::Widget::set_can_default()</methodname>和<methodname>Gtk::Widget::grab_default()</methodname>。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Entry.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Entry.html">参考</ulink>

en: Simple Entry Example
zh_CN: 简单的条目示例

en: This example uses <classname>Gtk::Entry</classname>. It also has two <classname>CheckButton</classname>s, with which you can toggle the editable and visible flags.
zh_CN: 本示例使用<classname>Gtk::Entry</classname>。他还有两个<classname>CheckButton</classname>，你可以使用他们切换条目部件的可见性和可编辑性标志。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/entry/simple">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/entry/simple">源代码</ulink>

en: Entry Completion
zh_CN: 条目补全(Entry Completion)

en: An <classname>Entry</classname> widget can offer a drop-down list of pre-existing choices based on the first few characters typed by the user. For instance, a search dialog could suggest text from previous searches.
zh_CN: <classname>Entry</classname>条目组件可以通过用户输入的前几个字符提供预先准备好选项的下拉列表。例如，在搜索对话框中提供以前输入过的文本作为建议。

en: To enable this functionality, you must create an <classname>EntryCompletion</classname> object, and provide it to the <classname>Entry</classname> widget via the <methodname>set_completion()</methodname> method.
zh_CN: 要启用此功能，你需要创建一个<classname>EntryCompletion</classname>对象，然后使用<classname>Entry</classname>部件的<methodname>set_completion()</methodname>方法将其提供给条目部件。

en: The <classname>EntryCompletion</classname> may use a <classname>TreeModel</classname> containing possible entries, specified with <methodname>set_model()</methodname>. You should then call <methodname>set_text_column()</methodname> to specify which of your model columns should be used to match possible text entries.
zh_CN: <classname>EntryCompletion</classname>可以用<methodname>set_model()</methodname>指定一个包含所有可能的条目的<classname>TreeModel</classname>。你应该调用<methodname>set_text_column()</methodname>指定该模型的那一行用以匹配可能的文本条目。

en: Alternatively, if a complete list of possible entries would be too large or too inconvenient to generate, a callback slot may instead be specified with <methodname>set_match_func()</methodname>. This is also useful if you wish to match on a part of the string other than the start.
zh_CN: 或是在不方便生成补全条目列表的时候(太大或者生成太麻烦)，也可以使用<methodname>set_match_func()</methodname>指定一个回调槽。这在你想匹配字符串中开头以外的部分的时候这会很有用。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1EntryCompletion.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1EntryCompletion.html">参考</ulink>

en: Entry Completion Example
zh_CN: 条目补全示例

en: This example creates a <classname>Gtk::EntryCompletion</classname> and associates it with a <classname>Gtk::Entry</classname> widget. The completion uses a <classname>Gtk::TreeModel</classname> of possible entries, and some additional actions.
zh_CN: 这个示例创建一个<classname>Gtk::EntryCompletion</classname>并将其与<classname>Gtk::Entry</classname>相关联。补全使用了一个包含了可能条目的<classname>Gtk::TreeModel</classname>以及一些其他的额外的操作。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/entry/completion">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/entry/completion">源代码</ulink>

en: Entry Icons
zh_CN: 条目图标

en: An <classname>Entry</classname> widget can show an icon at the start or end of the text area. The icon can be specifed by methods such as <methodname>set_icon_from_pixbuf()</methodname> or <methodname>set_icon_from_icon_name()</methodname>. An application can respond to the user pressing the icon by handling the <methodname>signal_icon_press</methodname> signal.
zh_CN: <classname>Entry</classname>部件可以在文本区域的开头或结尾显示一个图标。可以使用<methodname>set_icon_from_pixbuf()</methodname>或<methodname>set_icon_from_icon_name()</methodname>之类的方法指定要显示的图标。应用程序可以通过响应<methodname>signal_icon_press</methodname>信号来处理用户按下图标事件。

en: Entry Icon Example
zh_CN: 条目图标示例

en: This example shows a <classname>Gtk::Entry</classname> widget with a named search icon, and prints text to the terminal when the icon is pressed.
zh_CN: 这个示例显示带有具名搜索图标的<classname>Gtk::Entry</classname>部件，并且在按下这个图标的时候将该名称打印到终端上。

en: Entry with Icon
zh_CN: 带图标的条目

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/entry/icon">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/entry/icon">源代码</ulink>

en: Entry Progress
zh_CN: 条目进度

en: An <classname>Entry</classname> widget can show a progress bar inside the text area, under the entered text. The progress bar will be shown if the <methodname>set_progress_fraction()</methodname> or <methodname>set_progress_pulse_step()</methodname> methods are called.
zh_CN: <classname>Entry</classname>部件可以在输入的文本之下显示一个进度条。当部件的<methodname>set_progress_fraction()</methodname>或<methodname>set_progress_pulse_step()</methodname>方法被调用的时候进度条将显示出来。

en: Entry Progress Example
zh_CN: 条目进度示例

en: This example shows a <classname>Gtk::Entry</classname> widget with a progress bar.
zh_CN: 这个示例显示一个带有进度条的<classname>Gtk::Entry</classname>部件。

en: Entry with Progress Bar
zh_CN: 带有进度条的条目

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/entry/progress">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/entry/progress">源代码</ulink>

en: SpinButton
zh_CN: 微调按钮(SpinButton)

en: A <classname>SpinButton</classname> allows the user to select a value from a range of numeric values. It has an <classname>Entry</classname> widget with increment and decrement buttons at the side. Clicking the buttons causes the value to 'spin' up and down across the range of possible values. The <classname>Entry</classname> widget may also be used to enter a value directly.
zh_CN: <classname>SpinButton</classname>允许用户从一个数值范围内选择一个值。它包含了一个<classname>Entry</classname>部件在其侧边有递增和递减按钮。单击按钮会使得值在可能的范围内“旋转”。你也可以直接在<classname>Entry</classname>部件中输入一个值。

en: The value can have an adjustable number of decimal places, and the step size is configurable. <classname>SpinButton</classname>s have an 'auto-repeat' feature as well: holding down the increment or decrement button can optionally cause the value to change more quickly the longer the button is held down.
zh_CN: 这个值的小数位可以进行调整，步长也可以进行配置。<classname>SpinButton</classname>具有“自动重复”功能：长按递增、递减按钮该值的变化速度会越来越快。

en: <literal>value</literal>: value for the Spin Button
zh_CN: <literal>value</literal>：微调按钮的值

en: <literal>lower</literal>: lower range value
zh_CN: <literal>lower</literal>：微调按钮允许的最小值

en: <literal>upper</literal>: upper range value
zh_CN: <literal>upper</literal>：微调按钮允许的最大值

en: <literal>step_increment</literal>: value to increment/decrement when pressing mouse button 1
zh_CN: <literal>step_increment</literal>：鼠标键1(通常是左键)点击一下递增/递减的值

en: <literal>page_increment</literal>: value to increment/decrement when pressing mouse button 2
zh_CN: <literal>page_increment</literal>：鼠标键2(通常是右键)点击一下递增/递减的值

en: <literal>page_size</literal>: unused
zh_CN: <literal>page_size</literal>：目前没作用

en: <classname>SpinButton</classname>s use an <link linkend="chapter-adjustment">Adjustment</link> object to hold information about the range of values. These Adjustment attributes are used by the Spin Button like so: <_:itemizedlist-1/>
zh_CN: <classname>SpinButton</classname>使用<link linkend="chapter-adjustment">调整(Adjustment)</link>对象保存值的范围信息。下述调整属性由微调按钮使用：<_:itemizedlist-1/>

en: Additionally, mouse button 3 can be used to jump directly to the <literal>upper</literal> or <literal>lower</literal> values.
zh_CN: 另外，鼠标键3(通常是中键)用于直接跳到<literal>upper</literal>或<literal>lower</literal> values。

en: The <classname>SpinButton</classname> can create a default <classname>Adjustment</classname>, which you can access via the <methodname>get_adjustment()</methodname> method, or you can specify an existing <classname>Adjustment</classname> in the constructor.
zh_CN: <classname>SpinButton</classname>可以创建一个默认状态的<classname>Adjustment</classname>，然后你可以调用<methodname>get_adjustment()</methodname>方法访问这个<classname>Adjustment</classname>，也可以通过<classname>SpinButton</classname>的构造函数直接使用一个已经存在的<classname>Adjustment</classname>。

en: The number of decimal places can be altered using the <methodname>set_digits()</methodname> method.
zh_CN: 数值的小数位可以使用<methodname>set_digits()</methodname>方法进行调整。

en: You can set the spinbutton's value using the <methodname>set_value()</methodname> method, and retrieve it with <methodname>get_value()</methodname>.
zh_CN: 你可以使用<methodname>set_value()</methodname>方法设置微调按钮的值，也可以使用<methodname>get_value()</methodname>方法获得微调按钮的值。

en: The <methodname>spin()</methodname> method 'spins' the <classname>SpinButton</classname>, as if its increment or decrement button had been clicked. You need to specify a <classname>Gtk::SpinType</classname> to specify the direction or new position.
zh_CN: <methodname>spin()</methodname>方法的行为和手动点击递增/递减按钮一样。你需要传递一个<classname>Gtk::SpinType</classname>对象给该方法以指定是递增还是递减。

en: To prevent the user from typing non-numeric characters into the entry box, pass <literal>true</literal> to the <methodname>set_numeric()</methodname> method.
zh_CN: 将<literal>true</literal>传递给<methodname>set_numeric()</methodname>方法可以阻止用户在条目框内输入非数字字符。

en: To make the <classname>SpinButton</classname> 'wrap' between its upper and lower bounds, use the <methodname>set_wrap()</methodname> method.
zh_CN: 使用<methodname>set_wrap()</methodname>方法指定<classname>SpinButton</classname>的值到达上下限的时候是否绕回。

en: To force it to snap to the nearest <literal>step_increment</literal>, use <methodname>set_snap_to_ticks()</methodname>.
zh_CN: 使用<methodname>set_snap_to_ticks()</methodname>方法可以在向微调按钮设置了无效值的时候强制校正到最接近<literal>step_increment</literal>策略可达到的有效值。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1SpinButton.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1SpinButton.html">参考</ulink>

en: Here's an example of a <classname>SpinButton</classname> in action:
zh_CN: 这是一个使用<classname>SpinButton</classname>的示例：

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/spinbutton">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/spinbutton">源代码</ulink>

en: ProgressBar
zh_CN: 进度条(ProgressBar)

en: Progress bars are used to show the status of an ongoing operation. For instance, a <classname>ProgressBar</classname> can show how much of a task has been completed.
zh_CN: 进度条用于显示正在进行的操作的状态。例如，<classname>ProgressBar</classname>可以用于显示已经有多少任务被完成。

en: To change the value shown, use the <methodname>set_fraction()</methodname> method, passing a <type>double</type> between 0.0 and 1.0 to provide the new fraction.
zh_CN: 要修改显示的值，请调用<methodname>set_fraction()</methodname>方法，向该方法传递一个0.0到1.0之间的<type>double</type>值。

en: A <classname>ProgressBar</classname> is horizontal and left-to-right by default, but you can change it to a vertical progress bar by using the <methodname>set_orientation()</methodname> method.
zh_CN: <classname>ProgressBar</classname>默认是水平且从左向右的，但是你可以使用<methodname>set_orientation()</methodname>方法来改变这个行为。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ProgressBar.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ProgressBar.html">参考</ulink>

en: Activity Mode
zh_CN: 活动模式

en: Besides indicating the amount of progress that has occured, the progress bar can also be used to indicate that there is some activity; this is done by placing the progress bar in <emphasis>activity mode</emphasis>. In this mode, the progress bar displays a small rectangle which moves back and forth. Activity mode is useful in situations where the progress of an operation cannot be calculated as a value range (e.g., receiving a file of unknown length).
zh_CN: 除了用于表示已经达成的进度，进度条还可以用于表示任务处于活动状态；只需要将进度条的行为模式设置为<emphasis>activity mode</emphasis>即可。在这个模式下，进度条显示一个小矩形，该矩形可以在进度条内前后移动。活动模式在无法确定操作的进度的时候很有用（例如，接受一个长度未知的文件）。

en: To do this, you need to call the <methodname>pulse()</methodname> method at regular intervals. You can also choose the step size, with the <methodname>set_pulse_step()</methodname> method.
zh_CN: 为此，你还需要定时调用<methodname>pulse()</methodname>方法。你还可以使用<methodname>set_pulse_step()</methodname>方法控制矩形的移动步长。

en: The progress bar can also display a configurable text string next to the bar, using the <methodname>set_text()</methodname> method.
zh_CN: 进度条还可以使用<methodname>set_text()</methodname>方法来在其边上显示可配置的文本字符串。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/progressbar">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/progressbar">源代码</ulink>

en: InfoBar
zh_CN: 信息栏(InfoBar)

en: An <classname>InfoBar</classname> may show small items of information or ask brief questions. Unlike a <classname>Dialog</classname>, it appears at the top of the current window instead of opening a new window. Its API is very similar to the <link linkend="chapter-dialogs">Gtk::Dialog</link> API.
zh_CN: <classname>InfoBar</classname>可用于显示一些信息、小物品或者简短的问题。他显示在窗口的顶部而不是和<classname>Dialog</classname>一样打开一个新的窗口。但是他的API和<link linkend="chapter-dialogs">Gtk::Dialog</link>的API十分相似。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1InfoBar.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1InfoBar.html">参考</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/infobar">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/infobar">源代码</ulink>

en: Tooltips
zh_CN: 工具提示框(Tooltips)

en: Tooltips are the little information windows that pop up when you leave your pointer over a widget for a few seconds. Use <methodname>set_tooltip_text()</methodname> to set a text string as a tooltip on any <classname>Widget</classname>. <classname>Gtk::Tooltip</classname> is used for more advanced tooltip usage, such as showing an image as well as text.
zh_CN: 工具提示框是将鼠标悬停于部件上几秒后弹出的信息窗口。使用<methodname>set_tooltip_text()</methodname>可以为任意的<classname>Widget</classname>设置一个文本字符串作为提示。<classname>Gtk::Tooltip</classname>被用作更高级的提示工具，例如显示图像和文本。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Widget.html">Widget Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Widget.html">部件参考</ulink>

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Tooltip.html">Tooltip Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Tooltip.html">工具提示框参考</ulink>

en: Tooltip
zh_CN: 工具提示框(Tooltip)

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/tooltips">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/tooltips">源代码</ulink>

en: Container Widgets
zh_CN: 容器(Container)部件

en: Container widgets, like other widgets, derive from <classname>Gtk::Widget</classname>. Some container widgets, such as <classname>Gtk::Grid</classname> can hold many child widgets, so these typically have more complex interfaces. Others, such as <classname>Gtk::Frame</classname> contain only one child widget.
zh_CN: 容器部件与其他部件一样都是从<classname>Gtk::Widget</classname>派生而来。一些容器部件可以容纳多个子部件，例如<classname>Gtk::Grid</classname>，因此通常他们具有更为复杂的接口。还有些容器部件只能容纳一个子部件，例如<classname>Gtk::Frame</classname>

en: Single-item Containers
zh_CN: 单项容器

en: Most single-item container widgets have <methodname>set_child()</methodname> and <methodname>unset_child()</methodname> methods for the child widget. <classname>Gtk::Button</classname> and <classname>Gtk::Window</classname> are technically single-item containers, but we have discussed them already elsewhere.
zh_CN: 大多数单项容器部件具有其子部件的<methodname>set_child()</methodname>和<methodname>unset_child()</methodname>方法。<classname>Gtk::Button</classname>和<classname>Gtk::Window</classname>从技术上来说是单项容器，但是我们已经在其他地方讨论过它们。

en: We also discuss the <classname>Gtk::Paned</classname> widget, which allows you to divide a window into two separate "panes". This widget actually contains two child widgets, but the number is fixed so it seems appropriate.
zh_CN: 我们还讨论了<classname>Gtk::Paned</classname>部件，它允许你将窗口分为两个单独的"窗格"，这个部件实际上可以包含两个子部件，但是他只能包含固定数量的部件，因此也将其称为单项容器。

en: Frame
zh_CN: 框架(Frame)

en: Frames can enclose one or a group of widgets within a box, optionally with a title. For instance, you might place a group of <classname>ToggleButton</classname>s or <classname>CheckButton</classname>s in a <classname>Frame</classname>.
zh_CN: 框架可以将一个或一组部件封装在一个框内，还可以为他们选择标题。例如你可以将一组<classname>ToggleButton</classname>或者<classname>CheckButton</classname>放入一个<classname>Frame</classname>中。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Frame.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Frame.html">参考</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/frame">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/frame">源代码</ulink>

en: Paned
zh_CN: 窗格(Paned)

en: Panes divide a widget into two halves, separated by a moveable divider. The two halves (panes) can be oriented either horizontally (side by side) or vertically (one above the other).
zh_CN: 窗格用一个可移动的分隔符将一个部件一分为二。其可以水平（使两个窗格并排）也可以竖直（使两个窗格一个在另一个之上）的分隔部件。

en: Unlike the other widgets in this section, pane widgets contain not one but two child widgets, one in each pane. Therefore, you should use <methodname>set_start_child()</methodname> and <methodname>set_end_child()</methodname> instead of a <methodname>set_child()</methodname> method.
zh_CN: 与本小节的其他小部件不一样的是，窗格部件包含两个子部件而不是一个部件（每个窗格中一个）。因此你应该用<methodname>set_start_child()</methodname>和<methodname>set_end_child()</methodname>替代<methodname>set_child()</methodname>方法。

en: You can adjust the position of the divider using the <methodname>set_position()</methodname> method, and you will probably need to do so.
zh_CN: 如果你需要，你可以使用<methodname>set_position()</methodname>调整分割线的位置。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Paned.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Paned.html">参考</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/paned">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/paned">源代码</ulink>

en: ScrolledWindow
zh_CN: 滚动窗口

en: <classname>ScrolledWindow</classname> widgets create a scrollable area. You can insert any type of widget into a <classname>ScrolledWindow</classname>, and it will be accessible regardless of its size by using the scrollbars. Note that <classname>ScrolledWindow</classname> is not a <classname>Gtk::Window</classname> despite the slightly misleading name.
zh_CN: <classname>ScrolledWindow</classname>部件会创建一个可以滚动的区域。你可以将任何类型的部件插入到<classname>ScrolledWindow</classname>中，无论该部件有多大你都可以通过滚动条来访问它。请注意虽然<classname>ScrolledWindow</classname>的名称像是<classname>Gtk::Window</classname>的衍生部件，但其实不是。

en: Scrolled windows have <emphasis>scrollbar policies</emphasis> which determine whether the <classname>Scrollbar</classname>s will be displayed. The policies can be set with the <methodname>set_policy()</methodname> method. The policy may be for instance <literal>Gtk::PolicyType::AUTOMATIC</literal> or <literal>Gtk::PolicyType::ALWAYS</literal>. <literal>Gtk::PolicyType::AUTOMATIC</literal> will cause the scrolled window to display the scrollbar only if the contained widget is larger than the visible area. <literal>Gtk::PolicyType::ALWAYS</literal> will cause the scrollbar to be displayed always.
zh_CN: 滚动窗口具有用于确定是否要显示<classname>Scrollbar(滚动条)</classname>的<emphasis>scrollbar policies(滚动条策略)</emphasis>。你可以使用<methodname>set_policy()</methodname>方法来设置策略。例如设置策略为<literal>Gtk::PolicyType::AUTOMATIC</literal>或是<literal>Gtk::PolicyType::ALWAYS</literal>。当策略为<literal>Gtk::PolicyType::AUTOMATIC</literal>的时候，只有在被包含的部件大于可见区域的时候滚动条才会被显示出来。而<literal>Gtk::PolicyType::ALWAYS</literal>将使滚动条始终显示。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ScrolledWindow.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ScrolledWindow.html">参考</ulink>

en: Here is a simple example that packs 100 toggle buttons into a ScrolledWindow. Try resizing the window to see the scrollbars react.
zh_CN: 这是一个简单的示例，其将100个开关按钮放入滚动窗口中。你可以尝试调整窗口的大小，以查看滚动条的反应。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/scrolledwindow">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/scrolledwindow">源代码</ulink>

en: AspectFrame
zh_CN: 定比框架(AspectFrame)

en: The <classname>AspectFrame</classname> widget looks like a <classname>Frame</classname> widget, but it also enforces the <emphasis>aspect ratio</emphasis> (the ratio of the width to the height) of the child widget, adding extra space if necessary. For instance, this would allow you to display a photograph without allowing the user to distort it horizontally or vertically while resizing.
zh_CN: <classname>AspectFrame</classname>部件和<classname>Frame</classname>部件类似，但它强制子部件的<emphasis>aspect ratio(长宽比)</emphasis>（长与宽的比例）保持不变。并在有必要的时候添加额外的空间。例如，这将允许你显示照片并且无需在用户调整窗口大小的时候对照片进行水平/垂直变形。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1AspectFrame.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1AspectFrame.html">参考</ulink>

en: The following program uses a <classname>Gtk::AspectFrame</classname> to present a drawing area whose aspect ratio will always be 2:1, no matter how the user resizes the top-level window.
zh_CN: 下面的程序使用<classname>Gtk::AspectFrame</classname>显示一个绘图区域，无论用户如何调整顶层窗口大小宽高比依旧保持2:1。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/aspectframe">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/aspectframe">源代码</ulink>

en: Other Single-item Containers
zh_CN: 其他单项容器

en: There are other single-item containers. See the reference documentation for a complete list. Here are links to some example programs that show containers, which are not mentioned elsewhere in this tutorial.
zh_CN: 还有其他的单项容器。请参阅参考文档获取完整列表。这里是一些本教程其他地方未曾提及的显示容器的示例程序的链接。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/expander">Source Code, Expander</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/expander">扩展器(Expander)源代码</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/popover">Source Code, Popover</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/popover">气泡(Popover)源代码</ulink>

en: Multiple-item Containers
zh_CN: 多项容器

en: Multiple-item container widgets have other methods than <methodname>set_child()</methodname> and <methodname>unset_child()</methodname>. Different containers can have different methods for adding and removing child widgets. For instance, <classname>Gtk::Box</classname> has <methodname>append()</methodname> and <methodname>remove()</methodname> as well as other methods. The <methodname>remove()</methodname> method for multiple-item containers takes an argument, specifying which widget to remove.
zh_CN: 多项容器部件除<methodname>set_child()</methodname>和<methodname>unset_child()</methodname>方法以外还有其他的方法。不同容器有不同的添加/删除子部件的方法。例如<classname>Gtk::Box</classname>具有<methodname>append()</methodname>和<methodname>remove()</methodname>以及其他方法。多项容器的<methodname>remove()</methodname>方法需要传入一个用于指示需要删除的部件的参数。

en: Packing
zh_CN: 组装(Packing)

en: You've probably noticed that <application>gtkmm</application> windows seem "elastic" - they can usually be stretched in many different ways. This is due to the <emphasis>widget packing</emphasis> system.
zh_CN: 你可能已经注意到了<application>gtkmm</application>窗口看起来是“弹性”的 -他们通常可以以不同方式进行拉伸。这是<emphasis>部件装填(widget packing)</emphasis>系统在起作用。

en: Many GUI toolkits require you to precisely place widgets in a window, using absolute positioning, often using a visual editor. This leads to several problems:
zh_CN: 许多GUI工具包使用可视化编辑器的时候都要求你使用部件相对于窗口的绝对位置。这将导致以下几个问题：

en: The widgets don't rearrange themselves when the window is resized. Some widgets are hidden when the window is made smaller, and lots of useless space appears when the window is made larger.
zh_CN: 在调整窗口大小的时候部件不会重新排布自己。窗口变小的时候一些部件会被隐藏窗口变大的时候会出现很多无用的空间。

en: It's impossible to predict the amount of space necessary for text after it has been translated to other languages, or displayed in a different font. On Unix it is also impossible to anticipate the effects of every theme and window manager.
zh_CN: 将文本翻译成其他语言或者用其他字体显示的时候，无法预测显示文本所需要的空间。而在Unix上不可能预料在每个主题和窗口管理器下的显示效果。

en: Changing the layout of a window "on the fly", to make some extra widgets appear, for instance, is complex. It requires tedious recalculation of every widget's position.
zh_CN: 即时更改窗口布局以显示额外的部件将会很复杂，这需要对每个部件的位置进行繁琐的重新计算。

en: <application>gtkmm</application> uses the packing system to solve these problems. Rather than specifying the position and size of each widget in the window, you can arrange your widgets in rows, columns, and/or grids. <application>gtkmm</application> can size your window automatically, based on the sizes of the widgets it contains. And the sizes of the widgets are, in turn, determined by the amount of text they contain, or the minimum and maximum sizes that you specify, and/or how you have requested that the available space should be shared between sets of widgets. You can perfect your layout by specifying margins and centering values for each of your widgets. <application>gtkmm</application> then uses all this information to resize and reposition everything sensibly and smoothly when the user manipulates the window.
zh_CN: <application>gtkmm</application>使用装填系统解决这些问题。无需为窗口中的每个部件指定大小和位置，而是将部件放入行、列、和或网格中。<application>gtkmm</application>可以基于包含的部件的大小自动调整你的窗口大小。部件的大小由它包含的文本量、最大/小尺寸（由你指定的）、部件之间如何共享可用空间（你要求的方式）共同决定。你可以通过为每个部件指定边距与居中值来完善布局。然后<application>gtkmm</application>会使用以上的信息在用户操作窗口的时候合理、顺畅的调整部件们的大小和位置。

en: <application>gtkmm</application> arranges widgets hierarchically, using <emphasis>containers</emphasis>. A container widget contains other widgets. Most <application>gtkmm</application> widgets are containers. Windows, Notebook tabs, and Buttons are all container widgets. There are two flavours of containers: single-child containers and multiple-child containers. Most container widgets in <application>gtkmm</application> are single-child containers, including <classname>Gtk::Window</classname>.
zh_CN: <application>gtkmm</application>使用<emphasis>containers</emphasis>分层排布部件。容器部件包含其他部件。大多数的<application>gtkmm</application>部件都是容器部件。窗口(Windows)部件、笔记本选项卡(Notebook tabs)部件、按钮(Buttons)部件都是容器部件。容器有两种类型：单项容器和多项容器。<application>gtkmm</application>中包括<classname>Gtk::Window</classname>在内的多数容器部件都是单项部件。

en: Yes, that's correct: a Window can contain at most one widget. How, then, can we use a window for anything useful? By placing a multiple-child container in the window. The most useful container widgets are <classname>Gtk::Grid</classname> and <classname>Gtk::Box</classname>.
zh_CN: 对，没错，一个窗口最多只能包含一个部件。那么我们要如何将多个部件放于窗口中呢？答案是通过向窗口放入一个多项容器实现。最合理的部件是<classname>Gtk::Grid</classname>和<classname>Gtk::Box</classname>。

en: <classname>Gtk::Grid</classname> arranges its child widgets in rows and columns. Use <methodname>attach()</methodname> and <methodname>attach_next_to()</methodname> to insert child widgets.
zh_CN: <classname>Gtk::Grid</classname>将其子部件按行和列排列。使用<methodname>attach()</methodname>和<methodname>attach_next_to()</methodname>方法向网格(Grid)部件中插入子部件。

en: <classname>Gtk::Box</classname> arranges its child widgets vertically or horizontally. Use <methodname>append()</methodname> to insert child widgets.
zh_CN: <classname>Gtk::Box</classname>将其子部件水平或垂直排列。使用<methodname>append()</methodname>方法向盒(Box)部件插入子部件。

en: There are several other containers, which we will also discuss.
zh_CN: 还有几个容器我们将在之后讨论。

en: If you've never used a packing toolkit before, it can take some getting used to. You'll probably find, however, that you don't need to rely on visual form editors quite as much as you might with other toolkits.
zh_CN: 如果你之前从未使用组装工具包，那可能需要一段时间来适应它。然后你会发现你不需要和使用其他工具包一样依赖可视化编辑工具。

en: An improved Hello World
zh_CN: 改进后的Hello World

en: Let's take a look at a slightly improved <literal>helloworld</literal>, showing what we've learnt.
zh_CN: 让我们看看改进后的<literal>helloworld</literal>，以展示我们所学到的内容。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/helloworld2">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/helloworld2">源代码</ulink>

en: After building and running this program, try resizing the window to see the behaviour. Also, try playing with <methodname>set_expand()</methodname>, <methodname>set_hexpand()</methodname>, <methodname>set_vexpand()</methodname>, <methodname>set_halign()</methodname> and <methodname>set_valign()</methodname> while reading the <link linkend="sec-boxes">Boxes</link> section.
zh_CN: 生成并运行这个程序后，请尝试调整窗口的大小查看其行为。此外在阅读<link linkend="sec-boxes">盒子(Boxes)</link>小节时请尝试使用<methodname>set_expand()</methodname>、<methodname>set_hexpand()</methodname>、<methodname>set_vexpand()</methodname>、<methodname>set_halign()</methodname>和<methodname>set_valign()</methodname>方法。

en: Boxes
zh_CN: 盒子(Boxes)

en: Most packing uses boxes as in the above example. These are invisible containers into which we can pack our widgets. When packing widgets into a horizontal box, the objects are inserted horizontally from left to right. In a vertical box, widgets are packed from top to bottom. You may use any combination of boxes inside or beside other boxes to create the desired effect.
zh_CN: 如上例所示，这些都是不可见容器我们可以将容器装入其中。将部件装填到水平盒中的时候部件从左到右水平插入。将部件装填到垂直盒中的时候部件从上到下垂直插入。你可以在盒中或盒侧组合使用盒以达到你所需的效果。

en: Adding widgets
zh_CN: 添加部件

en: Per-child packing options
zh_CN: 子部件装填选项

en: The <methodname>append()</methodname> method places widgets inside these containers. It will start at the top and work its way down in a <classname>Box</classname> with vertical orientation, or pack left to right in a <classname>Box</classname> with horizontal orientation. If it's inconvenient to add widgets in this order, use <methodname>insert_child_after()</methodname> or <methodname>insert_child_at_start()</methodname>. We will use <methodname>append()</methodname> in our examples.
zh_CN: <methodname>append()</methodname>方法将部件放置于这些容器中。它们将从顶部开始。按<classname>Box</classname>的垂直方向向下移动，或者按<classname>Box</classname>的水平方向从左向右移动。如果你不愿意按此顺序添加子部件，请使用<methodname>insert_child_after()</methodname>或<methodname>insert_child_at_start()</methodname>方法。我们将在示例中使用<methodname>append()</methodname>。

en: There are several options governing how widgets are to be packed, and this can be confusing at first. You can modify the packing by using <methodname>set_expand()</methodname>, <methodname>set_hexpand()</methodname>, <methodname>set_vexpand()</methodname>, <methodname>set_halign()</methodname>, <methodname>set_valign()</methodname> and/or <methodname>set_margin()</methodname> on the child widgets. If you have difficulties, then it is sometimes a good idea to play with the <application>glade</application> GUI designer to see what is possible. You might even decide to use the <classname>Gtk::Builder</classname> API to load your GUI at runtime.
zh_CN: 有几个选项可以控制部件的打包方式，但是初次使用可能会难以理清效果。你可以在子部件上使用<methodname>set_expand()</methodname>、<methodname>set_hexpand()</methodname>、<methodname>set_vexpand()</methodname>、<methodname>set_halign()</methodname>、<methodname>set_valign()</methodname>方法修改装填策略。如果你感到困难，可以试试<application>glade</application>GUI设计器，看看能不能对你有所帮助。你甚至可以使用<classname>Gtk::Builder</classname>API在运行时加载GUI。

en: There are basically five different styles, as shown in this picture:
zh_CN: 如图所示，有五种不同的基本样式。

en: Box Packing 1
zh_CN: 组装盒1

en: Each line contains one horizontal <classname>Box</classname> with several buttons. Each of the buttons on a line is packed into the <classname>Box</classname> with the same arguments to the <methodname>set_hexpand()</methodname>, <methodname>set_halign()</methodname>, <methodname>set_margin_start()</methodname> and <methodname>set_margin_end()</methodname> methods.
zh_CN: 每一行包含一个有多个按钮的水平<classname>Box</classname>。行中的每一个按钮都使用相同参数的<methodname>set_hexpand()</methodname>、<methodname>set_halign()</methodname>、<methodname>set_margin_start()</methodname>和<methodname>set_margin_end()</methodname>方法装入<classname>Box</classname>。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Box.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Box.html">参考</ulink>

en: Per-container packing options
zh_CN: 容器装填选项

en: Here's the constructor for the <classname>Box</classname> widget, and methods that set per-container packing options: <_:programlisting-1/> Passing <literal>true</literal> to <methodname>set_homogeneous()</methodname> will cause all of the contained widgets to be the same size. <parameter>spacing</parameter> is a (minimum) number of pixels to leave between each widget.
zh_CN: 这是<classname>Box</classname>部件的构造函数，以及设置每个容器的打包选项的方法：<_:programlisting-1/> 将<literal>true</literal>传递给<methodname>set_homogeneous()</methodname>方法将导致容器部件所包含的所有部件都有一样的大小。<parameter>spacing</parameter>是每个部件之间要保留的最小像素数。

en: What's the difference between spacing (set when the box is created) and margins (set separately for each child widget)? Spacing is added between objects, and margins are added on one or more sides of a widget. The following figure should make it clearer. The shown margins are the left and right margins of each button in the row.
zh_CN: 间距（创建盒的时候设置）与边距（为每个子部件分别设置）的区别是：在对象之间添加间距，在部件的一侧或多侧添加边距。下图能使你更清楚的理解这一点。所显示的边距是该行中每个按钮的左右边距。

en: Box Packing 2
zh_CN: 组装盒2

en: Gtk::Application and command-line options
zh_CN: Gtk::Application和命令行选项

en: The following example program requires a command-line option. The source code shows two ways of handling command-line options in combination with <classname>Gtk::Application</classname>.
zh_CN: 下面的示例程序需要一个命令行选项。源代码展示了两种<classname>Gtk::Application</classname>处理命令行选项的方式。

en: Handle the options in <function>main()</function> and hide them from <classname>Gtk::Application</classname> by setting <literal>argc = 1</literal> in the call to <methodname>Gtk::Application::run()</methodname>.
zh_CN: 在<function>main()</function>中处理选项并且通过设置<literal>argc = 1</literal>将他们从<classname>Gtk::Application</classname>中隐藏，然后调用<methodname>Gtk::Application::run()</methodname>。

en: Give all command-line options to <methodname>Gtk::Application::run()</methodname> and add the flag <literal>Gio::Application::Flags::HANDLES_COMMAND_LINE</literal> to <methodname>Gtk::Application::create()</methodname>. Connect a signal handler to the <literal>command_line</literal> signal, and handle the command-line options in the signal handler.
zh_CN: 将所有的命令行选项传递给<methodname>Gtk::Application::run()</methodname>并为<methodname>Gtk::Application::create()</methodname>方法设置标志<literal>Gio::Application::Flags::HANDLES_COMMAND_LINE</literal>。

en: You must set the optional parameter <literal>after = false</literal> in the call to <literal>signal_command_line().connect()</literal>, because your signal handler must be called before the default signal handler. You must also call <methodname>Gio::Application::activate()</methodname> in the signal handler, unless you want your application to exit without showing its main window. (<classname>Gio::Application</classname> is a base class of <classname>Gtk::Application</classname>.)
zh_CN: 你必须在调用<literal>signal_command_line().connect()</literal>时设置可选参数<literal>after = false</literal>，因为此时必须在默认的信号处理程序之前调用你的信号处理程序。你还必须调用<methodname>Gio::Application::activate()</methodname>处理程序，除非你希望你的应用程序不显示主窗口直接退出（<classname>Gio::Application</classname>是<classname>Gtk::Application</classname>的基类）。

en: Here is the source code for the example that produced the screenshots above. When you run this example, provide a number between 1 and 3 as a command-line option, to see different packing options in use.
zh_CN: 这是上述截图所运行示例的源代码。在运行此示例时请提供1到3之间的数字作为命令行选项以查看正在使用不同装填选项的行为。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/box">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/box">源代码</ulink>

en: Grid
zh_CN: 网格(Grid)

en: A <classname>Grid</classname> dynamically lays out child widgets in rows and columns. The dimensions of the grid do not need to be specified in the constructor.
zh_CN: <classname>Grid</classname>在行与列中动态的摆放他的子部件。不需要在其构造函数当中指定维数。

en: Child widgets can span multiple rows or columns, using <methodname>attach()</methodname>, or added next to an existing widget inside the grid with <methodname>attach_next_to()</methodname>. Individual rows and columns of the grid can be set to have uniform height or width with <methodname>set_row_homogeneous()</methodname> and <methodname>set_column_homogeneous()</methodname>.
zh_CN: 使用<methodname>attach()</methodname>方法可以跨越多行/列插入子部件，也可以使用<methodname>attach_next_to()</methodname>将子部件插入已经存在于网格中的部件的旁边。可以通过调用<methodname>set_row_homogeneous()</methodname>和<methodname>set_column_homogeneous()</methodname>令网格中所有子部件具有一致的高度或宽度。

en: You can set the <emphasis>margin</emphasis> and <emphasis>expand</emphasis> properties of the child <classname>Widget</classname>s to control their spacing and their behaviour when the Grid is resized.
zh_CN: 你可以设置子部件的<emphasis>margin</emphasis>和<emphasis>expand</emphasis>属性用以控制调整网格大小时它们之间的间距。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Grid.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Grid.html">参考</ulink>

en: This example creates a window with three buttons in a grid. The first two buttons are in the upper row, from left to right. A third button is attached underneath the first button, in a new lower row, spanning two columns.
zh_CN: 本示例创建一个窗口其中具有一个包含三个按钮的网格。前两个按钮位于最上行并从左向右排列。第三个按钮位于第一个按钮的下方，位于最下行并横跨两列。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/grid">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/grid">源代码</ulink>

en: Notebook
zh_CN: 笔记本(Notebook)

en: A <classname>Notebook</classname> has a set of stacked <literal>pages</literal>, each of which contains widgets. Labelled <literal>tabs</literal> allow the user to select the pages. <classname>Notebook</classname>s allow several sets of widgets to be placed in a small space, by only showing one page at a time. For instance, they are often used in preferences dialogs.
zh_CN: <classname>Notebook</classname>有一组堆叠好的<literal>pages</literal>，每个页面(page)包含一个部件。带标签的<literal>tabs</literal>允许用户选择页面。<classname>Notebook</classname>一次只显示一页，这样可以将好几组部件放于很小的空间当中。例如他们经常在首选项对话框中使用。

en: Use the <methodname>append_page()</methodname>, <methodname>prepend_page()</methodname> and <methodname>insert_page()</methodname> methods to add tabbed pages to the <literal>Notebook</literal>, supplying the child widget and the name for the tab.
zh_CN: 使用<methodname>append_page()</methodname>、<methodname>prepend_page()</methodname>和<methodname>insert_page()</methodname>方法可以添加带标签的页面到<literal>Notebook</literal>中，你需要为这些方法提供子部件和标签名。

en: To discover the currently visible page, use the <methodname>get_current_page()</methodname> method. This returns the page number, and then calling <methodname>get_nth_page()</methodname> with that number will give you a pointer to the actual child widget.
zh_CN: 如果你想知道当前可见的页面是那一个，可以使用<methodname>get_current_page()</methodname>方法。该方法返回一个页码，你可以将页码传递给<methodname>get_nth_page()</methodname>获取指向该页当前子部件的指针。

en: To programmatically change the selected page, use the <methodname>set_current_page()</methodname> method.
zh_CN: 要以编程方式改变所选的页面，请使用<methodname>set_current_page()</methodname>方法。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Notebook.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Notebook.html">参考</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/notebook/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/notebook/">源代码</ulink>

en: Assistant
zh_CN: 助手(Assistant)

en: An <classname>Assistant</classname> splits a complex operation into steps. Each step is a page, containing a header, a child widget and an action area. The Assistant's action area has navigation buttons which update automatically depending on the type of the page, set with <methodname>set_page_type()</methodname>.
zh_CN: <classname>Assistant</classname>将一个复杂的操作切分为数个步骤。每个步骤都是一个页面，包含一个标题、一个子部件和一个可操作区域。助手的操作区域有一个导航按钮，这些按钮会根据页面的类型自动更新（使用<methodname>set_page_type()</methodname>设置页面类型）。

en: Use the <methodname>append_page()</methodname>, <methodname>prepend_page</methodname> and <methodname>insert_page()</methodname> methods to add pages to the <classname>Assistant</classname>, supplying the child widget for each page.
zh_CN: 使用<methodname>append_page()</methodname>、<methodname>prepend_page</methodname>和<methodname>insert_page()</methodname>方法可以向<classname>Assistant</classname>添加页面，你需要每个页面提供子部件。

en: To determine the currently-visible page, use the <methodname>get_current_page()</methodname> method, and pass the result to <methodname>get_nth_page()</methodname>, which returns a pointer to the actual widget. To programmatically change the current page, use the <methodname>set_current_page()</methodname> method.
zh_CN: 要确定当前可见的页面，请使用<methodname>get_current_page()</methodname>方法，然后将返回值传递给<methodname>get_nth_page()</methodname>，其会返回一个指向实际部件的指针。要想用编程的方式改变当前页，请使用<methodname>set_current_page()</methodname>方法。

en: To set the title of a page, use the <methodname>set_page_title()</methodname> method.
zh_CN: 要为页面设置标题，请使用<methodname>set_page_title()</methodname>方法。

en: To add widgets to the action area, use the <methodname>add_action_widget()</methodname> method. They will be packed alongside the default buttons. Use the <methodname>remove_action_widget()</methodname> method to remove widgets.
zh_CN: 要将部件添加到操作区域，请使用<methodname>add_action_widget()</methodname>方法。他们将与默认按钮一并被装填。使用<methodname>remove_action_widget()</methodname>方法可以删除部件。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Assistant.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Assistant.html">参考</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/assistant/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/assistant/">源代码</ulink>

en: Other Multi-item Containers
zh_CN: 其他多项容器

en: There are other multi-item containers. See the reference documentation for a complete list. Here are links to some example programs that show containers, which are not mentioned elsewhere in this tutorial.
zh_CN: 还有其他多项容器。请参阅文档以获取完整列表。这里是一些本教程未提及的显示容器的示例程序连接。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/actionbar">Source Code, ActionBar</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/actionbar">动作条(ActionBar)源代码</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/flowbox">Source Code, FlowBox</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/flowbox">流式盒(FlowBox)源代码</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/iconview">Source Code, IconView</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/iconview">图标视图(IconView)源代码</ulink>

en: The TreeView widget
zh_CN: 树形视图(TreeView)部件

en: The <classname>Gtk::TreeView</classname> widget can contain lists or trees of data, in columns.
zh_CN:  <classname>Gtk::TreeView</classname>部件的每一行都可以包含数据列表或数据树。

en: The Model
zh_CN: 模型(Model)

en: Each <classname>Gtk::TreeView</classname> has an associated <classname>Gtk::TreeModel</classname>, which contains the data displayed by the <classname>TreeView</classname>. Each <classname>Gtk::TreeModel</classname> can be used by more than one <classname>Gtk::TreeView</classname>. For instance, this allows the same underlying data to be displayed and edited in 2 different ways at the same time. Or the 2 Views might display different columns from the same Model data, in the same way that 2 SQL queries (or "views") might show different fields from the same database table.
zh_CN: 每一个<classname>Gtk::TreeView</classname>都有一个与之关联的<classname>Gtk::TreeModel</classname>，模型中包含了<classname>TreeView</classname>将要显示的数据。每个<classname>Gtk::TreeModel</classname>都可以被多个<classname>Gtk::TreeView</classname>使用。例如，这将允许以多种不同的方式同时显示和编辑一致的数据。也允许不同的视图显示同一个模型的不同列的数据，就像是多个SQL查询（或“视图”）显示同一个数据库表的不同字段一样。

en: Although you can theoretically implement your own Model, you will normally use either the <classname>ListStore</classname> or <classname>TreeStore</classname> model classes.
zh_CN: 理论上你可以实现自己的模型，但通常情况直接使用<classname>ListStore</classname>或<classname>TreeStore</classname>可以省略很多麻烦。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TreeModel.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TreeModel.html">参考</ulink>

en: ListStore, for rows
zh_CN: 列表储存(ListStore)的行

en: The <classname>ListStore</classname> contains simple rows of data, and each row has no children.
zh_CN: <classname>ListStore</classname>包含简单的数据行，每个行都没有孩子。

en: TreeView - ListStore
zh_CN: 树形视图 - 列表储存

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ListStore.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ListStore.html">参考</ulink>

en: TreeStore, for a hierarchy
zh_CN: 具有层次的树状储存

en: The <classname>TreeStore</classname> contains rows of data, and each row may have child rows.
zh_CN: <classname>TreeStore</classname>包含数据行，并且每一行都可能有子行。

en: TreeView - TreeStore
zh_CN: 树形视图 - 树状储存

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TreeStore.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TreeStore.html">参考</ulink>

en: Model Columns
zh_CN: 模型列

en: The <classname>TreeModelColumnRecord</classname> class is used to keep track of the columns and their data types. You add <classname>TreeModelColumn</classname> instances to the <classname>ColumnRecord</classname> and then use those <classname>TreeModelColumns</classname> when getting and setting the data in model rows. You will probably find it convenient to derive a new <classname>TreeModelColumnRecord</classname> which has your <classname>TreeModelColumn</classname> instances as member data.
zh_CN: <classname>TreeModelColumnRecord</classname>用于跟踪列和它们的数据类型。你<classname>TreeModelColumn</classname>实例添加到<classname>ColumnRecord</classname>，然后使用那些<classname>TreeModelColumns</classname>获取和设置模型列中的数据。你可能会发现，派生一个你自己的包含有<classname>TreeModelColumn</classname>数据成员的<classname>TreeModelColumnRecord</classname>会更方便。

en: You specify the <classname>ColumnRecord</classname> when creating the Model, like so:
zh_CN: 你可以在创建模型的时候指定<classname>ColumnRecord</classname>，如下所示：

en: As a <classname>TreeModelColumnRecord</classname> describes structure, not data, it can be shared among multiple models, and this is preferable for efficiency. However, the instance (such as <varname>m_Columns</varname> here) should usually not be static, because it often needs to be instantiated after <application>glibmm</application> has been initialized. The best solution is to make it a lazily instantiated singleton, so that it will be constructed on-demand, whenever the first model accesses it.
zh_CN: <classname>TreeModelColumnRecord</classname>描述的是结构而不是数据，它可以在多个模型之间共享，这样效率更高。但是实例（例如此处的<varname>m_Columns</varname>）通常不是静态的，因为通常需要在<application>glibmm</application>初始化后示例化它。最好的解决方案是使他成为惰性初始化的单例，以便在第一个模型访问他的时候按需构造。

en: Adding Rows
zh_CN: 添加行

en: Add rows to the model with the <methodname>append()</methodname>, <methodname>prepend()</methodname>, or <methodname>insert()</methodname> methods.
zh_CN: 使用<methodname>append()</methodname>、<methodname>prepend()</methodname>或<methodname>insert()</methodname>方法可以向模型添加行。

en: You can dereference the iterator to get the Row:
zh_CN: 你可以通过解引用迭代器获得行：

en: Adding child rows
zh_CN: 添加子行

en: <classname>Gtk::TreeStore</classname> models can have child items. Add them with the <methodname>append()</methodname>, <methodname>prepend()</methodname>, or <methodname>insert()</methodname> methods, like so:
zh_CN: <classname>Gtk::TreeStore</classname>模型可以存在子物件。可以通过<methodname>append()</methodname>、<methodname>prepend()</methodname>或<methodname>insert()</methodname>方法添加，如下所示：

en: Setting values
zh_CN: 设置值

en: You can use the <methodname>operator[]</methodname> overload to set the data for a particular column in the row, specifying the <classname>TreeModelColumn</classname> used to create the model.
zh_CN: 你可以使用<methodname>operator[]</methodname>重载设置行中的特定列的数据，你需要使用创建模型时的<classname>TreeModelColumn</classname>指定列。

en: Getting values
zh_CN: 获取值

en: You can use the <methodname>operator[]</methodname> overload to get the data in a particular column in a row, specifying the <classname>TreeModelColumn</classname> used to create the model.
zh_CN: 你可以使用<methodname>operator[]</methodname>重载获取行中特定列的数据，你需要使用创建模型时的<classname>TreeModelColumn</classname>指定列。

en: The compiler will complain if you use an inappropriate type. For instance, this would generate a compiler error:
zh_CN: 如果你使用了不合适的类型，编译器会报错。例如，编译器将生成一个编译错误：

en: "Hidden" Columns
zh_CN: “隐藏”列

en: You might want to associate extra data with each row. If so, just add it as a Model column, but don't add it to the View.
zh_CN: 你可能想要将额外的数据和每一行关联。如果是这样，你只需要将其添加到模型的一个行中而不将其添加到视图中即可。

en: The View
zh_CN: 视图

en: The View is the actual widget (<classname>Gtk::TreeView</classname>) that displays the model (<classname>Gtk::TreeModel</classname>) data and allows the user to interact with it. The View can show all of the model's columns, or just some, and it can show them in various ways.
zh_CN: 视图实际上是一个用于显示模型(<classname>Gtk::TreeModel</classname>)数据并允许用户与其交互的部件(<classname>Gtk::TreeView</classname>)。视图可以显示模型的所有列也可以只显示一部分列还可以以不同的方式显示列。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TreeView.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TreeView.html">参考</ulink>

en: Using a Model
zh_CN: 使用模型

en: You can specify a <classname>Gtk::TreeModel</classname> when constructing the <classname>Gtk::TreeView</classname>, or you can use the <methodname>set_model()</methodname> method, like so:
zh_CN: 你可以在构造<classname>Gtk::TreeView</classname>的时候为其指定一个<classname>Gtk::TreeModel</classname>，也可以构筑完成后使用<methodname>set_model()</methodname>方法指定，如下所示：

en: Adding View Columns
zh_CN: 为视图添加列

en: You can use the <methodname>append_column()</methodname> method to tell the View that it should display certain Model columns, in a certain order, with a certain column title.
zh_CN: 你可以使用<methodname>append_column()</methodname>方法告知视图以一定的顺序于某个列标题下显示模型的某个列。

en: When using this simple <methodname>append_column()</methodname> overload, the <classname>TreeView</classname> will display the model data with an appropriate <classname>CellRenderer</classname>. For instance, strings and numbers are shown in a simple <classname>Gtk::Entry</classname> widget, and booleans are shown in a <classname>Gtk::CheckButton</classname>. This is usually what you need. For other column types you must either connect a callback that converts your type into a string representation, with <methodname>TreeViewColumn::set_cell_data_func()</methodname>, or derive a custom <classname>CellRenderer</classname>. Note that (unsigned) short is not supported by default - You could use (unsigned) int or (unsigned) long as the column type instead.
zh_CN: 当使用这种简单的<methodname>append_column()</methodname>重载的时候，<classname>TreeView</classname>将会使用适当的<classname>CellRenderer</classname>显示模型数据。例如将字符串和数字显示在简单的<classname>Gtk::Entry</classname>部件中，布尔量使用<classname>Gtk::CheckButton</classname>显示。这通常是你所希望的行为。对于其他类型的行，你必须使用<methodname>TreeViewColumn::set_cell_data_func()</methodname>连接一个将你的类型转换为字符串表示形式的回调，或者是从<classname>CellRenderer</classname>派生一个合适的类。请注意，默认情况下<literal>(unsigned) short</literal>不被支持 - 作为替代你可以使用<literal>(unsigned) int</literal>或者<literal>(unsigned) long</literal>作为行类型。

en: More than one Model Column per View Column
zh_CN: 每个视图列不不止一个模型列

en: To render more than one model column in a view column, you need to create the <classname>TreeView::Column</classname> widget manually, and use <methodname>pack_start()</methodname> to add the model columns to it.
zh_CN: 要在一个视图列中呈现多个模型列，你需要手动创建<classname>TreeView::Column</classname>部件，并使用<methodname>pack_start()</methodname>方法向其添加模型列。

en: Then use <methodname>append_column()</methodname> to add the view Column to the View. Notice that <methodname>Gtk::TreeView::append_column()</methodname> is overloaded to accept either a prebuilt <classname>Gtk::TreeView::Column</classname> widget, or just the <classname>TreeModelColumn</classname> from which it generates an appropriate <classname>Gtk::TreeView::Column</classname> widget.
zh_CN: 然后使用<methodname>append_column()</methodname>将视图列添加到视图中。请注意，<methodname>Gtk::TreeView::append_column()</methodname>被重载为接受预建的<classname>Gtk::TreeView::Column</classname>部件，或者只接受由<classname>TreeModelColumn</classname>生成的合适的<classname>Gtk::TreeView::Column</classname>部件。

en: Here is some example code, which has a pixbuf icon and a text name in the same column:
zh_CN: 这是一些示例代码，在同一列中有一个像素缓冲区(pixbuf)图标和一个文本名：

en: Specifying CellRenderer details
zh_CN: 指定单元格渲染器(CellRenderer)详情

en: The default <classname>CellRenderers</classname> and their default behaviour will normally suffice, but you might occasionally need finer control. For instance, this example code from <filename>gtkmm/demos/gtk-demo/example_treeview_treestore.cc</filename>, appends a <classname>Gtk::CellRenderer</classname> widget and instructs it to render the data from various model columns through various aspects of its appearance.
zh_CN: 默认的<classname>CellRenderers</classname>及其默认行为通常已经足够好了，但是有时你需要更精细的控制它。例如来自<filename>gtkmm/demos/gtk-demo/example_treeview_treestore.cc</filename>的示例代码，附加一个<classname>Gtk::CellRenderer</classname>部件并指示其各个模型列的外观的各个方面来呈现数据。

en: You can also connect to <classname>CellRenderer</classname> signals to detect user actions. For instance:
zh_CN: 你还可以通过连接到<classname>CellRenderer</classname>的信号以检测用户的操作。例如：

en: Editable Cells
zh_CN: 可编辑单元格

en: Automatically-stored editable cells.
zh_CN: 自动储存的可编辑单元格

en: Cells in a <classname>TreeView</classname> can be edited in-place by the user. To allow this, use the <classname>Gtk::TreeView</classname> <methodname>insert_column_editable()</methodname> and <methodname>append_column_editable()</methodname> methods instead of <methodname>insert_column()</methodname> and <methodname>append_column()</methodname>. When these cells are edited the new values will be stored immediately in the Model. Note that these methods are templates which can only be instantiated for simple column types such as <classname>Glib::ustring</classname>, int, and long.
zh_CN: 用户可以就地编辑<classname>TreeView</classname>中的单元格。若要如此，请使用<classname>Gtk::TreeView</classname>的<methodname>insert_column_editable()</methodname>和<methodname>append_column_editable()</methodname>方法而不是<methodname>insert_column()</methodname>和<methodname>append_column()</methodname>方法。编辑单元格后新的值将立刻储存在模型中。请注意，这些方法是模版，只能为简单的列类型实例化（例如，<classname>Glib::ustring</classname>、<literal>int</literal>和<literal>long</literal>）。

en: Implementing custom logic for editable cells.
zh_CN: 为可编辑单元格实现自定义逻辑。

en: However, you might not want the new values to be stored immediately. For instance, maybe you want to restrict the input to certain characters or ranges of values.
zh_CN: 但是你可能不希望立刻储存新的值。例如你可能希望对输入进行检测，符合预期的范围才储存。

en: To achieve this, you should use the normal <classname>Gtk::TreeView</classname> <methodname>insert_column()</methodname> and <methodname>append_column()</methodname> methods, then use <methodname>get_column_cell_renderer()</methodname> to get the <classname>Gtk::CellRenderer</classname> used by that column.
zh_CN: 为此，你应该使用常规的<methodname>Gtk::TreeView::insert_column()</methodname>和<methodname>Gtk::TreeView::append_column()</methodname>方法，然后使用<methodname>get_column_cell_renderer()</methodname>方法获取该列使用的<classname>Gtk::CellRenderer</classname>。

en: You should then cast that <classname>Gtk::CellRenderer*</classname> to the specific <classname>CellRenderer</classname> that you expect, so you can use specific API.
zh_CN: 然后你应该讲<classname>Gtk::CellRenderer*</classname>转换为你期望的特定版本的<classname>CellRenderer</classname>（例如转换为<classname>CellRendererText</classname>，以便调用特定的API。

en: For instance, for a CellRendererText, you would set the cell's <emphasis>editable</emphasis> property to true, like so:
zh_CN: 例如，对于<classname>CellRendererText</classname>，你应该将单元格的<emphasis>editable</emphasis>属性设置为<literal>true</literal>，如下所示：

en: For a CellRendererToggle, you would set the <emphasis>activatable</emphasis> property instead.
zh_CN: 对于<classname>CellRendererToggle</classname>，你应该改为设置<emphasis>activatable</emphasis>属性。

en: You can then connect to the appropriate "edited" signal. For instance, connect to <methodname>Gtk::CellRendererText::signal_edited()</methodname>, or <methodname>Gtk::CellRendererToggle::signal_toggled()</methodname>. If the column contains more than one <classname>CellRenderer</classname> then you will need to use <methodname>Gtk::TreeView::get_column()</methodname> and then call <methodname>get_cells()</methodname> on that view Column.
zh_CN: 你可以连接到适当的"edited"信号。例如，连接到<methodname>Gtk::CellRendererText::signal_edited()</methodname>或者是<methodname>Gtk::CellRendererToggle::signal_toggled()</methodname>。如果该列包含多个<classname>CellRenderer</classname>，则你需要在视图上使用<methodname>Gtk::TreeView::get_column()</methodname>方法然后再调用<methodname>get_cells()</methodname>获取目标单元格。

en: In your signal handler, you should examine the new value and then store it in the Model if that is appropriate for your application.
zh_CN: 在你的信号处理函数中，你应该检查新值如果其对于你的应用程序而言是合适的则将其储存到你的模型中。

en: Iterating over Model Rows
zh_CN: 遍历模型行

en: <classname>Gtk::TreeModel</classname> provides a C++ Standard Library-style container of its children, via the <methodname>children()</methodname> method. You can use the familiar <methodname>begin()</methodname> and <methodname>end()</methodname> methods iterator incrementing, like so:
zh_CN: <classname>Gtk::TreeModel</classname>通过<methodname>children()</methodname>方法提供了标准C++容器库风格的子代迭代器。你可以使用熟悉的<methodname>begin()</methodname>和<methodname>end()</methodname>方法递增迭代器，如下所示：

en: If you always want to iterate across the entire range, much more succinct syntax is possible using C++'s range-based <literal>for</literal> loop:
zh_CN: 如果你总是想迭代整个范围，则可以使用C++基于范围的更简洁的<literal>for</literal>循环语法：

en: Row children
zh_CN: 子行

en: When using a <classname>Gtk::TreeStore</classname>, the rows can have child rows, which can have their own children in turn. Use <methodname>Gtk::TreeModel::Row::children()</methodname> to get the container of child <classname>Row</classname>s:
zh_CN: 在使用<classname>Gtk::TreeStore</classname>的时候，其行可以存在子行，子行也可以存在子行。使用<methodname>Gtk::TreeModel::Row::children()</methodname>方法可以获取<classname>Row</classname>的子行：

en: The Selection
zh_CN: 选择

en: To find out what rows the user has selected, get the <classname>Gtk::TreeView::Selection</classname> object from the <classname>TreeView</classname>, like so:
zh_CN: 要找出用户选择了那些行，请从<classname>TreeView</classname>的<classname>Gtk::TreeView::Selection</classname>对象获取。

en: Single or multiple selection
zh_CN: 单选或多选

en: By default, only single rows can be selected, but you can allow multiple selection by setting the mode, like so:
zh_CN: 默认情况下，只能选定一行，但是你可以通过设置选择模式选择多行，如下所示：

en: The selected rows
zh_CN: 选定的行

en: For single-selection, you can just call <methodname>get_selected()</methodname>, like so:
zh_CN: 对于单选模式，你可以如下所示调用<methodname>get_selected()</methodname>：

en: For multiple-selection, you need to call <methodname>get_selected_rows()</methodname> or define a callback, and give it to <methodname>selected_foreach()</methodname>, <methodname>selected_foreach_path()</methodname>, or <methodname>selected_foreach_iter()</methodname>, like so:
zh_CN: 对于多选模式，你需要调用<methodname>get_selected_rows()</methodname>或者定义一个回调然后将其传递给<methodname>selected_foreach()</methodname>、<methodname>selected_foreach_path()</methodname>或<methodname>selected_foreach_iter()</methodname>，如下所示：

en: The "changed" signal
zh_CN: "changed"信号

en: To respond to the user clicking on a row or range of rows, connect to the signal like so:
zh_CN: 要响应用户单击某行或者某个范围的行，请按以下方式连接信号：

en: Preventing row selection
zh_CN: 防止行被选择

en: Maybe the user should not be able to select every item in your list or tree. For instance, in the gtk-demo, you can select a demo to see the source code, but it doesn't make any sense to select a demo category.
zh_CN: 或许用户不应该能选择列表或树中的每个项目。例如在gtk-demo中，你可以选择一个演示来查看他的源代码，但是你选一个演示类别没有意义。

en: To control which rows can be selected, use the <methodname>set_select_function()</methodname> method, providing a <classname>sigc::slot</classname> callback. For instance:
zh_CN: 要控制一个行是否能被选择，请使用<methodname>set_select_function()</methodname>方法为其提供一个<classname>sigc::slot</classname>回调。例如：

en: and then
zh_CN: 接着

en: Changing the selection
zh_CN: 修改选择

en: To change the selection, specify a <classname>Gtk::TreeModel::iterator</classname> or <classname>Gtk::TreeModel::Row</classname>, like so:
zh_CN: 要更改选择，请指定<classname>Gtk::TreeModel::iterator</classname>或<classname>Gtk::TreeModel::Row</classname>，然后如下所示：

en: or
zh_CN: 或者

en: Sorting
zh_CN: 排序

en: The standard tree models (<classname>TreeStore</classname> and <classname>ListStore</classname>) derive from <classname>TreeSortable</classname>, so they offer sorting functionality. For instance, call <methodname>set_sort_column()</methodname>, to sort the model by the specified column. Or supply a callback function to <methodname>set_sort_func()</methodname> to implement a more complicated sorting algorithm.
zh_CN: 标准树模型（<classname>TreeStore</classname>和<classname>ListStore</classname>）派生自<classname>TreeSortable</classname>，因此它们提供了排序功能。例如，调用<methodname>set_sort_column()</methodname>按指定的列对模型进行排序。或者向<methodname>set_sort_func()</methodname>提供一个回调函数以实现更复杂的排序算法。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TreeSortable.html">TreeSortable Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TreeSortable.html">可排序树参考</ulink>

en: Sorting by clicking on columns
zh_CN: 单击列进行排序

en: So that a user can click on a <classname>TreeView</classname>'s column header to sort the <classname>TreeView</classname>'s contents, call <methodname>Gtk::TreeView::Column::set_sort_column()</methodname>, supplying the model column on which model should be sorted when the header is clicked. For instance:
zh_CN: 为了使用户可以点击<classname>TreeView</classname>的列标题以对<classname>TreeView</classname>内容进行排序，请在需要此功能的列上调用<methodname>Gtk::TreeView::Column::set_sort_column()</methodname>，以提供此功能。如下所示：

en: Independently sorted views of the same model
zh_CN: 对同一模型进行独立排序的视图

en: The <classname>TreeView</classname> already allows you to show the same <classname>TreeModel</classname> in two <classname>TreeView</classname> widgets. If you need one of these TreeViews to sort the model differently than the other then you should use a <classname>TreeModelSort</classname> instead of just, for instance, <methodname>Gtk::TreeViewColumn::set_sort_column()</methodname>. <classname>TreeModelSort</classname> is a model that contains another model, presenting a sorted version of that model. For instance, you might add a sorted version of a model to a <classname>TreeView</classname> like so:
zh_CN: <classname>TreeView</classname>可以让你用两个<classname>TreeView</classname>部件显示同一个<classname>TreeModel</classname>。如果你需要让这这些树形视图对模型进行不同的排序，则你应该使用<classname>TreeModelSort</classname>而不仅仅是使用<methodname>Gtk::TreeViewColumn::set_sort_column()</methodname>。<classname>TreeModelSort</classname>是一个包含其他模型的模型，其提供了该模型的将已排序版本。你可以如下所示的将已排序版本模型添加到<classname>TreeView</classname>：

en: Note, however, that the TreeView will provide iterators to the sorted model. You must convert them to iterators to the underlying child model in order to perform actions on that model. For instance:
zh_CN: 请注意，这样做树形视图将会提供已排序模型的迭代器。你必须将其转换为基础的子模型迭代器以便对这个模型进行操作。例如：

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TreeModelSort.html">TreeModelSort Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TreeModelSort.html">树模型排序参考</ulink>

en: Drag and Drop
zh_CN: 拖放

en: <classname>Gtk::TreeView</classname> already implements simple drag-and-drop when used with the <classname>Gtk::ListStore</classname> or <classname>Gtk::TreeStore</classname> models. If necessary, it also allows you to implement more complex behaviour when items are dragged and dropped, using the normal <link linkend="chapter-draganddrop">Drag and Drop</link> API.
zh_CN: 当使用<classname>Gtk::ListStore</classname>或者<classname>Gtk::TreeStore</classname>模型时<classname>Gtk::TreeView</classname>已经实现了简单的拖放。如果有必要，它还允许你使用常规的<link linkend="chapter-draganddrop">拖放</link>API实现更复杂的拖放行为。

en: Reorderable rows
zh_CN: 可重排序的行

en: If you call <methodname>Gtk::TreeView::set_reorderable()</methodname> then your TreeView's items can be moved within the treeview itself. This is demonstrated in the <classname>TreeStore</classname> example.
zh_CN: 如果调用<methodname>Gtk::TreeView::set_reorderable()</methodname>则你可以在树视图中移动其本身的项目。<classname>TreeStore</classname>的示例对此进行了演示。

en: However, this does not allow you any control of which items can be dragged, and where they can be dropped. If you need that extra control then you might create a derived <literal>Gtk::TreeModel</literal> from <literal>Gtk::TreeStore</literal> or <literal>Gtk::ListStore</literal> and override the <literal>Gtk::TreeDragSource::row_draggable_vfunc()</literal> and <literal>Gtk::TreeDragDest::row_drop_possible_vfunc()</literal> virtual methods. You can examine the <literal>Gtk::TreeModel::Path</literal>s provided and allow or disallow dragging or dropping by returning <literal>true</literal> or <literal>false</literal>.
zh_CN: 但是，这不允许你控制哪些项目可以拖动以及可以将他们拖动到哪里。如果你想做到这些，你需要从<literal>Gtk::TreeStore</literal>或<literal>Gtk::ListStore</literal>创建派生的<literal>Gtk::TreeModel</literal>，然后覆盖<literal>Gtk::TreeDragSource::row_draggable_vfunc()</literal>和<literal>Gtk::TreeDragDest::row_drop_possible_vfunc()</literal>虚方法。你可以检查提供的<literal>Gtk::TreeModel::Path</literal>并返回<literal>true</literal>或<literal>false</literal>来允许或禁止拖放。

en: This is demonstrated in the drag_and_drop example.
zh_CN: 在drag_and_drop示例中对此进行了演示。

en: Popup Context Menu
zh_CN: 弹出上下文菜单

en: Lots of people need to implement right-click context menus for <classname>TreeView</classname>'s so we will explain how to do that here to save you some time. Apart from one or two points, it's much the same as a normal context menu, as described in the <link linkend="sec-menus-popup">menus chapter</link>.
zh_CN: 很多人认为需要为<classname>TreeView</classname>实现右键单击上下文菜单，因此我们在这里说明如何做到这个以节省你的时间。其与普通的上下文菜单只有一两点不同，如<link linkend="sec-menus-popup">菜单章节</link>所述。

en: Handling <literal>button_press_event</literal>
zh_CN: 处理<literal>button_press_event</literal>

en: To detect a click of the right mouse button, you need to handle the <literal>button_press_event</literal> signal, and check exactly which button was pressed. Because the <classname>TreeView</classname> normally handles this signal completely, you need to either override the default signal handler in a derived <classname>TreeView</classname> class, use <methodname>connect_notify()</methodname> or use <methodname>connect(slot, /* after= */ false)</methodname>. You probably also want to call the default handler before doing anything else, so that the right-click will cause the row to be selected first.
zh_CN: 要检测鼠标右键的点击，你需要处理<literal>button_press_event</literal>信号，并准确的检查按下了哪个按钮。因为<classname>TreeView</classname>通常会处理这个信号，所以你需要使用<methodname>connect_notify()</methodname>或<methodname>connect(slot, /* after= */ false)</methodname>在<classname>TreeView</classname>的派生类中覆盖默认信号处理函数。你可能还想在执行任何其他操作之前先调用默认信号处理函数，以便右键时先选择该行。

en: This is demonstrated in the Popup Context Menu example.
zh_CN: Popup Context Menu示例中对此进行了演示。

en: Examples
zh_CN: 示例

en: Some <classname>TreeView</classname> examples are shown here. There are more examples in the <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/">treeview directory</ulink> in <application>gtkmm-documentation</application>'s examples.
zh_CN: 这里显示了一些<classname>TreeView</classname>的示例。<application>gtkmm文档</application>示例中的<ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/">树形视图文件夹</ulink>还有更多的示例。

en: If neither <classname>ListStore</classname> nor <classname>TreeStore</classname> is suitable for your application, look at the <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/custom_treemodel">custom TreeModel</ulink> example. It shows how you can make your own implementation of the <classname>TreeModel</classname> interface.
zh_CN: 如果<classname>ListStore</classname>和<classname>TreeStore</classname>都不适合你的应用程序，请查看<ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/custom_treemodel">自定义树模型</ulink>示例。它向你展示了如何实现自己的<classname>TreeModel</classname>接口

en: ListStore
zh_CN: 列表储存(ListStore)

en: This example has a <classname>Gtk::TreeView</classname> widget, with a <classname>Gtk::ListStore</classname> model.
zh_CN: 这个例子有一个使用<classname>Gtk::ListStore</classname>模型的<classname>Gtk::TreeView</classname>部件。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/list/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/list/">源代码</ulink>

en: TreeStore
zh_CN: 树储存(TreeStore)

en: This example is very similar to the <classname>ListStore</classname> example, but uses a <classname>Gtk::TreeStore</classname> model instead, and adds children to the rows.
zh_CN: 这个示例和<classname>ListStore</classname>示例非常的相似，但是使用的是<classname>Gtk::TreeStore</classname>模型并且添加了子行。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/tree/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/tree/">源代码</ulink>

en: This example is identical to the <classname>ListStore</classname> example, but it uses <methodname>TreeView::append_column_editable()</methodname> instead of <methodname>TreeView::append_column()</methodname>.
zh_CN: 这个示例与<classname>ListStore</classname>示例相同，但是使用<methodname>TreeView::append_column_editable()</methodname>代替<methodname>TreeView::append_column()</methodname>。

en: TreeView - Editable Cells
zh_CN: 树形视图 - 可编辑单元格

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/editable_cells/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/editable_cells/">源代码</ulink>

en: This example is much like the <classname>TreeStore</classname> example, but has 2 extra columns to indicate whether the row can be dragged, and whether it can receive drag-and-dropped rows. It uses a derived <classname>Gtk::TreeStore</classname> which overrides the virtual functions as described in the <link linkend="sec-treeview-draganddrop">TreeView Drag and Drop</link> section.
zh_CN: 这个示例和<classname>TreeStore</classname>示例十分相似，但是额外有两个用于指示行是否可以进行拖放和接受拖放的列。它通过从<classname>Gtk::TreeStore</classname>来覆盖虚函数，如<link linkend="sec-treeview-draganddrop">拖放树视图</link>小节所述。

en: TreeView - Drag And Drop
zh_CN: 树形视图 - 拖放

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/drag_and_drop/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/drag_and_drop/">源代码</ulink>

en: This example is much like the <classname>ListStore</classname> example, but derives a custom <classname>TreeView</classname> in order to override the <literal>button_press_event</literal>, and also to encapsulate the tree model code in our derived class. See the <link linkend="sec-treeview-contextmenu">TreeView Popup Context Menu</link> section.
zh_CN: 这个示例和<classname>ListStore</classname>示例十分相似，但是它牌手了一个自定义的<classname>TreeView</classname>以覆盖<literal>button_press_event</literal>，并将树模型代码封装在派生类代码中，请参阅<link linkend="sec-treeview-contextmenu">树形视图弹出上下文菜单</link>小节。

en: TreeView - Popup Context Menu
zh_CN: 树形视图 - 弹出上下文菜单

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/popup/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/treeview/popup/">源代码</ulink>

en: Combo Boxes
zh_CN: 组合框(Combo Boxes)

en: The <classname>ComboBox</classname> widget offers a list (or tree) of choices in a dropdown menu. If appropriate, it can show extra information about each item, such as text, a picture, a check button, or a progress bar. The <classname>ComboBox</classname> widget usually restricts the user to the available choices, but it can optionally have an <classname>Entry</classname>, allowing the user to enter arbitrary text if none of the available choices are suitable.
zh_CN: <classname>ComboBox</classname>部件在下拉菜单中提供了选项列表（或树）。如果需要它可以为每个项目显示额外的信息，例如文本、图片、复选按钮或是进度条。<classname>ComboBox</classname>部件通常将显示用户的可选项，但是它可以有一个<classname>Entry</classname>以允许用户在没有合适的选项的时候输入任意文本。

en: The list is provided via a <classname>TreeModel</classname>, and columns from this model are added to the ComboBox's view with the <methodname>ComboBox::pack_start()</methodname> method. This provides flexibility and compile-time type-safety, but the <classname>ComboBoxText</classname> class provides a simpler text-based specialization in case that flexibility is not required.
zh_CN: 这个列表通过<classname>TreeModel</classname>提供，这个模型的列通过<methodname>ComboBox::pack_start()</methodname>方法添加到组合框的视图中。这提供了灵活性和编译时的类型安全，在不需要灵活性的情况下，<classname>ComboBoxText</classname>类提供了更简单的基于文本的特化支持。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ComboBox.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ComboBox.html">参考</ulink>

en: The model
zh_CN: 模型

en: The model for a ComboBox can be defined and filled exactly as for a <classname>TreeView</classname>. For instance, you might derive a ComboBox class with one integer and one text column, like so:
zh_CN: 可以像<classname>TreeView</classname>一样定义和填充组合框的模型。你可以与如下所示的一样派生具有一个整数行和一个文本行的组合框类：

en: After appending rows to this model, you should provide the model to the <classname>ComboBox</classname> with the <methodname>set_model()</methodname> method. Then use the <methodname>pack_start()</methodname> or <methodname>pack_end()</methodname> methods to specify what columns will be displayed in the ComboBox. As with the TreeView you may either use the default cell renderer by passing the <classname>TreeModelColumn</classname> to the pack methods, or you may instantiate a specific <classname>CellRenderer</classname> and specify a particular mapping with either <methodname>add_attribute()</methodname> or <methodname>set_cell_data_func()</methodname>. Note that these methods are in the <classname>CellLayout</classname> base class.
zh_CN: 将行追加到此模型中后，你应该使用<methodname>set_model()</methodname>方法将模型提供给<classname>ComboBox</classname>。然后使用<methodname>pack_start()</methodname>或<methodname>pack_end()</methodname>方法指定哪个行将要被组合框显示。和树状视图一样，你可以通过将<classname>TreeModelColumn</classname>传递给pack方法来使用默认的单元格渲染器，也可以实例化一个特定的<classname>CellRenderer</classname>并使用<methodname>add_attribute()</methodname>或<methodname>set_cell_data_func()</methodname>指定具体映射到哪行。请注意这些方法在<classname>CellLayout</classname>基类中。

en: The chosen item
zh_CN: 所选项

en: To discover what item, if any, the user has chosen from the ComboBox, call <methodname>ComboBox::get_active()</methodname>. This returns a <classname>TreeModel::iterator</classname> that you can dereference to a <classname>Row</classname> in order to read the values in your columns. For instance, you might read an integer ID value from the model, even though you have chosen only to show the human-readable description in the ComboBox. For instance:
zh_CN: 要了解用户从组合框中选择了哪一项可以调用<methodname>ComboBox::get_active()</methodname>。这将返回一个<classname>TreeModel::iterator</classname>，你可以解引用它得到一个<classname>Row</classname>，然后从其中读取该列的值。例如，你可以在组合框中只显示人类可读的描述，然后你可以读取模型中储存于该行的整数ID值（于并未被显示的列）。例如：

en: Responding to changes
zh_CN: 响应变更

en: You might need to react to every change of selection in the ComboBox, for instance to update other widgets. To do so, you should handle the <literal>changed</literal> signal. For instance:
zh_CN: 你可能需要对组合框中每个选择的变更进行响应，例如更新其他的部件。为此你应该处理<literal>changed</literal>。例如：

en: Full Example
zh_CN: 完整例子

en: ComboBox
zh_CN: 组合框(ComboBox)

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/combobox/complex">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/combobox/complex">源代码</ulink>

en: Simple Text Example
zh_CN: 简单文字示例

en: ComboBoxText
zh_CN: 文本组合框(ComboBoxText)

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/combobox/text">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/combobox/text">源代码</ulink>

en: ComboBox with an Entry
zh_CN: 带有条目的组合框

en: A <classname>ComboBox</classname> may contain an <classname>Entry</classname> widget for entering of arbitrary text, by specifying <literal>true</literal> for the constructor's <literal>has_entry</literal> parameter.
zh_CN: 通过指定<classname>ComboBox</classname>构造函数的<literal>has_entry</literal>参数为<literal>true</literal>，可以令其包含一个<classname>Entry</classname>部件用以输入任意文本。

en: The text column
zh_CN: 文本列

en: So that the <classname>Entry</classname> can interact with the drop-down list of choices, you must specify which of your model columns is the text column, with <methodname>set_entry_text_column()</methodname>. For instance:
zh_CN: 为了使<classname>Entry</classname>可以与下拉列表的选项进行交互，你必须使用<methodname>set_entry_text_column()</methodname>指定哪些模型列是文本列。例如：

en: When you select a choice from the drop-down menu, the value from this column will be placed in the <classname>Entry</classname>.
zh_CN: 当你从下拉菜单中选择一个选项的时候，该列的值将被放于<classname>Entry</classname>中。

en: The entry
zh_CN: 条目

en: Because the user may enter arbitrary text, an active model row isn't enough to tell us what text the user has entered. Therefore, you should retrieve the <classname>Entry</classname> widget with the <methodname>ComboBox::get_entry()</methodname> method and call <methodname>get_text()</methodname> on that.
zh_CN: 由于用户可以输入任意文本，被使用中的模型行可能不足以告诉我们用户输入了什么，因此，你应该使用<methodname>ComboBox::get_entry()</methodname>方法检索组合框中的<classname>Entry</classname>部件并在其上调用<methodname>get_text()</methodname>。

en: When the user enters arbitrary text, it may not be enough to connect to the <literal>changed</literal> signal, which is emitted for every typed character. It is not emitted when the user presses the <keycap>Enter</keycap> key. Pressing the <keycap>Enter</keycap> key or moving the keyboard focus to another widget may signal that the user has finished entering text. To be notified of these events, connect to the <classname>Entry</classname>'s <literal>activate</literal> and <literal>focus_out_event</literal> signals, like so <_:programlisting-1/> The <literal>changed</literal> signals of <classname>ComboBox</classname> and <classname>Entry</classname> are both emitted for every change. It doesn't matter which one you connect to. But only <classname>Entry</classname>'s <literal>focus_out_event</literal> signal is useful here.
zh_CN: 当用户输入任意文本时，只连接到为每个键入字符而发出的<literal>changed</literal>信号可能是不够的。当用户按下<keycap>Enter</keycap>键的时候，这个信号不会被发出。而按下<keycap>Enter</keycap>或是键盘焦点被移动到另一个部件的时候，可以表示用户已经完成了输入。为了收到这些事件的通知，你需要连接到<classname>Entry</classname>的<literal>activate</literal>和<literal>focus_out_event</literal>信号像是这样<_:programlisting-1/> 每次更改<classname>ComboBox</classname>和<classname>Entry</classname>都会发出<literal>changed</literal>信号，你可以连接它们中的任意一个。但是在这里只有<classname>Entry</classname>的<literal>focus_out_event</literal>信号才有用。

en: X events are described in more detail in the <link linkend="sec-xeventsignals">X Event signals</link> section in the appendix.
zh_CN: X事件在附录的<link linkend="sec-xeventsignals">X事件信号</link>小节有更详细的描述。

en: ComboBox with Entry
zh_CN: 带条目的组合框

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/combobox/entry_complex">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/combobox/entry_complex">源代码</ulink>

en: ComboBoxText with Entry
zh_CN: 带条目的文本组合框

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/combobox/entry_text">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/combobox/entry_text">源代码</ulink>

en: TextView
zh_CN: 文本视图(TextView)

en: The <classname>TextView</classname> widget can be used to display and edit large amounts of formatted text. Like the <classname>TreeView</classname>, it has a model/view design. In this case the <classname>TextBuffer</classname> is the model.
zh_CN: <classname>TextView</classname>部件可以用于显示和编辑大量的格式化文本。与<classname>TreeView</classname>一样，它具有模型/视图设计。<classname>TextBuffer</classname>是它预期的模型。

en: The Buffer
zh_CN: 缓冲区

en: <classname>Gtk::TextBuffer</classname> is a model containing the data for the <classname>Gtk::TextView</classname>, like the <classname>Gtk::TreeModel</classname> used by <classname>Gtk::TreeView</classname>. This allows two or more <classname>Gtk::TextView</classname>s to share the same <classname>TextBuffer</classname>, and allows those TextBuffers to be displayed slightly differently. Or you could maintain several <classname>Gtk::TextBuffer</classname>s and choose to display each one at different times in the same <classname>Gtk::TextView</classname> widget.
zh_CN: <classname>Gtk::TextBuffer</classname>是一个包含<classname>Gtk::TextView</classname>数据的模型，和<classname>Gtk::TreeView</classname>所使用的<classname>Gtk::TreeModel</classname>类似。这允许复数个<classname>Gtk::TextView</classname>共享同一个<classname>TextBuffer</classname>，并允许以不同方式显示文本缓冲区。你也可以维护多个<classname>Gtk::TextBuffer</classname>并让同一个<classname>Gtk::TextView</classname>部件于不同时候分别显示它们。

en: The <classname>TextView</classname> creates its own default <classname>TextBuffer</classname>, which you can access via the <methodname>get_buffer()</methodname> method.
zh_CN: <classname>TextView</classname>会创建一个由它拥有的默认<classname>TextBuffer</classname>，你可以通过<methodname>get_buffer()</methodname>方法访问这个缓冲区。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextBuffer.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextBuffer.html">参考</ulink>

en: Iterators
zh_CN: 迭代器

en: A <classname>Gtk::TextBuffer::iterator</classname> and a <classname>Gtk::TextBuffer::const_iterator</classname> represent a position between two characters in the text buffer. Whenever the buffer is modified in a way that affects the number of characters in the buffer, all outstanding iterators become invalid. Because of this, iterators can't be used to preserve positions across buffer modifications. To preserve a position, use <classname>Gtk::TextBuffer::Mark</classname>.
zh_CN: <classname>Gtk::TextBuffer::iterator</classname>和<classname>Gtk::TextBuffer::const_iterator</classname>表示文本缓冲区中两个字符之间的位置。只要以影响缓冲区中字符数量的方式修改了缓冲区，所有越过修改范围的迭代器都将失效。因此，迭代器不能用于保存越过缓冲区被修改部分的位置。如果想保存位置，请使用<classname>Gtk::TextBuffer::Mark</classname>。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextIter.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextIter.html">参考</ulink>

en: Tags and Formatting
zh_CN: 标签和格式

en: Tags
zh_CN: 标签(Tags)

en: To specify that some text in the buffer should have specific formatting, you must define a tag to hold that formatting information, and then apply that tag to the region of text. For instance, to define the tag and its properties:
zh_CN: 要指定缓冲区中的一些文本具有特定的格式，你需要定义一个标签来保存格式信息，并将该标签应用于文本区域。例如，定义标签及其属性：

en: You can specify a name for the <classname>Tag</classname> when using the <methodname>create()</methodname> method, but it is not necessary.
zh_CN: 你可以在使用<classname>Tag</classname>的<methodname>create()</methodname>方法时为其指定一个名称，但这不是必须的。

en: The <classname>Tag</classname> class has many other properties.
zh_CN: <classname>Tag</classname>类还有许多其他的特性。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextTag.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextTag.html">参考</ulink>

en: TagTable
zh_CN: 标签表(TagTable)

en: Each <classname>Gtk::TextBuffer</classname> uses a <classname>Gtk::TextBuffer::TagTable</classname>, which contains the <classname>Tag</classname>s for that buffer. 2 or more <classname>TextBuffer</classname>s may share the same <classname>TagTable</classname>. When you create <classname>Tag</classname>s you should add them to the <classname>TagTable</classname>. For instance:
zh_CN: 每个<classname>Gtk::TextBuffer</classname>使用一个<classname>Gtk::TextBuffer::TagTable</classname>，其中包含了该缓冲区的<classname>Tag</classname>。复数个<classname>TextBuffer</classname>可以共享一个<classname>TagTable</classname>。当你创建<classname>Tag</classname>的时候，你应该将其加入<classname>TagTable</classname>。例如：

en: You can also use <methodname>get_tag_table()</methodname> to get, and maybe modify, the <classname>TextBuffer</classname>'s default <classname>TagTable</classname> instead of creating one explicitly.
zh_CN: 你也可以使用<methodname>get_tag_table()</methodname>获取并修改<classname>TextBuffer</classname>的默认<classname>TagTable</classname>，而不是显示创建一个。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextTagTable.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextTagTable.html">参考</ulink>

en: Applying Tags
zh_CN: 应用标签

en: If you have created a <classname>Tag</classname> and added it to the <classname>TagTable</classname>, you may apply that tag to part of the <classname>TextBuffer</classname> so that some of the text is displayed with that formatting. You define the start and end of the range of text by specifying <classname>Gtk::TextBuffer::iterator</classname>s. For instance:
zh_CN: 如果你创建了一个<classname>Tag</classname>并将其加入到<classname>TagTable</classname>，则可以将其应用于<classname>TextBuffer</classname>的一部分，以便使用该格式显示某些文本。你可以通过使用<classname>Gtk::TextBuffer::iterator</classname>指示文本的开始和结束范围。例如：

en: Or you could specify the tag when first inserting the text:
zh_CN: 或者你可以在首次插入文本的时候指定标签：

en: You can apply more than one <classname>Tag</classname> to the same text, by using <methodname>apply_tag()</methodname> more than once, or by using <methodname>insert_with_tags()</methodname>. The <classname>Tag</classname>s might specify different values for the same properties, but you can resolve these conflicts by using <methodname>Tag::set_priority()</methodname>.
zh_CN: 你可以多次使用<methodname>apply_tag()</methodname>或<methodname>insert_with_tags()</methodname>将不同的<classname>Tag</classname>应用于同一文本。<classname>Tag</classname>可能会为同一属性指定不同的值，但你可以使用<methodname>Tag::set_priority()</methodname>解决这些冲突。

en: Marks
zh_CN: 标记(Marks)

en: <classname>TextBuffer</classname> iterators are generally invalidated when the text changes, but you can use a <classname>Gtk::TextBuffer::Mark</classname> to remember a position in these situations. For instance,
zh_CN: 当文本发生更改的时候<classname>TextBuffer</classname>迭代器通常会失效，但是你可以使用<classname>Gtk::TextBuffer::Mark</classname>记住位置，例如：

en: You can then use the <methodname>get_iter()</methodname> method later to create an iterator for the <classname>Mark</classname>'s new position.
zh_CN: 你可以在之后使用<methodname>get_iter()</methodname>方法为<classname>Mark</classname>的新位置创建迭代器。

en: There are two built-in <classname>Mark</classname>s - <literal>insert</literal> and <literal>selection_bound</literal>, which you can access with <classname>TextBuffer</classname>'s <methodname>get_insert()</methodname> and <methodname>get_selection_bound()</methodname> methods.
zh_CN: 有两个内置的<classname>Mark</classname> - <literal>insert</literal>和<literal>selection_bound</literal>，你可以使用<classname>TextBuffer</classname>的<methodname>get_insert()</methodname>和<methodname>get_selection_bound()</methodname>方法访问它们。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextMark.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextMark.html">参考</ulink>

en: As mentioned above, each <classname>TextView</classname> has a <classname>TextBuffer</classname>, and one or more <classname>TextView</classname>s can share the same <classname>TextBuffer</classname>.
zh_CN: 如上所述，每个<classname>TextView</classname>都有一个<classname>TextBuffer</classname>，并且多个<classname>TextView</classname>可以共享同一个<classname>TextBuffer</classname>。

en: Like the <classname>TreeView</classname>, you should probably put your <classname>TextView</classname> inside a <classname>ScrolledWindow</classname> to allow the user to see and move around the whole text area with scrollbars.
zh_CN: 和<classname>TreeView</classname>一样，你可以将<classname>TextView</classname>放入<classname>ScrolledWindow</classname>中以允许用户使用滚动条查看并在整个文本区域中移动。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextView.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextView.html">参考</ulink>

en: Default formatting
zh_CN: 默认格式

en: <classname>TextView</classname> has various methods which allow you to change the presentation of the buffer for this particular view. Some of these may be overridden by the <classname>Gtk::TextTag</classname>s in the buffer, if they specify the same things. For instance, <methodname>set_left_margin()</methodname>, <methodname>set_right_margin()</methodname>, <methodname>set_indent()</methodname>, etc.
zh_CN: <classname>TextView</classname>具有多种可以让你修改特定视图中缓冲区的显示方式的方法。如果它们指定同一区域，则其中一些可能会覆写缓冲区中的<classname>Gtk::TextTag</classname>。例如：<methodname>set_left_margin()</methodname>、<methodname>set_right_margin()</methodname>、<methodname>set_indent()</methodname>等。

en: Scrolling
zh_CN: 滚动

en: <classname>Gtk::TextView</classname> has various <methodname>scroll_to()</methodname> methods. These allow you to ensure that a particular part of the text buffer is visible. For instance, your application's Find feature might use <methodname>Gtk::TextView::scroll_to()</methodname> to show the found text.
zh_CN: <classname>Gtk::TextView</classname>有多种<methodname>scroll_to()</methodname>方法。这些可以确保你能看到缓冲区中的特定部分。例如你的应用程序可能会使用<methodname>Gtk::TextView::scroll_to()</methodname>方法显示找到的文本。

en: Widgets and ChildAnchors
zh_CN: 部件和子锚(ChildAnchors)

en: You can embed widgets, such as <classname>Gtk::Button</classname>s, in the text. Each such child widget needs a <classname>ChildAnchor</classname>. ChildAnchors are associated with <classname>iterators</classname>. For instance, to create a child anchor at a particular position, use <methodname>Gtk::TextBuffer::create_child_anchor()</methodname>:
zh_CN: 你可以在文本中嵌入小部件，例如<classname>Gtk::Button</classname>。每一个这样的子部件都需要一个<classname>ChildAnchor</classname>。子锚与迭代器相关联。例如，使用<methodname>Gtk::TextBuffer::create_child_anchor()</methodname>于特定位置创建子锚：

en: Then, to add a widget at that position, use <methodname>Gtk::TextView::add_child_at_anchor()</methodname>:
zh_CN: 然后使用<methodname>Gtk::TextView::add_child_at_anchor()</methodname>将部件添加到该位置：

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextChildAnchor.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1TextChildAnchor.html">参考</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/textview/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/textview/">源代码</ulink>

en: Menus and Toolbars
zh_CN: 菜单和工具栏

en: There are specific APIs for menus and toolbars, but you should usually deal with them together, creating <classname>Gio::SimpleAction</classname>s that you can refer to in both menus and toolbars. In this way you can handle activation of the action instead of responding to the menu and toolbar items separately. And you can enable or disable both the menu and toolbar item via the action. <classname>Gtk::Builder</classname> can create menus and toolbars.
zh_CN: 菜单和工具栏都有特有的API，但是通常你应该创建在菜单和工具栏都可以引用的<classname>Gio::SimpleAction</classname>以便一并处理它们。这样你可以响应动作被激活而不需要分别响应菜单和工具栏。你可以通过动作启用或者禁用菜单和工具栏项。<classname>Gtk::Builder</classname>可以创建菜单和工具栏。

en: This involves the use of the <classname>Gio::SimpleActionGroup</classname>, <classname>Gio::SimpleAction</classname> and <classname>Gtk::Builder</classname> classes, all of which should be instantiated via their <methodname>create()</methodname> methods, which return <classname>RefPtr</classname>s.
zh_CN: 这涉及到了<classname>Gio::SimpleActionGroup</classname>、<classname>Gio::SimpleAction</classname>和<classname>Gtk::Builder</classname>类的使用，所有的这些类都需要通过返回<classname>RefPtr</classname>的<methodname>create()</methodname>方法进行实例化。

en: Actions
zh_CN: 动作(Actions)

en: First create the <classname>Gio::SimpleAction</classname>s and add them to a <classname>Gio::SimpleActionGroup</classname>, with <methodname>Gio::ActionMap::add_action()</methodname>. (<classname>Gio::ActionMap</classname> is a base class of <classname>Gio::SimpleActionGroup</classname>.) Then add the action group to your window with <methodname>Gtk::Widget::insert_action_group()</methodname>.
zh_CN: 首先创建<classname>Gio::SimpleAction</classname>并使用<methodname>Gio::ActionMap::add_action()</methodname>方法将其加入<classname>Gio::SimpleActionGroup</classname>中（<classname>Gio::ActionMap</classname>是<classname>Gio::SimpleActionGroup</classname>的基类。）。然后将动作组使用<methodname>Gtk::Widget::insert_action_group()</methodname>加入到你的窗口中。

en: The arguments to <methodname>add_action()</methodname> specify the action's name, which is used in the menu items and toolbar buttons. You can also specify a signal handler when calling <methodname>add_action()</methodname>. This signal handler will be called when the action is activated via either a menu item or a toolbar button.
zh_CN: <methodname>add_action()</methodname>的参数用于指定动作名，该名称由菜单项和工具栏按钮使用。你还可以在调用<methodname>add_action()</methodname>时指定信号处理函数。在菜单项或工具栏按钮被激活的时候此信号处理函数被调用。

en: For instance:
zh_CN: 例如：

en: If you use an <classname>Gtk::ApplicationWindow</classname>, you don't have to create your own action group. <classname>Gio::ActionGroup</classname> and <classname>Gio::ActionMap</classname> are base classes of <classname>Gtk::ApplicationWindow</classname>.
zh_CN: 如果你使用<classname>Gtk::ApplicationWindow</classname>，则你不需要自己创建动作组。因为<classname>Gio::ActionGroup</classname>和<classname>Gio::ActionMap</classname>是<classname>Gtk::ApplicationWindow</classname>的基类。

en: Menubar and Toolbar
zh_CN: 菜单和工具栏

en: Next you should create a <classname>Gtk::Builder</classname>. At this point is also a good idea to tell the application to respond to keyboard shortcuts, by using <methodname>Gtk::Application::set_accel_for_action()</methodname>.
zh_CN: 接下来你应该创建一个<classname>Gtk::Builder</classname>。此时使用<methodname>Gtk::Application::set_accel_for_action()</methodname>告诉应用程序响应键盘快捷键也是一个好主意。

en: For instance,
zh_CN: 例如：

en: If your main window is derived from <classname>ApplicationWindow</classname> and you instantiate your menubar with <methodname>Gtk::Application::set_menubar()</methodname>, then you don't have to call <methodname>set_accel_for_action()</methodname>. See <link linkend="menu-example-main">Application Menu and Main Menu example</link> for an example.
zh_CN: 如果你的主窗口是由<classname>ApplicationWindow</classname>派生而来的，并且你使用<methodname>Gtk::Application::set_menubar()</methodname>实例化了菜单栏，则你不需要调用<methodname>set_accel_for_action()</methodname>。有关示例参见：<link linkend="menu-example-main">应用程序菜单和主菜单示例</link>。

en: Then, you can define the actual visible layout of the menus and toolbars, and add the UI layout to the <classname>Builder</classname>. This "ui string" uses an XML format, in which you should mention the names of the actions that you have already created. For instance:
zh_CN: 然后，你可以定义菜单和工具栏的实际可见布局，并将这个UI布局添加到<classname>Builder</classname>。这个"UI字符串"使用XML格式，你应该在其中使用你已经创建的动作的名称。例如：

en: This is where we specify the names of the menu items as they will be seen by users in the menu. Therefore, this is where you should make strings translatable, by adding <literal>translatable='yes'</literal>.
zh_CN: 这里我们指定菜单项的名称，因为用户可以在菜单中看到它们。因此你应该添加<literal>translatable='yes'</literal>使这些的字符串可以被翻译。

en: To instantiate a <classname>Gtk::MenuBar</classname> and <classname>Gtk::Toolbar</classname> which you can actually show, you should use the <methodname>Builder::get_object()</methodname> and <methodname>Builder::get_widget()</methodname> methods, and then add the widgets to a container. For instance:
zh_CN: 要实例化<classname>Gtk::MenuBar</classname>和<classname>Gtk::Toolbar</classname>并可以实际显示他们，应该使用<methodname>Builder::get_object()</methodname>和<methodname>Builder::get_widget()</methodname>方法，然后将部件加入容器中。例如：

en: Popup Menus
zh_CN: 弹出菜单

en: <classname>Menus</classname> are normally just added to a window, but they can also be displayed temporarily as the result of a mouse button click. For instance, a context menu might be displayed when the user clicks their right mouse button.
zh_CN: <classname>Menus</classname>通常将直接被加入到窗口中，但也可以通过鼠标单击来临时显示他们。例如当用户单击鼠标右键的时候，可能需要显示上下文菜单。

en: To show the popup menu, use <classname>Gtk::Menu</classname>'s <methodname>popup()</methodname> method, providing the button identifier and the time of activation, as provided by the <literal>button_press_event</literal> signal, which you will need to handle anyway. For instance:
zh_CN: 要显示弹出菜单，请使用<classname>Gtk::Menu</classname>的<methodname>popup()</methodname>方法，无论如何你都需要处理由<literal>button_press_event</literal>信号提供的激活时机（鼠标单双三击、按下还是释放）和按钮标识（哪个鼠标按键）。例如：

en: Gio::Resource and glib-compile-resources
zh_CN: Gio::Resource和glib-compile-resources

en: Applications and libraries often contain binary or textual data that is really part of the application, rather than user data. For instance <classname>Gtk::Builder</classname> <filename class="extension">.glade</filename> files, splashscreen images, <classname>Gio::Menu</classname> markup xml, CSS files, icons, etc. These are often shipped as files in <filename class="directory">$datadir/appname</filename>, or manually included as literal strings in the code.
zh_CN: 应用程序和库经常包含是应用程序的一部分的二进制或文本数据，而不是用户数据。例如<classname>Gtk::Builder</classname>使用的<filename class="extension">.glade</filename>文件、启动画面、<classname>Gio::Menu</classname>标记XML、CSS文件、图标等。这些通常这些文件放于<filename class="directory">$datadir/appname</filename>目录下，也可以将其转换为文本字面量手动包含在代码中。

en: The <classname>Gio::Resource</classname> API and the <application>glib-compile-resources</application> program provide a convenient and efficient alternative to this, which has some nice properties. You maintain the files as normal files, so it's easy to edit them, but during the build the files are combined into a binary bundle that is linked into the executable. This means that loading the resource files is efficient (as they are already in memory, shared with other instances) and simple (no need to check for things like I/O errors or locate the files in the filesystem). It also makes it easier to create relocatable applications.
zh_CN: <classname>Gio::Resource</classname>API和<application>glib-compile-resources</application>程序提供了一个方便且有效的替代方案，这个方案有一些良好的性质。你可以将这些文件作为普通文件进行维护，因此你可以轻松的编辑它们，在构建过程中，这些文件将会被组合成一个二进制捆绑包，并将其链接到可执行文件中。这意味着加载资源文件会很高效（因为他们在启动时已经被加载到了内存中，并与其他实例共享）且很简单（无需对IO错误进行检查和在文件系统中查找文件）。这也使得创建可重定位应用程序变得更为简单。

en: Resource bundles are created by the <ulink url="https://developer.gnome.org/gio/stable/glib-compile-resources.html">glib-compile-resources</ulink> program which takes an xml file that describes the bundle, and a set of files that the xml references. These are combined into a binary resource bundle.
zh_CN: 资源包是由<ulink url="https://developer.gnome.org/gio/stable/glib-compile-resources.html">glib-compile-resources</ulink>程序创建的，该程序使用一个XML文件描述资源包并由该XML文件指示资源包引用了那些文件。被引用的文件和XML文件将被组合为一个二进制的资源包。

en: <ulink url="http://developer.gnome.org/glibmm/unstable/classGio_1_1Resource.html">Gio::Resource Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/glibmm/unstable/classGio_1_1Resource.html">Gio::Resource参考</ulink>

en: An example: <_:programlisting-1/> This will create a resource bundle with the files <_:itemizedlist-2/>
zh_CN: 一个示例：<_:programlisting-1/> 这将创建一个包含以下文件的资源包:<_:itemizedlist-2/>

en: You can then use <application>glib-compile-resources</application> to compile the xml to a binary bundle that you can load with <methodname>Gio::Resource::create_from_file()</methodname>. However, it's more common to use the <parameter class="command">--generate-source</parameter> argument to create a C source file to link directly into your application. E.g. <_:screen-1/>
zh_CN: 然后你可以使用<application>glib-compile-resources</application>将XML编译为可以用<methodname>Gio::Resource::create_from_file()</methodname>加载的二进制包。但是使用--generate-source生成C源文件直接链接到你的应用程序更为常见。例如：<_:screen-1/>

en: Once a <classname>Gio::Resource</classname> has been created and registered all the data in it can be accessed globally in the process by using API calls like <methodname>Gio::Resource::open_stream_from_global_resources()</methodname> to stream the data or <methodname>Gio::Resource::lookup_data_in_global_resources()</methodname> to get a direct pointer to the data. You can also use URIs like <uri>resource:///toolbar/rain.png</uri> with <classname>Gio::File</classname> to access the resource data.
zh_CN: 一旦创建并注册了<classname>Gio::Resource</classname>，就可以使用API调用（例如：<methodname>Gio::Resource::open_stream_from_global_resources()</methodname>流式获取数据或是<methodname>Gio::Resource::lookup_data_in_global_resources()</methodname>直接获取指向数据的指针）在进程的全局访问数据。你还可以使用类似于<uri>resource:///toolbar/rain.png</uri>的URI通过<classname>Gio::File</classname>访问资源数据。

en: Often you don't need a <classname>Gio::Resource</classname> instance, because resource data can be loaded with methods such as <methodname>Gdk::Pixbuf::create_from_resource()</methodname>, <methodname>Gtk::Builder::add_from_resource()</methodname> and <methodname>Gtk::Image::set_from_resource()</methodname>.
zh_CN: 通常你不需要<classname>Gio::Resource</classname>实例，因为可以使用<methodname>Gdk::Pixbuf::create_from_resource()</methodname>、<methodname>Gtk::Builder::add_from_resource()</methodname>和<methodname>Gtk::Image::set_from_resource()</methodname>直接加载资源数据。

en: Application Menu and Main Menu example
zh_CN: 应用程序菜单和主菜单实例

en: This program contains an application menu, a menubar and a toolbar. Classes are derived from <classname>Gtk::Application</classname> and <classname>Gtk::ApplicationWindow</classname>.
zh_CN: 该程序拥有一个应用程序菜单，一个菜单栏和一个工具栏。这个类是自<classname>Gtk::Application</classname>和<classname>Gtk::ApplicationWindow</classname>派生而来的。

en: App and Main Menu
zh_CN: 应用程序和主菜单

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/menus/main_menu/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/menus/main_menu/">源代码</ulink>

en: Main Menu example
zh_CN: 主菜单示例

en: This program contains a menubar and a toolbar. A class is derived from <classname>Gtk::Window</classname>.
zh_CN: 该程序包含一个菜单栏和一个工具栏。一个从<classname>Gtk::Window</classname>派生的类。

en: Main Menu
zh_CN: 主菜单

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/menus_and_toolbars">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/menus_and_toolbars">源代码</ulink>

en: Popup Menu example
zh_CN: 弹出菜单示例

en: Popup Menu
zh_CN: 弹出菜单

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/menus/popup/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/menus/popup/">源代码</ulink>

en: Adjustments
zh_CN: 调整(Adjustments)

en: <application>gtkmm</application> has various widgets that can be visually adjusted using the mouse or the keyboard, such as the <classname>Range</classname> widgets (described in the <link linkend="chapter-range-widgets">Range Widgets</link> section). There are also a few widgets that display some adjustable part of a larger area, such as the <classname>Viewport</classname> widget. These widgets have <classname>Gtk::Adjustment</classname> objects that express this common part of their API.
zh_CN: <application>gtkmm</application>有各种可以使用鼠标和键盘进行视觉上的调整的部件，例如<classname>Range</classname>部件（在<link linkend="chapter-range-widgets">范围部件</link>小节介绍）。还有些部件显示较大区域的可调整部分，例如<classname>Viewport</classname>部件。这些部件的<classname>Gtk::Adjustment</classname>对象表达了它的共有部分的API。

en: So that applications can react to changes, for instance when a user moves a scrollbar, <classname>Gtk::Adjustment</classname> has a <literal>value_changed</literal> signal. You can then use the <methodname>get_value()</methodname> method to discover the new value.
zh_CN: 如此一来，应用程序可以对更改做出反应。例如当用户移动滚动条的时候<classname>Gtk::Adjustment</classname>发出<literal>value_changed</literal>信号。你可以在信号处理函数中使用<methodname>get_value()</methodname>方法获取新的值。

en: Creating an Adjustment
zh_CN: 创建调整

en: The <classname>Gtk::Adjustment</classname> is created by its <methodname>create()</methodname> method which is as follows:
zh_CN: <classname>Gtk::Adjustment</classname>由它的<methodname>create()</methodname>方法创建，该方法的声明如下：

en: The <parameter>value</parameter> argument is the initial value of the adjustment, usually corresponding to the topmost or leftmost position of an adjustable widget. The <parameter>lower</parameter> and <parameter>upper</parameter> arguments specify the possible range of values which the adjustment can hold. The <parameter>step_increment</parameter> argument specifies the smaller of the two increments by which the user can change the value, while the <parameter>page_increment</parameter> is the larger one. The <parameter>page_size</parameter> argument usually corresponds somehow to the visible area of a panning widget. The <parameter>upper</parameter> argument is used to represent the bottommost or rightmost coordinate in a panning widget's child.
zh_CN: 其中<parameter>value</parameter>参数是调整的初始值，通常对应于可调整部件的最上边或者最左边。<parameter>lower</parameter>和<parameter>upper</parameter>参数指定调整可以容纳的值的范围。<parameter>step_increment</parameter>和<parameter>page_increment</parameter>指定了一小一大两个增量，增量控制用户在更改调整值的时候一次可以改变的量。<parameter>page_size</parameter>参数通常以某种方式与平移部件能见到的区域大小。<parameter>upper</parameter>参数被用于表示平移子部件最底端或最右端的坐标。

en: Using Adjustments the Easy Way
zh_CN: 轻松使用调整

en: The adjustable widgets can be roughly divided into those which use and require specific units for these values, and those which treat them as arbitrary numbers.
zh_CN: 可调整部件大致可以分为使用并要求这些值使用特定单位的和将它们视作任意数字的。

en: The group which treats the values as arbitrary numbers includes the <classname>Range</classname> widgets (<classname>Scrollbar</classname> and <classname>Scale</classname>), the <classname>ScaleButton</classname> widget, and the <classname>SpinButton</classname> widget. These widgets are typically "adjusted" directly by the user with the mouse or keyboard. They will treat the <parameter>lower</parameter> and <parameter>upper</parameter> values of an adjustment as a range within which the user can manipulate the adjustment's <parameter>value</parameter>. By default, they will only modify the <parameter>value</parameter> of an adjustment.
zh_CN: 将<parameter>value</parameter>视作任意数的部件组包括<classname>Range</classname>（<classname>Scrollbar</classname>和<classname>Scale</classname>）、<classname>ScaleButton</classname>、<classname>SpinButton</classname>。这些部件通常由用户使用鼠标和键盘直接进行"调整"。他们会将<parameter>lower</parameter>和<parameter>upper</parameter>视为用户可以操纵调整的<parameter>value</parameter>的范围。默认情况下它们只会修改调整的<parameter>value</parameter>。

en: The other group includes the <classname>Viewport</classname> widget and the <classname>ScrolledWindow</classname> widget. All of these widgets use pixel values for their adjustments. These are also typically adjusted indirectly using scrollbars. While all widgets which use adjustments can either create their own adjustments or use ones you supply, you'll generally want to let this particular category of widgets create its own adjustments.
zh_CN: 另一组部件包括<classname>Viewport</classname>和<classname>ScrolledWindow</classname>。所有的这些部件都将调整的值视作像素值。通常你也可以使用滚动条间接的修改调整的值。虽然所有使用调整的部件都可以创建自己的调整也可以使用你提供的调整，但是通常情况下你都会希望使用这些部件自行创建的调整。

en: If you share an adjustment object between a Scrollbar and a TextView widget, manipulating the scrollbar will automagically adjust the TextView widget. You can set it up like this:
zh_CN: 如果你使滚动条和文本视图部件共享一个调整对象，则你操纵滚动条的时候文本视图将被自动调整。你可以这样设置：

en: Adjustment Internals
zh_CN: 调整的内部

en: OK, you say, that's nice, but what if I want to create my own handlers to respond when the user adjusts a <classname>Range</classname> widget or a <classname>SpinButton</classname>. To access the value of a <classname>Gtk::Adjustment</classname>, you can use the <methodname>get_value()</methodname> and <methodname>set_value()</methodname> methods:
zh_CN: 如果你想要创建一个自己的处理函数以响应用户对<classname>Range</classname>或<classname>SpinButton</classname>部件的调整。你可以使用<classname>Gtk::Adjustment</classname>的<methodname>get_value()</methodname>和<methodname>set_value()</methodname>方法访问其值：

en: As mentioned earlier, <classname>Gtk::Adjustment</classname> can emit signals. This is, of course, how updates happen automatically when you share an <classname>Adjustment</classname> object between a <classname>Scrollbar</classname> and another adjustable widget; all adjustable widgets connect signal handlers to their adjustment's <literal>value_changed</literal> signal, as can your program.
zh_CN: 如前所述，<classname>Gtk::Adjustment</classname>可以发射信号。而所有可调整部件都会将信号处理函数连接到其调整对象的<literal>value_changed</literal>信号你的程序也可以如此。这使得当<classname>Scrollbar</classname>和其他可调整部件共享一个<classname>Adjustment</classname>对象时，如果你操纵滚动条与其共享调整对象的其他可调整部件将会自动更新。

en: So, for example, if you have a <classname>Scale</classname> widget, and you want to change the rotation of a picture whenever its value changes, you would create a signal handler like this:
zh_CN: 因此，例如，如果你有一个<classname>Scale</classname>部件并且你想要当调整值变更以后更改图片的旋转角度，你可以创建一个如下所示的信号处理函数：

en: and connect it to the scale widget's adjustment like this:
zh_CN: 并且将其连接到比例部件的调整对象上，如下所示：

en: What if a widget reconfigures the <parameter>upper</parameter> or <parameter>lower</parameter> fields of its <classname>Adjustment</classname>, such as when a user adds more text to a text widget? In this case, it emits the <literal>changed</literal> signal.
zh_CN: 如果一个部件重新配置其<classname>Adjustment</classname>的<parameter>upper</parameter>和<parameter>lower</parameter>字段（例如：用户向文本部件添加了更多的文本），那么它将发出<literal>changed</literal>信号。

en: <classname>Range</classname> widgets typically connect a handler to this signal, which changes their appearance to reflect the change - for example, the size of the slider in a scrollbar will grow or shrink in inverse proportion to the difference between the <parameter>lower</parameter> and <parameter>upper</parameter> values of its <classname>Adjustment</classname>.
zh_CN: <classname>Range</classname>部件通常会将处理程序连接到此信号，并更改其外观响应变更 - 例如：滚动条中的滑块将随着<classname>Adjustment</classname>中<parameter>lower</parameter>与<parameter>upper</parameter>的差值的增大逐渐变小，反之则逐渐增大。

en: You probably won't ever need to attach a handler to this signal, unless you're writing a new type of range widget.
zh_CN: 除非你正在编写新的范围部件，否则你可能永远不需要将处理程序连接到这个信号。

en: Dialogs
zh_CN: 对话框(Dialogs)

en: Dialogs are used as secondary windows, to provide specific information or to ask questions. <classname>Gtk::Dialog</classname> windows contain a few pre-packed widgets to ensure consistency, and a <methodname>run()</methodname> method which blocks until the user dismisses the dialog.
zh_CN: 对话框被用作辅助窗口，以提供特定的信息或者提出问题。<classname>Gtk::Dialog</classname>窗口包含了一些预装部件以确保一致性，且有一个<methodname>run()</methodname>方法可以阻塞到用户关闭对话框。

en: There are several derived <classname>Dialog</classname> classes which you might find useful. <classname>Gtk::MessageDialog</classname> is used for most simple notifications. But at other times you might need to derive your own dialog class to provide more complex functionality.
zh_CN: 有几个派生自<classname>Dialog</classname>的类可能对你而言很有用。<classname>Gtk::MessageDialog</classname>多被用于简单的通知。但有时候你也需要派生自己的对话框类以提供更为复杂的功能。

en: To pack widgets into a custom dialog, you should pack them into the <classname>Gtk::Box</classname>, available via <methodname>get_content_area()</methodname>. To just add a <classname>Button</classname> to the bottom of the <classname>Dialog</classname>, you could use the <methodname>add_button()</methodname> method.
zh_CN: 若要将部件添加到自定义的对话框中，你需要将其装入通过<methodname>get_content_area()</methodname>获得的<classname>Gtk::Box</classname>中。如果你只需要向<classname>Dialog</classname>的底部添加一个<classname>Button</classname>，那么你可以直接使用<methodname>add_button()</methodname>方法。

en: The <methodname>run()</methodname> method returns an <literal>int</literal>. This may be a value from the <literal>Gtk::ResponseType</literal> if the user closed the dialog by clicking a standard button, or it could be the custom response value that you specified when using <methodname>add_button()</methodname>.
zh_CN: <methodname>run()</methodname>方法返回一个<literal>int</literal>。如果用户是通过单击标准按钮关闭的对话框，则该值可能是<literal>Gtk::ResponseType</literal>中的一个也可能是使用<methodname>add_button()</methodname>时你所指定的值。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Dialog.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Dialog.html">参考</ulink>

en: MessageDialog
zh_CN: 消息对话框(MessageDialog)

en: <classname>MessageDialog</classname> is a convenience class, used to create simple, standard message dialogs, with a message, an icon, and buttons for user response. You can specify the type of message and the text in the constructor, as well as specifying standard buttons via the <literal>Gtk::ButtonsType</literal> enum.
zh_CN: <classname>MessageDialog</classname>是一个便利类，用于创建包含消息、图标、以及便于用户响应的按钮的简易标准消息对话框。你可以在其构造函数中指定消息类型和消息文本，也可以通过<literal>Gtk::ButtonsType</literal>枚举指定其包含的标准按钮。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1MessageDialog.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1MessageDialog.html">参考</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/dialogs/messagedialog">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/dialogs/messagedialog">源代码</ulink>

en: FileChooserDialog
zh_CN: 文件选择对话框(FileChooserDialog)

en: The <classname>FileChooserDialog</classname> is suitable for use with "Open" or "Save" menu items.
zh_CN: <classname>FileChooserDialog</classname>通常被用于"打开"或"保存"菜单项。

en: Most of the useful member methods for this class are actually in the <classname>Gtk::FileChooser</classname> base class.
zh_CN: 该类的大部分有用的成员函数都在其基类<classname>Gtk::FileChooser</classname>中。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1FileChooserDialog.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1FileChooserDialog.html">参考</ulink>

en: FileChooser
zh_CN: 文件选择器(FileChooser)

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/dialogs/filechooserdialog">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/dialogs/filechooserdialog">源代码</ulink>

en: ColorChooserDialog
zh_CN: 颜色选择器对话框(ColorChooserDialog)

en: The <classname>ColorChooserDialog</classname> allows the user to choose a color. The <classname>ColorButton</classname> opens a color selection dialog when it is clicked.
zh_CN: <classname>ColorChooserDialog</classname>允许用户选择一个颜色。当<classname>ColorButton</classname>被点击的时会打开一个颜色选择对话框。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ColorChooserDialog.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1ColorChooserDialog.html">参考</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/dialogs/colorchooserdialog">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/dialogs/colorchooserdialog">源代码</ulink>

en: FontChooserDialog
zh_CN: 字体选择器对话框(FontChooserDialog)

en: The <classname>FontChooserDialog</classname> allows the user to choose a font. The <classname>FontButton</classname> opens a font chooser dialog when it is clicked.
zh_CN: <classname>FontChooserDialog</classname>允许用户选择一个字体。当<classname>FontButton</classname>被点击时将打开一个字体选择对话框。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1FontChooserDialog.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1FontChooserDialog.html">参考</ulink>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/dialogs/fontchooserdialog">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/dialogs/fontchooserdialog">源代码</ulink>

en: Non-modal AboutDialog
zh_CN: 非模态关于对话框(AboutDialog)

en: The <classname>AboutDialog</classname> offers a simple way to display information about a program, like its logo, name, copyright, website and license.
zh_CN: <classname>AboutDialog</classname>提供了一个简单的显示程序有关信息（例如标志、名称、版权、网站、许可证）的方式。

en: Most dialogs in this chapter are modal, that is, they freeze the rest of the application while they are shown. It's also possible to create a non-modal dialog, which does not freeze other windows in the application. The following example shows a non-modal <classname>AboutDialog</classname>. This is perhaps not the kind of dialog you would normally make non-modal, but non-modal dialogs can be useful in other cases. E.g. <application>gedit</application>'s search-and-replace dialog is non-modal.
zh_CN: 本章中的大部分对话框都是模态的，也就是说在显示它们的时候应用程序的其他部分是被冻结的。你也可以创建一个非模态的对话框，这样的对话框不会冻结应用程序的其他窗口。下面的示例显示了一个非模态的<classname>AboutDialog</classname>。通常你不会想要将该对话框做成非模态，但这不表示非模态对话框在其它情况下没有用。例如：在<application>gedit</application>中搜索和替换对话框就是非模态的。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1AboutDialog.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1AboutDialog.html">参考</ulink>

en: AboutDialog
zh_CN: 关于对话框

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/dialogs/aboutdialog">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/dialogs/aboutdialog">源代码</ulink>

en: The DrawingArea Widget
zh_CN: 绘图区域部件(DrawingArea Widget)

en: The <classname>DrawingArea</classname> widget is a blank window that gives you the freedom to create any graphic you desire. Along with that freedom comes the responsibility to draw on the widget. When a widget is first shown, or when it is covered and then uncovered again it needs to redraw itself. Most widgets have code to do this, but the <classname>DrawingArea</classname> does not, allowing you to write your own draw function to determine how the contents of the widget will be drawn. This is done by setting a draw function with a call to the <methodname>set_draw_func()</methodname> member function.
zh_CN: <classname>DrawingArea</classname>部件是一个空白的窗口，让你可以自由的创造任何你想要的图形。伴随着这种自由而来的是绘制这个部件的责任。在部件第一次显示或者部件被覆盖后又露出的时候它需要重绘自己。大多数部件都包含执行此操作的代码，但是<classname>DrawingArea</classname>并没有。因此你可以编写自己的绘图函数来确定如何绘制绘部件的内容。你可以调用<methodname>set_draw_func()</methodname>成员函数来设置绘图函数。

en: GTK uses the <ulink url="http://cairographics.org">Cairo</ulink> drawing API. With <application>gtkmm</application>, you may use the <ulink url="http://www.cairographics.org/cairomm/">cairomm</ulink> C++ API for cairo.
zh_CN: GTK使用<ulink url="http://cairographics.org">开罗</ulink>绘图API。而在<application>gtkmm</application>中你可以使用由<ulink url="http://www.cairographics.org/cairomm/">cairomm</ulink>提供的开罗C++ API。

en: You can draw very sophisticated shapes using Cairo, but the methods to do so are quite basic. Cairo provides methods for drawing straight lines, curved lines, and arcs (including circles). These basic shapes can be combined to create more complex shapes and paths which can be filled with solid colors, gradients, patterns, and other things. In addition, Cairo can perform complex transformations, do compositing of images, and render antialiased text.
zh_CN: 你可以使用开罗绘制非常复杂的形状，但你只有一些很基本的方法可用。开罗提供了绘制直线、曲线、圆弧（包括圆）的方法。你可以通过对这些图形进行组合从而创建更为复杂的形状和路径，然后用纯色、渐变、模式等进行填充。除此之外，开罗还可以进行复杂的转换、合成图像和渲染抗锯齿文本等。

en: Cairo and Pango
zh_CN: 开罗和Pango

en: Although Cairo can render text, it's not meant to be a replacement for Pango. Pango is a better choice if you need to perform more advanced text rendering such as wrapping or ellipsizing text. Drawing text with Cairo should only be done if the text is part of a graphic.
zh_CN: 虽然开罗可以用于渲染文本，但不意味着它能替代Pango。如果你需要进行更高级的文本渲染（例如环绕和省略文本）则Pango会是更好的选择。只有当文本是图形的一部分的时候才应该使用开罗绘制文本。

en: In this section of the tutorial, we'll cover the basic Cairo drawing model, describe each of the basic drawing elements in some detail (with examples), and then present a simple application that uses Cairo to draw a custom clock widget.
zh_CN: 在本教程的这一部分中，我们将介绍开罗的基本绘图模型，详细描述每个基本绘制元素（包括示例），然后介绍一个使用开罗绘制自定义时钟部件的简单应用程序。

en: The Cairo Drawing Model
zh_CN: 开罗绘制模型

en: The basic concept of drawing in Cairo involves defining 'invisible' paths and then stroking or filling them to make them visible.
zh_CN: 开罗的基本概念包括定义'不可见'路径然后描绘(stroking)或者填充(filling)它们使其可见。

en: To do any drawing in <application>gtkmm</application> with Cairo, you must first get a <classname>Cairo::Context</classname> object. This class holds all of the graphics state parameters that describe how drawing is to be done. This includes information such as line width, color, the surface to draw to, and many other things. This allows the actual drawing functions to take fewer arguments to simplify the interface. Usually, you use the <classname>Cairo::Context</classname> that you get as input data to the draw function that you set with the call to <methodname>set_draw_func()</methodname>. It's also possible to create a <classname>Cairo::Context</classname> by calling the <methodname>Gdk::Surface::create_cairo_context()</methodname> and <methodname>Gdk::CairoContext::cairo_create()</methodname> functions. Since Cairo contexts are reference-counted objects, <methodname>cairo_create()</methodname> returns a <classname>Cairo::RefPtr&lt;Cairo::Context&gt;</classname> object. (Note the difference between <classname>Gdk::CairoContext</classname> and <classname>Cairo::Context</classname>.)
zh_CN: 要在<application>gtkmm</application>中使用开罗进行绘制，必须先获取<classname>Cairo::Context</classname>对象。这个类保存了所有描述如何进行绘制的图形状态参数。状态参数包含了诸如线宽、颜色、要绘制的表面和许多其他内容的信息。这允许实际上的绘图函数只需要使用较少的参数从而简化接口。通常你使用<methodname>set_draw_func()</methodname>设置的绘图函数将<classname>Cairo::Context</classname>作为输入数据。也可以通过调用<methodname>Gdk::Surface::create_cairo_context()</methodname>和<methodname>Gdk::CairoContext::cairo_create()</methodname>函数创建一个<classname>Cairo::Context</classname>。由于<classname>Cairo::Context</classname>是一个使用引用计数的对象，因此<methodname>cairo_create()</methodname>返回<classname>Cairo::RefPtr&lt;Cairo::Context&gt;</classname>对象（请注意区分<classname>Gdk::CairoContext</classname>与<classname>Cairo::Context</classname>。）。

en: The following example shows how to set up a Cairo context with a foreground color of red and a width of 2. Any drawing functions that use this context will use these settings.
zh_CN: 以下示例显示如何设置一个开罗上下文(Cairo Context)的前景色为红色且宽度为2。任何使用该上下文的绘图函数都将使用这些设置。

en: Each <classname>Cairo::Context</classname> is associated with a particular <classname>Gdk::Surface</classname>, so the first line of the above example creates a <classname>Gtk::DrawingArea</classname> widget and the next two lines use its associated <classname>Gdk::Surface</classname> to create a <classname>Cairo::Context</classname> object. The final two lines change the graphics state of the context.
zh_CN: 每一个<classname>Cairo::Context</classname>都有一个特定的<classname>Gdk::Surface</classname>与之相关联，因此上面示例的第一行创建了一个<classname>Gtk::DrawingArea</classname>部件，接下来两行使用与其相关联的<classname>Gdk::Surface</classname>创建一个<classname>Cairo::Context</classname>对象。最后两行更改上下文的图形状态。

en: There are a number of graphics state variables that can be set for a Cairo context. The most common context attributes are color (using <methodname>set_source_rgb()</methodname> or <methodname>set_source_rgba()</methodname> for translucent colors), line width (using <methodname>set_line_width()</methodname>), line dash pattern (using <methodname>set_dash()</methodname>), line cap style (using <methodname>set_line_cap()</methodname>), and line join style (using <methodname>set_line_join()</methodname>), and font styles (using <methodname>set_font_size()</methodname>, <methodname>set_font_face()</methodname> and others). There are many other settings as well, such as transformation matrices, fill rules, whether to perform antialiasing, and others. For further information, see the <ulink url="http://www.cairographics.org/cairomm/">cairomm</ulink> API documentation.
zh_CN: 可以为开罗上下文设置许多的图形状态。最常见的上下文属性是颜色（使用<methodname>set_source_rgb()</methodname>或需要半透明颜色的时候用<methodname>set_source_rgba()</methodname>）、线宽（使用<methodname>set_line_width()</methodname>）、虚线模式（使用<methodname>set_dash()</methodname>）、线帽样式（使用<methodname>set_line_cap()</methodname>）、线条连接样式（使用<methodname>set_line_join()</methodname>）以及字体样式（使用<methodname>set_font_size()</methodname>）。还有许多其他设置，例如变换矩阵、填充规则、是否执行抗锯齿规则等。更多详情请参阅<ulink url="http://www.cairographics.org/cairomm/">cairomm</ulink>API文档。

en: It is good practice to put all modifications to the graphics state between <methodname>save()</methodname>/<methodname>restore()</methodname> function calls. For example, if you have a function that takes a <classname>Cairo::Context</classname> reference as an argument, you might implement it as follows:
zh_CN: 好的做法是在一组<methodname>save()</methodname>/<methodname>restore()</methodname>调用之间进行所有对图形状态的更改。例如，如果你有一个将<classname>Cairo::Context</classname>的引用作为参数的函数，你可以这样实现它：

en: The current state of a <classname>Cairo::Context</classname> can be saved to an internal stack of saved states and later be restored to the state it was in when you saved it. To do this, use the <methodname>save()</methodname> method and the <methodname>restore()</methodname> method. This can be useful if you need to temporarily change the line width and color (or any other graphics setting) in order to draw something and then return to the previous settings. In this situation, you could call <methodname>Cairo::Context::save()</methodname>, change the graphics settings, draw the lines, and then call <methodname>Cairo::Context::restore()</methodname> to restore the original graphics state. Multiple calls to <methodname>save()</methodname> and <methodname>restore()</methodname> can be nested; each call to <methodname>restore()</methodname> restores the state from the matching paired <methodname>save()</methodname>. <_:tip-1/>
zh_CN: 可以将<classname>Cairo::Context</classname>当前的状态保存到其内部用于保存状态的栈中，并在之后将状态还原为保存时的状态。要做到这个请调用<methodname>save()</methodname>和<methodname>restore()</methodname>方法。当你需要临时更改某些图形设置（例如线宽和颜色）以绘制某些内容然后又退回到之前的状态时这将很有用。在这种情况下，你可以先调用<methodname>Cairo::Context::save()</methodname>，然后修改图形设置并绘制图形，再调用<methodname>Cairo::Context::restore()</methodname>恢复之前的图形状态。你可以多次嵌套调用<methodname>save()</methodname>和<methodname>restore()</methodname>；每次<methodname>restore()</methodname>调用都会将恢复状态到与之相对应的<methodname>save()</methodname>所保存的状态。 <_:tip-1/>

en: The draw function that you set with a call to <methodname>set_draw_func()</methodname> is called with a Cairo context that you shall use for drawing in the <classname>Gtk::DrawingArea</classname> widget. It is not necessary to save and restore this Cairo context in the draw function.
zh_CN: 你通过调用<methodname>set_draw_func()</methodname>所设置的绘图函数是由你要绘制的<classname>Gtk::DrawingArea</classname>部件用开罗上下文调用的。所以你不需要在绘图函数中对此开罗上下文进行保存和恢复（部件会在调用绘图函数时做保存与恢复）。

en: Drawing Straight Lines
zh_CN: 画直线

en: Since the Cairo graphics library was written with support for multiple output targets (the X window system, PNG images, OpenGL, etc), there is a distinction between user-space and device-space coordinates. The mapping between these two coordinate systems defaults to one-to-one so that integer values map roughly to pixels on the screen, but this setting can be adjusted if desired. Sometimes it may be useful to scale the coordinates so that the full width and height of a window both range from 0 to 1 (the 'unit square') or some other mapping that works for your application. This can be done with the <methodname>Cairo::Context::scale()</methodname> function.
zh_CN: 由于开罗图形库是为了支持多个输出目标（X window系统、PNG图片、OpenGL等）编写的，因此用户空间坐标和设备空间坐标存在一些区别。默认情况下这两个坐标系是一对一的，这样可以将整数值大致映射为屏幕上的像素值，不过有需要时可以通过<methodname>Cairo::Context::scale()</methodname>函数对此行为进行调整。例如：你可能会需要使一个窗口的宽和高在调整比例后的坐标系中取值范围均处于0到1之间（单位正方形）。

en: Now that we understand the basics of the Cairo graphics library, we're almost ready to start drawing. We'll start with the simplest of drawing elements: the straight line. But first you need to know a little bit about Cairo's coordinate system. The origin of the Cairo coordinate system is located in the upper-left corner of the window with positive x values to the right and positive y values going down. <_:tip-1/>
zh_CN: 现在我们已经了解了开罗图形库的基本知识，是时候开始画图了。我们将从画最简单的元素：直线 开始。但是在此之前你需要对开罗的坐标系有所了解。开罗的坐标系原点在窗口的左上角，从左向右X的值逐渐增大，从上往下Y的值逐渐增大。 <_:tip-1/>

en: In this example, we'll construct a small but fully functional <application>gtkmm</application> program and draw some lines into the window. The lines are drawn by creating a path and then stroking it. A path is created using the functions <methodname>Cairo::Context::move_to()</methodname> and <methodname>Cairo::Context::line_to()</methodname>. The function <methodname>move_to()</methodname> is similar to the act of lifting your pen off of the paper and placing it somewhere else -- no line is drawn between the point you were at and the point you moved to. To draw a line between two points, use the <methodname>line_to()</methodname> function.
zh_CN: 在这个示例中，我们将构建一个很小但功能齐全的<application>gtkmm</application>程序，并将一些线绘制到窗口中。使用函数<methodname>Cairo::Context::move_to()</methodname>和<methodname>Cairo::Context::line_to()</methodname>创建一个路径。<methodname>move_to()</methodname>函数的行为类似于将笔从纸上抬起并放到其他地方 -- 在你移动到的点和你之前所在的点直接不会画出一条线。使用<methodname>line_to()</methodname>函数可以在两点之间画线。

en: After you've finished creating your path, you still haven't drawn anything visible yet. To make the path visible, you must use the function <methodname>stroke()</methodname> which will stroke the current path with the line width and style specified in your <classname>Cairo::Context</classname> object. After stroking, the current path will be cleared so that you can start on your next path.
zh_CN: 创建完你的路径以后。你依旧没有画任何看得见的东西。要想让路径可见，你需要使用<methodname>stroke()</methodname>函数，该函数将使用你的<classname>Cairo::Context</classname>对象中保存的线宽与样式绘制当前的路径。描绘完成后，当前路径将被清除，以便你可以从下一个路径开始。

en: Many Cairo drawing functions have a <methodname>_preserve()</methodname> variant. Normally drawing functions such as <methodname>clip()</methodname>, <methodname>fill()</methodname>, or <methodname>stroke()</methodname> will clear the current path. If you use the <methodname>_preserve()</methodname> variant, the current path will be retained so that you can use the same path with the next drawing function.
zh_CN: 多数的开罗绘图函数都拥有一个<methodname>_preserve()</methodname>变体。通常情况下<methodname>clip()</methodname>、<methodname>fill()</methodname>、<methodname>stroke()</methodname>函数会清除当前的路径。如果你使用他们的<methodname>_preserve()</methodname>变体，则当前路径会被保留，以便下一个绘图函数能继续在一样的路径上绘制。

en: Drawing Area - Lines
zh_CN: 绘图区域 - 线

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/simple">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/simple">源代码</ulink>

en: This program contains a single class, <classname>MyArea</classname>, which is a subclass of <classname>Gtk::DrawingArea</classname> and contains an <methodname>on_draw()</methodname> member function. This function becomes the draw function by a call to <methodname>set_draw_func()</methodname> in <classname>MyArea</classname>'s constructor. <methodname>on_draw()</methodname> is then called whenever the image in the drawing area needs to be redrawn. It is passed a <classname>Cairo::RefPtr</classname> pointer to a <classname>Cairo::Context</classname> that we use for the drawing. The actual drawing code sets the color we want to use for drawing by using <methodname>set_source_rgb()</methodname> which takes arguments defining the Red, Green, and Blue components of the desired color (valid values are between 0 and 1). After setting the color, we created a new path using the functions <methodname>move_to()</methodname> and <methodname>line_to()</methodname>, and then stroked this path with <methodname>stroke()</methodname>.
zh_CN: 这个程序包含一个<classname>MyArea</classname>类，它是<classname>Gtk::DrawingArea</classname>的子类，并且包含<methodname>on_draw()</methodname>成员函数。通过在<classname>MyArea</classname>的构造函数中调用<methodname>set_draw_func()</methodname>使其变成绘制函数。每当需要重绘绘图区域的图像的时候，<methodname>on_draw()</methodname>就会被调用。这将会向我们的绘制函数传递一个指向<classname>Cairo::Context</classname>的<classname>Cairo::RefPtr</classname>指针。实际进行绘图的代码使用<methodname>set_source_rgb()</methodname>设置我们将用于绘图的颜色，这个函数接受定义颜色所需的红色、绿色、蓝色分量作为参数（参数的有效值介于0到1之间）。设置完颜色后，我们使用<methodname>move_to()</methodname>和<methodname>line_to()</methodname>函数创建一个新的路径，然后使用<methodname>stroke()</methodname>绘制了这个路径。

en: Drawing with relative coordinates
zh_CN: 使用相对坐标绘图

en: In the example above we drew everything using absolute coordinates. You can also draw using relative coordinates. For a straight line, this is done with the function <methodname>Cairo::Context::rel_line_to()</methodname>.
zh_CN: 在上面的例子中，我们使用绝对坐标进行绘图。你也可以使用相对坐标进行绘图。对于直线而言，你可以通过<methodname>Cairo::Context::rel_line_to()</methodname>完成用相对坐标绘图。

en: Line styles
zh_CN: 线型

en: In addition to drawing basic straight lines, there are a number of things that you can customize about a line. You've already seen examples of setting a line's color and width, but there are others as well.
zh_CN: 除了绘制基本直线以外，你还可以对线条进行很多自定义。你已经看到了对线条颜色和线条宽度的示例，但还有其他示例。

en: If you've drawn a series of lines that form a path, you may want them to join together in a certain way. Cairo offers three different ways to join lines together: Miter, Bevel, and Round. These are show below:
zh_CN: 如果你于一个路径绘制了一系列的线条，你可能希望它们以某种方式被连接起来。开罗提供了三种不同的连接线条的方式：斜接(Miter)、斜切(Bevel)、圆(Round)。这些连接方式的示意图如下：

en: Different join types in Cairo
zh_CN: 开罗的不同连接类型

en: The line join style is set using the function <methodname>Cairo::Context::set_line_join()</methodname>.
zh_CN: 线条连接样式由<methodname>Cairo::Context::set_line_join()</methodname>函数进行设置。

en: Line ends can have different styles as well. The default style is for the line to start and stop exactly at the destination points of the line. This is called a Butt cap. The other options are Round (uses a round ending, with the center of the circle at the end point) or Square (uses a squared ending, with the center of the square at the end point). This setting is set using the function <methodname>Cairo::Context::set_line_cap()</methodname>.
zh_CN: 线尾也有不同的样式。默认样式是从线条的开始到结尾准确的停止。这被叫做平端。其他的可选性有圆（使用圆形结束，以终点为圆心）和方（使用正方形结束，以终点为正方形的中心）。这可以使用<methodname>Cairo::Context::set_line_cap()</methodname>函数使用。

en: There are other things you can customize as well, including creating dashed lines and other things. For more information, see the Cairo API documentation.
zh_CN: 你还可以自定义其他内容，比如创建虚线等。更多有关信息请参阅开罗API文档。

en: Drawing thin lines
zh_CN: 画细线

en: If you try to draw one pixel wide lines, you may notice that the line sometimes comes up blurred and wider than it ought to be. This happens because Cairo will try to draw from the selected position, to both sides (half to each), so if you're positioned right on the intersection of the pixels, and want a one pixel wide line, Cairo will try to use half of each adjacent pixel, which isn't possible (a pixel is the smallest unit possible). This happens when the width of the line is an odd number of pixels (not just one pixel).
zh_CN: 如果你尝试画一条宽度为一个像素的线条，你可能会注意到这条线有时会变得模糊并且比应有的宽度更宽。发生这种情况的原因是开若尝试在所选位置向两边绘制（一边一半），因此如果你如果正好位于像素交点上，还想绘制一个像素宽度的线条，那是不可能做到的（像素是最小的单位）。所以当像素的宽度是奇数的时候就会出现这种情况（不只是一个像素的时候）。

en: The trick is to position in the middle of the pixel where you want the line to be drawn, and thus guaranteeing you get the desired results. See <ulink url="http://cairographics.org/FAQ/#sharp_lines">Cairo FAQ</ulink>.
zh_CN: 解决问题的诀窍是将像素放于要绘制的线条的中间，从而确保获得所需的结果。请参阅<ulink url="http://cairographics.org/FAQ/#sharp_lines">开罗常见问题</ulink>。

en: Drawing Area - Thin Lines
zh_CN: 绘图区域 - 细线

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/thin_lines">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/thin_lines">源代码</ulink>

en: Drawing Curved Lines
zh_CN: 画曲线

en: In addition to drawing straight lines Cairo allows you to easily draw curved lines (technically a cubic Bézier spline) using the <methodname>Cairo::Context::curve_to()</methodname> and <methodname>Cairo::Context::rel_curve_to()</methodname> functions. These functions take coordinates for a destination point as well as coordinates for two 'control' points. This is best explained using an example, so let's dive in.
zh_CN: 除了绘制直线以外，开罗还允许你用<methodname>Cairo::Context::curve_to()</methodname>和<methodname>Cairo::Context::rel_curve_to()</methodname>函数轻松的绘制曲线（从技术上而言是三次贝塞尔曲线）。这些函数需要一个目标点的坐标和两个'控制'点的坐标。这最好用一个示例来解释，所以让我们开始吧。

en: This simple application draws a curve with Cairo and displays the control points for each end of the curve.
zh_CN: 这个简单的示例程序使用开罗绘制了一条曲线并显示了曲线两端的控制点。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/curve">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/curve">源代码</ulink>

en: The only difference between this example and the straight line example is in the <methodname>on_draw()</methodname> function, but there are a few new concepts and functions introduced here, so let's examine them briefly.
zh_CN: 这个示例与绘制直线示例的唯一区别在它们的<methodname>on_draw()</methodname>函数，不过这里引入了一些新的概念和函数，所以让我们简要的介绍一下它们。

en: We make a call to <methodname>Cairo::Context::scale()</methodname>, passing in the width and height of the drawing area. This scales the user-space coordinate system such that the width and height of the widget are both equal to 1.0 'units'. There's no particular reason to scale the coordinate system in this case, but sometimes it can make drawing operations easier.
zh_CN: 我们调用<methodname>Cairo::Context::scale()</methodname>并传入绘图区域的宽和高，这将使用户空间坐标系被缩放为"1个单位"（宽高的范围变成[0.0,1.0]）。在这其实并没有什么特别的要对坐标系进行缩放的理由，只是为了使绘图操作有时候更易用。

en: The call to <methodname>Cairo::Context::curve_to()</methodname> should be fairly self-explanatory. The first pair of coordinates define the control point for the beginning of the curve. The second set of coordinates define the control point for the end of the curve, and the last set of coordinates define the destination point. To make the concept of control points a bit easier to visualize, a line has been drawn from each control point to the end-point on the curve that it is associated with. Note that these control point lines are both translucent. This is achieved with a variant of <methodname>set_source_rgb()</methodname> called <methodname>set_source_rgba()</methodname>. This function takes a fourth argument specifying the alpha value of the color (valid values are between 0 and 1).
zh_CN: 对<methodname>Cairo::Context::curve_to()</methodname>的调用应该是不言自明的。第一组坐标定义了曲线起点的控制点。第二组坐标定义了曲线终点的控制点，而最后一组坐标定义了目标点。为了使控制点的概念更容易被看清，从每个控制点到与之关联的曲线上的端点上都画了一条线。请注意，这些控制点线都是半透明的。这是通过调用<methodname>set_source_rgb()</methodname>的变体函数<methodname>set_source_rgba()</methodname>实现的。这个函数使用第四个参数来接受指定颜色的alpha值（值的有效区间为0到1）。

en: Drawing Arcs and Circles
zh_CN: 画圆弧和圆

en: With Cairo, the same function is used to draw arcs, circles, or ellipses: <methodname>Cairo::Context::arc()</methodname>. This function takes five arguments. The first two are the coordinates of the center point of the arc, the third argument is the radius of the arc, and the final two arguments define the start and end angle of the arc. All angles are defined in radians, so drawing a circle is the same as drawing an arc from 0 to 2 * M_PI radians. An angle of 0 is in the direction of the positive X axis (in user-space). An angle of M_PI/2 radians (90 degrees) is in the direction of the positive Y axis (in user-space). Angles increase in the direction from the positive X axis toward the positive Y axis. So with the default transformation matrix, angles increase in a clockwise direction. (Remember that the positive Y axis points downwards.)
zh_CN: 在开罗中，画圆弧、圆、椭圆使用的是同一个函数：<methodname>Cairo::Context::arc()</methodname>。这个函数有五个参数。前两个参数是圆弧中心点的坐标，第三个参数是圆弧的半径，最后两个参数是圆弧的起点和终点。所有的角度都使用弧度制，所以画圆和画一个弧度为0到2*M_PI的圆弧是一样的。角度0沿着X轴的正方向（对于用户空间而言）。角度M_PI/2（角度制的90°）沿着Y轴的正方向（对于用户空间而言）。角度沿着X轴的正方向向Y轴的正方向逐渐增加。所以使用默认的变换矩阵的时候，角度沿着顺时针方向增加（请记住Y轴的正方向指向下方）。

en: To draw an ellipse, you can scale the current transformation matrix by different amounts in the X and Y directions. For example, to draw an ellipse with center at <varname>x</varname>, <varname>y</varname> and size <varname>width</varname>, <varname>height</varname>:
zh_CN: 想要绘制椭圆的话，你可以在X和Y方向用不同的量缩放当前的变换矩阵。例如，如果你想要绘制一个以<varname>x</varname>，<varname>y</varname>为中心，大小为<varname>width</varname>，<varname>height</varname>的椭圆：

en: Here's an example of a simple program that draws an arc, a circle and an ellipse into a drawing area.
zh_CN: 这是一个简单的示例程序，它在绘图区域绘制了一个圆弧、一个圆和一个椭圆。

en: Drawing Area - Arcs
zh_CN: 绘图区域 - 圆弧

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/arcs">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/arcs">源代码</ulink>

en: There are a couple of things to note about this example code. Again, the only real difference between this example and the previous ones is the <methodname>on_draw()</methodname> function, so we'll limit our focus to that function. In addition, the first part of the function is nearly identical to the previous examples, so we'll skip that portion.
zh_CN: 关于这个示例代码有几件事需要注意。首先这个示例与之前的示例的区别也只在<methodname>on_draw()</methodname>函数中，因此我们重点接受这个函数。另外，函数的第一部分与之前的也几乎一样，所以我们将会跳过该部分。

en: Note that in this case, we've expressed nearly everything in terms of the height and width of the window, including the width of the lines. Because of this, when you resize the window, everything scales with the window. Also note that there are three drawing sections in the function and each is wrapped with a <methodname>save()</methodname>/<methodname>restore()</methodname> pair so that we're back at a known state after each drawing.
zh_CN: 请注意，在这个情况下我们几乎使用窗口的宽和高表示了包括线条宽度在内的所有的内容（通过缩放用户坐标系）。所以当我们调整窗口大小的时候，所有的内容都会随着窗口一同缩放。还请注意，函数中有三个进行绘图的部分都用一组<methodname>save()</methodname>/<methodname>restore()</methodname>包裹，以便我们在每次绘完图都能返回已知状态。

en: The section for drawing an arc introduces one new function, <methodname>close_path()</methodname>. This function will in effect draw a straight line from the current point back to the first point in the path. There is a significant difference between calling <methodname>close_path()</methodname> and manually drawing a line back to the starting point, however. If you use <methodname>close_path()</methodname>, the lines will be nicely joined together. If you use <methodname>line_to()</methodname> instead, the lines will end at the same point, but Cairo won't do any special joining.
zh_CN: 在绘制圆弧的部分介绍了一个新的函数：<methodname>close_path()</methodname>。这个函数的效果实际上就是在当前点和路径的第一个点之间画一条直线。但调用<methodname>close_path()</methodname>所绘制的线条和使用<methodname>line_to()</methodname>手工绘制一条回到起点的线条会有很大的不同。如果你使用<methodname>close_path()</methodname>，则这些线将会很好的连接到一起。如果你改用<methodname>line_to()</methodname>，那么这些线将在同一个点结束但是开罗不会对此做任何特殊的连接。

en: Drawing counter-clockwise
zh_CN: 逆时针绘图

en: The function <methodname>Cairo::Context::arc_negative()</methodname> is exactly the same as <methodname>Cairo::Context::arc()</methodname> but the angles go the opposite direction.
zh_CN: 函数<methodname>Cairo::Context::arc_negative()</methodname>的功能与<methodname>Cairo::Context::arc()</methodname>函数完全一致，但是他们的绘制方向是相反的。

en: Drawing Text
zh_CN: 绘制文本

en: Drawing Text with Pango
zh_CN: 使用Pango绘制文本

en: Text is drawn via Pango Layouts. The easiest way to create a <classname>Pango::Layout</classname> is to use <methodname>Gtk::Widget::create_pango_layout()</methodname>. Once created, the layout can be manipulated in various ways, including changing the text, font, etc. Finally, the layout can be rendered using the <methodname>Pango::Layout::show_in_cairo_context()</methodname> method.
zh_CN: 通过Pango布局绘制文本。创建一个<classname>Pango::Layout</classname>最简单的方法是使用<methodname>Gtk::Widget::create_pango_layout()</methodname>。创建布局以后，可以通过各种方式操纵布局，包括更改文本、字体等。然后可以使用<methodname>Pango::Layout::show_in_cairo_context()</methodname>方法渲染布局。

en: Here is an example of a program that draws some text, some of it upside-down. The Printing chapter contains another <link linkend="sec-printing-example">example</link> of drawing text.
zh_CN: 这是一个绘制一些文本的示例程序，其中的一些文本上下颠倒。打印一章包含了另一个绘制文本的<link linkend="sec-printing-example">示例</link>。

en: Drawing Area - Text
zh_CN: 绘图区域 - 文本

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/pango_text">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/pango_text">源代码</ulink>

en: Drawing Images
zh_CN: 绘制图片

en: There is a method for drawing from a <classname>Gdk::Pixbuf</classname> to a <classname>Cairo::Context</classname>. A <classname>Gdk::Pixbuf</classname> buffer is a useful wrapper around a collection of pixels, which can be read from files, and manipulated in various ways.
zh_CN: 有一个方法可以将<classname>Gdk::Pixbuf</classname>绘制到<classname>Cairo::Context</classname>。<classname>Gdk::Pixbuf</classname>缓冲区是对像素集合的有效封装，它提供了从文件读取以及各种操纵像素的方式。

en: Probably the most common way of creating <classname>Gdk::Pixbuf</classname>s is to use <methodname>Gdk::Pixbuf::create_from_file()</methodname> or <methodname>Gdk::Pixbuf::create_from_resource()</methodname>, which can read an image file, such as a png file into a pixbuf ready for rendering.
zh_CN: 最常见的<classname>Gdk::Pixbuf</classname>创建方法是用<methodname>Gdk::Pixbuf::create_from_file()</methodname>或<methodname>Gdk::Pixbuf::create_from_resource()</methodname>，它们可以将图像文件（例如png文件）读取到pixbuf中用于渲染。

en: The <classname>Gdk::Pixbuf</classname> can be rendered by setting it as the source pattern of the Cairo context with <methodname>Gdk::Cairo::set_source_pixbuf()</methodname>. Then draw the image with either <methodname>Cairo::Context::paint()</methodname> (to draw the whole image), or <methodname>Cairo::Context::rectangle()</methodname> and <methodname>Cairo::Context::fill()</methodname> (to fill the specified rectangle). <methodname>set_source_pixbuf()</methodname> is not a member of <classname>Cairo::Context</classname>. It takes a <classname>Cairo::Context</classname> as its first parameter.
zh_CN: 通过使用<methodname>Gdk::Cairo::set_source_pixbuf()</methodname>将<classname>Gdk::Pixbuf</classname>设置为开罗上下文的源模式使其可以被渲染。然后使用<methodname>Cairo::Context::paint()</methodname>（画整个图像），或者使用<methodname>Cairo::Context::rectangle()</methodname>和<methodname>Cairo::Context::fill()</methodname>（用图像填充整个矩形）。<methodname>set_source_pixbuf()</methodname>不是<classname>Cairo::Context</classname>的成员函数。<classname>Cairo::Context</classname>是它的第一个参数。

en: Here is a small bit of code to tie it all together: (Note that usually you wouldn't load the image every time in the draw signal handler! It's just shown here to keep it all together.)
zh_CN: 这是一小段将他们结合在一起的代码（请注意，通常你不应该在每次调用绘制信号处理函数的时候都加载一次图片）：

en: Here is an example of a simple program that draws an image. The program loads the image from a resource file. See the <link linkend="sec-gio-resource">Gio::Resource and glib-compile-resources</link> section. Use <application>glib-compile-resources</application> to compile the resources into a C source file that can be compiled and linked with the C++ code. E.g. <_:screen-1/>
zh_CN: 这是一个绘制图像的简单示例程序。该程序从资源文件加载图像。请参阅<link linkend="sec-gio-resource">Gio::Resource和glib-compile-resources</link>小节。使用<application>glib-compile-resources</application>将资源文件编译为C源文件，然后将该源文件与C++代码一起编译链接。例如：<_:screen-1/>

en: Drawing Area - Image
zh_CN: 绘图区域 - 图像

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/image">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/image">源代码</ulink>

en: Example Application: Creating a Clock with Cairo
zh_CN: 示例程序：使用开罗创建时钟

en: Now that we've covered the basics of drawing with Cairo, let's try to put it all together and create a simple application that actually does something. The following example uses Cairo to create a custom <classname>Clock</classname> widget. The clock has a second hand, a minute hand, and an hour hand, and updates itself every second.
zh_CN: 既然我们已经将使用开罗画图的基础知识介绍完了，那么现在让我们尝试将所有的内容放在一起，创建一个可以执行某些操作的简单应用程序。以下示例使用开罗创建一个自定义的<classname>Clock</classname>部件。这个时钟有秒针、分针、时针，并且每一秒更新一次。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/clock">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drawingarea/clock">源代码</ulink>

en: As before, almost all of the interesting stuff is done in the draw function <methodname>on_draw()</methodname>. Before we dig into the draw function, notice that the constructor for the <classname>Clock</classname> widget connects a handler function <methodname>on_timeout()</methodname> to a timer with a timeout period of 1000 milliseconds (1 second). This means that <methodname>on_timeout()</methodname> will get called once per second. The sole responsibility of this function is to invalidate the window so that <application>gtkmm</application> will be forced to redraw it.
zh_CN: 和之前一样，所有有趣的东西都在绘图函数<methodname>on_draw()</methodname>中完成。在深入研究绘图函数之前，请注意在<classname>Clock</classname>部件的构造函数中将处理函数<methodname>on_timeout()</methodname>连接到了用计时器上，该计时器的超时时间为1000毫秒（1秒）。这意味着<methodname>on_timeout()</methodname>将每秒被调用一次。这个函数的唯一任务就是使窗口无效，以便<application>gtkmm</application>强制重绘它。

en: Now let's take a look at the code that performs the actual drawing. The first section of <methodname>on_draw()</methodname> should be pretty familiar by now. This example again scales the coordinate system to be a unit square so that it's easier to draw the clock as a percentage of window size so that it will automatically scale when the window size is adjusted. Furthermore, the coordinate system is scaled over and down so that the (0, 0) coordinate is in the very center of the window.
zh_CN: 现在让我们研究实际执行绘图的函数。到现在<methodname>on_draw()</methodname>函数的第一部分你应该很熟悉了。此示例再次将坐标系缩放为单位正方形，以便更轻松的按窗口大小的百分比绘制时钟。此外坐标系是按比例缩放的，所以(0,0)坐标位于窗口的正中央。

en: The function <methodname>Cairo::Context::paint()</methodname> is used here to set the background color of the window. This function takes no arguments and fills the current surface (or the clipped portion of the surface) with the source color currently active. After setting the background color of the window, we draw a circle for the clock outline, fill it with white, and then stroke the outline in black. Notice that both of these actions use the <methodname>_preserve</methodname> variant to preserve the current path, and then this same path is clipped to make sure that our next lines don't go outside the outline of the clock.
zh_CN: <methodname>Cairo::Context::paint()</methodname>方法用于设置窗口的背景色。这个函数不接受任何参数，并使用处于活跃状态的源颜色填充当前表面（或表面裁剪的一部分）。设置背景色以后，我们画一个圆作为时钟的轮廓，用白色填充它然后用黑色进行描边。请注意，这两个操作都用<methodname>_preserve</methodname>变体以保留当前路径，然后对相同的路径进行剪辑以确保我们下一行不会超过时钟的轮廓。

en: After drawing the outline, we go around the clock and draw ticks for every hour, with a larger tick at 12, 3, 6, and 9. Now we're finally ready to implement the time-keeping functionality of the clock, which simply involves getting the current values for hours, minutes and seconds, and drawing the hands at the correct angles.
zh_CN: 绘制轮廓后，我们围绕时钟为每个小时绘制可读线并为12、3、6、9绘制相对更大的刻度线。接着我们就可以实现时钟的计时功能了 -- 获取当前时间的时、分、秒然后以正确的角度将指针绘制出来。

en: <classname>Gtk::Widget</classname> has several methods and signals which are prefixed with "drag_". These are used for Drag and Drop.
zh_CN: <classname>Gtk::Widget</classname>提供了几个带有"drag_"前缀的方法和信号用以支持拖放。

en: Sources and Destinations
zh_CN: 源与目的地

en: Things are dragged from <literal>sources</literal> to be dropped on <literal>destinations</literal>. Each source and destination has information about the data formats that it can send or receive, provided by <classname>Gdk::ContentFormats</classname>. A drop destination will only accept a dragged item if they both share a compatible format. Appropriate signals will then be emitted, telling the signal handlers which format was used.
zh_CN: 物件从<literal>sources</literal>被拖放到<literal>destinations</literal>。每个源与目的地都拥有由<classname>Gdk::ContentFormats</classname>提供的它们所能发送或接受的数据格式的相关信息。放置目的地只会在拖动项与其具有共同的兼容类型时才会接受它们。然后将会发出适当的信号，告诉信号处理函数使用了那种格式。

en: <classname>Gdk::ContentFormats</classname> objects contain information about available <type>GType</type>s and mime types (media types).
zh_CN: <classname>Gdk::ContentFormats</classname>对象包含了可用的<type>GType</type>和MIME类型（媒体类型）的相关信息。

en: <classname>Widget</classname>s can be identified as sources or destinations using these <classname>Gtk::Widget</classname> methods:
zh_CN: <classname>Gtk::Widget</classname>的以下方法可以将<classname>Widget</classname>作为源或者目标：

en: <literal>targets</literal> is a <classname>Gdk::ContentFormats</classname> object.
zh_CN: <literal>targets</literal>是一个<classname>Gdk::ContentFormats</classname>对象。

en: <literal>start_button_mask</literal> is an ORed combination of values, which specify which modifier key or mouse button must be pressed to start the drag.
zh_CN: <literal>start_button_mask</literal>是一组值异或后的结果，用于指定按下哪个组合键或鼠标按键才能开始拖动。

en: <literal>actions</literal> is an ORed combination of values, which specify which Drag and Drop operations will be possible from this source - for instance, copy, move, or link. The user can choose between the actions by using modifier keys, such as <keycap>Shift</keycap> to change from <literal>copy</literal> to <literal>move</literal>, and this will be shown by a different cursor.
zh_CN: <literal>actions</literal>是一组值异或后的结果，用于指定可以对该源进行的拖放操作 - 例如复制、移动或链接。用户可以通过修饰键选择动作，比如通过按下<keycap>Shift</keycap>键将动作从<literal>copy</literal>改变为<literal>move</literal>，这还会使光标显示不同的样式。

en: <literal>flags</literal> is an ORed combination of values which indicates how the widget will respond visually to Drag and Drop items.
zh_CN: 是一组值异或后的结果，用于表示部件在视觉上如何响应拖放项。

en: <literal>actions</literal> indicates the Drag and Drop actions which this destination can receive - see the description above.
zh_CN: <literal>actions</literal>指示此目的地可以接受的拖放动作 - 请参阅上面的描述。

en: There are several methods to add source formats and destination formats. Examples: <_:itemizedlist-1/>
zh_CN: 有些添加源格式和目的地格式的方法。例如：<_:itemizedlist-1/>

en: When a drop destination has accepted a dragged item, certain signals will be emitted, depending on what action has been selected. For instance, the user might have held down the <keycap>Shift</keycap> key to specify a <literal>move</literal> rather than a <literal>copy</literal>. Remember that the user can only select the actions which you have specified in your calls to <methodname>drag_dest_set()</methodname> and <methodname>drag_source_set()</methodname>.
zh_CN: 当一个放置目的地接受了拖动项，根据被选择的动作，将发出响应的信号。例如，用户可能按住<keycap>Shift</keycap>键指定进行<literal>move</literal>而不是<literal>copy</literal>。请注意，用户只能选择你在调用<methodname>drag_dest_set()</methodname>和<methodname>drag_source_set()</methodname>时所指定的动作。

en: Copy
zh_CN: 复制

en: <literal>drag_begin</literal>: Provides a <classname>Gdk::Drag</classname>.
zh_CN: <literal>drag_begin</literal>：提供一个<classname>Gdk::Drag</classname>。

en: <literal>drag_data_get</literal>: Provides a <classname>Gdk::Drag</classname>, and a <classname>Gtk::SelectionData</classname> object, in which you should put the requested data.
zh_CN: <literal>drag_data_get</literal>：提供一个<classname>Gdk::Drag</classname>和一个<classname>Gtk::SelectionData</classname>对象，你应该在其中放入所请求的数据。

en: <literal>drag_end</literal>: Provides a <classname>Gdk::Drag</classname>.
zh_CN: <literal>drag_end</literal>：提供一个<classname>Gdk::Drag</classname>。

en: The source widget will emit these signals, in this order: <_:itemizedlist-1/>
zh_CN: 源部件将按以下顺序发出这些信号：<_:itemizedlist-1/>

en: <literal>drag_motion</literal>: Provides a <classname>Gdk::Drop</classname> and coordinates. You can call the <methodname>status()</methodname> method of the <classname>Gdk::Drop</classname> to indicate which action will be accepted.
zh_CN: <literal>drag_motion</literal>：提供一个<classname>Gdk::Drop</classname>以及坐标。你可以调用<classname>Gdk::Drop</classname>的<methodname>status()</methodname>方法来指示要接受的动作。

en: <literal>drag_drop</literal>: Provides a <classname>Gdk::Drop</classname> and coordinates. You can call <methodname>drag_get_data()</methodname>, which triggers the <literal>drag_data_get</literal> signal in the source widget, and then the <literal>drag_data_received</literal> signal in the destination widget.
zh_CN: <literal>drag_drop</literal>：提供一个<classname>Gdk::Drop</classname>以及坐标。你可以调用<methodname>drag_get_data()</methodname>，这将触发源部件的<literal>drag_data_get</literal>信号，并在之后触发目的地部件的<literal>drag_data_received</literal>信号。

en: <literal>drag_data_received</literal>: Provides a <classname>Gdk::Drop</classname>, and a <methodname>Gtk::SelectionData</methodname> object which contains the dropped data. You should call the <methodname>finish()</methodname> or <methodname>failed()</methodname> method of the <classname>Gdk::Drop</classname> to indicate whether the operation was successful.
zh_CN: <literal>drag_data_received</literal>：提供一个<classname>Gdk::Drop</classname>和一个包含要放置的数据的<methodname>Gtk::SelectionData</methodname>对象。你应该调用<classname>Gdk::Drop</classname>的<methodname>finish()</methodname>或<methodname>failed()</methodname>方法来指示操作是否成功。

en: The destination widget will emit these signals, in this order: <_:itemizedlist-1/>
zh_CN: 目的地部件将按以下顺序发出这些信号：<_:itemizedlist-1/>

en: Move
zh_CN: 移动

en: <literal>drag_data_delete</literal>: Gives the source the opportunity to delete the original data if that's appropriate.
zh_CN: <literal>drag_data_delete</literal>：给源删除原始数据的合适时机。

en: During a <literal>move</literal>, the source widget will also emit this signal: <_:itemizedlist-1/>
zh_CN: 在<literal>move</literal>的过程中，源部件还将会发出以下信号：<_:itemizedlist-1/>

en: Here is a very simple example, demonstrating a drag and drop <literal>Copy</literal> operation:
zh_CN: 这是一个非常简单的示例，演示了拖放的<literal>Copy</literal>操作：

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drag_and_drop">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/drag_and_drop">源代码</ulink>

en: There is a more complex example in examples/others/dnd.
zh_CN: 在examples/others/dnd中有一个更复杂的示例。

en: The Clipboard
zh_CN: 剪切板(Clipboard)

en: Simple text copy-paste functionality is provided for free by widgets such as <classname>Gtk::Entry</classname> and <classname>Gtk::TextView</classname>, but you might need special code to deal with your own data formats. For instance, a drawing program would need special code to allow copy and paste within a view, or between documents.
zh_CN: <classname>Gtk::Entry</classname>和<classname>Gtk::TextView</classname>之类的部件提供了简单的文本复制粘贴功能，但如果你有自己的数据格式需要处理则需要为此编写特定的代码。例如，绘图程序需要编写特定的代码以支持在视图内或文档之间进行复制粘贴。

en: You can get a clipboard instance with <methodname>Gtk::Widget::get_clipboard()</methodname> or <methodname>Gdk::Display::get_clipboard()</methodname>.
zh_CN: 你可以使用<methodname>Gtk::Widget::get_clipboard()</methodname>或<methodname>Gdk::Display::get_clipboard()</methodname>获取剪切板实例。

en: Your application doesn't need to wait for clipboard operations, particularly between the time when the user chooses Copy and then later chooses Paste. Many <classname>Gdk::Clipboard</classname> methods take <classname>sigc::slot</classname>s which specify callback methods. When <classname>Gdk::Clipboard</classname> is ready, it will call these methods, providing the requested data.
zh_CN: 你的应用程序不需要等待剪切板操作，特别是用户选择复制然后选择粘贴的期间。<classname>Gdk::Clipboard</classname>的多数方法使用<classname>sigc::slot</classname>，它们指定了回调函数。当<classname>Gdk::Clipboard</classname>准备就绪时，它将会调用这些回调函数，并向其提供所请求的数据。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGdk_1_1Clipboard.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGdk_1_1Clipboard.html">参考</ulink>

en: Formats
zh_CN: 格式

en: Different applications contain different types of data, and they might make that data available in a variety of formats. <application>gtkmm</application> calls these data types <literal>format</literal>s.
zh_CN: 不同的应用程序包含不同类型的数据，并且它们可能使用多种可用格式提供数据。<application>gtkmm</application>称这些数据类型为<literal>format</literal>。

en: For instance, <application>gedit</application> can supply and receive the <literal>text/plain</literal> mime type, so you can paste data into <application>gedit</application> from any application that supplies that format. Or two different image editing applications might supply and receive a variety of image formats. As long as one application can receive one of the formats that the other supplies then you will be able to copy data from one to the other.
zh_CN: 例如，<application>gedit</application>可以提供和接收<literal>text/plain</literal>MIME类型，所以你可以从任何提供该格式的应用程序中将复制粘贴给<application>gedit</application>。或者两个不同的图像编辑程序可能会提供和接收各种图像格式。只要其中一个应用程序可以接收其他应用程序提供的一种格式，那么你就可以将数据从一个复制到另一个。

en: Clipboard data can be in a variety of binary formats. This chapter, and the examples, assume that the data is 8-bit text. This would allow us to use an XML format for the clipboard data. However this would probably not be appropriate for binary data such as images.
zh_CN: 剪切板数据可以使用多种二进制格式。本章和示例程序假定数据是8位文本。这将使我们可以对剪切板数据使用XML格式。但这可能不适合二进制数据（例如图像）。

en: The <link linkend="chapter-draganddrop">Drag and Drop</link> API uses the same mechanism. You should probably use the same data formats for both Clipboard and Drag and Drop operations.
zh_CN: <link linkend="chapter-draganddrop">拖放</link>API使用一样的机制。剪切板和拖放操作都应该使用一样的数据格式。

en: When the user asks to copy some data, you should copy the data to the <classname>Clipboard</classname>. For instance,
zh_CN: 当用户要复制某些数据的时候，你应该将数据复制到<classname>Clipboard</classname>。例如：

en: Paste
zh_CN: 粘贴

en: When the user asks to paste data from the <classname>Clipboard</classname>, you should request a specific format and provide a callback method which will be called with the actual data. For instance:
zh_CN: 当用户要从<classname>Clipboard</classname>中粘贴数据时，你应该请求一种特定的格式并提供一个回调函数，该回调函数将与实际数据一并被调用。例如：

en: Here is an example callback method:
zh_CN: 这是一个回调函数的示例：

en: Discovering the available formats
zh_CN: 发现可用格式

en: To find out what formats are currently available on the <classname>Clipboard</classname> for pasting, call the <methodname>get_formats()</methodname> method. Then call a <classname>Gdk::ContentFormats</classname> method to find out if a format that your application supports is available.
zh_CN: 要找出当前<classname>Clipboard</classname>可以用于粘贴的格式，请调用<methodname>get_formats()</methodname>方法。然后调用<classname>Gdk::ContentFormats</classname>方法来确定你的应用程序所支持的格式是否可用。

en: Simple
zh_CN: 简单

en: This example allows copy and pasting of application-specific data, using the standard text format. Although this is simple, it's not ideal because it does not identify the <classname>Clipboard</classname> data as being of a particular type.
zh_CN: 这个示例允许使用标准文本格式复制粘贴应用程序指定的数据。尽管着很简单，但是它并不够理想，因为他不能将<classname>Clipboard</classname>的数据标识为特定的类型。

en: Clipboard - Simple
zh_CN: 剪切板 - 简单

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/clipboard/simple/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/clipboard/simple/">源代码</ulink>

en: Ideal
zh_CN: 理想

en: Defines a custom clipboard target, though the format is still text.
zh_CN: 定义了一个自定义剪切板目标，尽管格式依旧是文本。

en: It uses the <methodname>Gdk::ContentFormats::signal_changed()</methodname> signal and disables the Paste button if it can't use anything on the clipboard.
zh_CN: 它使用<methodname>Gdk::ContentFormats::signal_changed()</methodname>信号并在剪切板不可用的时候禁用粘贴按钮。

en: This is like the simple example, but it <_:orderedlist-1/>
zh_CN: 这个与简单示例类型，但是它<_:orderedlist-1/>

en: Clipboard - Ideal
zh_CN: 剪切板 - 理想

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/clipboard/ideal/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/clipboard/ideal/">源代码</ulink>

en: Printing
zh_CN: 打印

en: At the application development level, <application>gtkmm</application>'s printing API provides dialogs that are consistent across applications and allows use of Cairo's common drawing API, with Pango-driven text rendering. In the implementation of this common API, platform-specific backends and printer-specific drivers are used.
zh_CN: 在应用程序级开发，<application>gtkmm</application>的打印API提供了跨应用程序兼容的对话框，并允许使用开罗通用绘制API和Pango驱动的文本渲染。在此通用API实现中，使用了特定平台的后端和特定打印机的驱动。

en: PrintOperation
zh_CN: 打印操作

en: The primary object is <classname>Gtk::PrintOperation</classname>, allocated for each print operation. To handle page drawing connect to its signals, or inherit from it and override the default virtual signal handlers. <classname>PrintOperation</classname> automatically handles all the settings affecting the print loop.
zh_CN: 主要对象是分配给每个打印操作的<classname>Gtk::PrintOperation</classname>。要处理绘制页请连接到它的信号，或从其继承并覆盖默认的虚信号处理函数。<classname>PrintOperation</classname>将自动处理所有影响打印循环的设置。

en: <literal>begin_print</literal>: You must handle this signal, because this is where you create and set up a <classname>Pango::Layout</classname> using the provided <classname>Gtk::PrintContext</classname>, and break up your printing output into pages.
zh_CN: <literal>begin_print</literal>：你必须处理该信号，因为这是你使用提供的<classname>Gtk::PrintContext</classname>创建和设置<classname>Pango::Layout</classname>的地方，以及对你的打印输出进行分页的地方。

en: <literal>paginate</literal>: Pagination is potentially slow so if you need to monitor it you can call the <methodname>PrintOperation::set_show_progress()</methodname> method and handle this signal.
zh_CN: <literal>paginate</literal>：分页可能很慢，所以如果需要监视它，你可以调用<methodname>PrintOperation::set_show_progress()</methodname>方法并处理此信号。

en: <literal>request_page_setup</literal>: Provides a <classname>PrintContext</classname>, page number and <classname>Gtk::PageSetup</classname>. Handle this signal if you need to modify page setup on a per-page basis.
zh_CN: <literal>request_page_setup</literal>：提供一个<classname>PrintContext</classname>、页码和<classname>Gtk::PageSetup</classname>。如果你需要逐页的修改页面设置，请处理此信号。

en: <literal>draw_page</literal>: You must handle this signal, which provides a <classname>PrintContext</classname> and a page number. The <classname>PrintContext</classname> should be used to create a <classname>Cairo::Context</classname> into which the provided page should be drawn. To render text, iterate over the <classname>Pango::Layout</classname> you created in the <literal>begin_print</literal> handler.
zh_CN: <literal>draw_page</literal>：你必须处理此信号，该信号提供一个<classname>PrintContext</classname>和页码。你应该使用<classname>PrintContext</classname>创建一个<classname>Cairo::Context</classname>，并将提供的页面绘制到其中。要渲染文本，请遍历你在<literal>begin_print</literal>处理程序中创建的<classname>Pango::Layout</classname>。

en: For each page that needs to be rendered, the following signals are emitted: <_:itemizedlist-1/>
zh_CN: 对于每个要渲染的页面，都会发出以下信号：<_:itemizedlist-1/>

en: <literal>end_print</literal>: A handler for it is a safe place to free any resources related to a <classname>PrintOperation</classname>. If you have your custom class that inherits from <classname>PrintOperation</classname>, it is naturally simpler to do it in the destructor.
zh_CN: <literal>end_print</literal>：它的处理程序是用于释放与<classname>PrintOperation</classname>相关的所有资源的安全场所。如果你通过继承<classname>PrintOperation</classname>创建了自定义类，则直接在自定义类的析构函数中进行此操作会更简单。

en: <literal>done</literal>: This signal is emitted when printing is finished, meaning when the print data is spooled. Note that the provided <literal>Gtk::PrintOperationResult</literal> may indicate that an error occurred. In any case you probably want to notify the user about the final status.
zh_CN: <literal>done</literal>：该信号于打印完成时（当打印数据假脱机）被发出。请注意，所提供的<literal>Gtk::PrintOperationResult</literal>可能表明发生了错误。无论如何你都应该让用户知道最终的状态。

en: <literal>status_changed</literal>: Emitted whenever a print job's status changes, until it is finished. Call the <methodname>PrintOperation::set_track_print_status()</methodname> method to monitor the job status after spooling. To see the status, use <methodname>get_status()</methodname> or <methodname>get_status_string()</methodname>.
zh_CN: <literal>status_changed</literal>: 直到打印作业完成，只要打印作业状态发生了更改就会发出此信号。假脱机后可以调用<methodname>PrintOperation::set_track_print_status()</methodname>监视作业状态。要查看状态请调用<methodname>get_status()</methodname>或<methodname>get_status_string()</methodname>。

en: The <methodname>PrintOperation::run()</methodname> method starts the print loop, during which various signals are emitted: <_:itemizedlist-1/>
zh_CN: <methodname>PrintOperation::run()</methodname>方法启动打印循环，在此期间会发出以下信号：<_:itemizedlist-1/>

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1PrintOperation.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1PrintOperation.html">参考</ulink>

en: Page setup
zh_CN: 页面设置

en: The <classname>PrintOperation</classname> class has a method called <methodname>set_default_page_setup()</methodname> which selects the default paper size, orientation and margins. To show a page setup dialog from your application, use the <methodname>Gtk::run_page_setup_dialog()</methodname> method, which returns a <classname>Gtk::PageSetup</classname> object with the chosen settings. Use this object to update a <classname>PrintOperation</classname> and to access the selected <classname>Gtk::PaperSize</classname>, <literal>Gtk::PageOrientation</literal> and printer-specific margins.
zh_CN: <classname>PrintOperation</classname>类有一个叫做<methodname>set_default_page_setup()</methodname>的方法，其用于选择默认的纸张尺寸、方向和页边距。要在你的应用程序中显示页面设置对话框，请使用<methodname>Gtk::run_page_setup_dialog()</methodname>方法，该方法返回一个<classname>Gtk::PageSetup</classname>对象，这个对象保存了所选的设置。使用这个对象更新<classname>PrintOperation</classname>并访问所选的<classname>Gtk::PaperSize</classname>、<literal>Gtk::PageOrientation</literal>和特定打印机的边距。

en: You should save the chosen <classname>Gtk::PageSetup</classname> so you can use it again if the page setup dialog is shown again.
zh_CN: 你应该保存所选的<classname>Gtk::PageSetup</classname>以便在下次打开页面设置对话框的时候使用。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1PageSetup.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1PageSetup.html">参考</ulink>

en: The Cairo coordinate system, in the <literal>draw_page</literal> handler, is automatically rotated to the current page orientation. It is normally within the printer margins, but you can change that via the <methodname>PrintOperation::set_use_full_page()</methodname> method. The default measurement unit is device pixels. To select other units, use the <methodname>PrintOperation::set_unit()</methodname> method.
zh_CN: 在<literal>draw_page</literal>处理程序中，开罗坐标系会自动旋转到当前页的方向。它通常在打印机的页边距之内，不过你可以使用<methodname>PrintOperation::set_use_full_page()</methodname>方法来更改它。默认的度量单位是设备像素。要选择其他单位请使用<methodname>PrintOperation::set_unit()</methodname>方法。

en: Rendering text
zh_CN: 渲染文本

en: Text rendering is done using Pango. The <classname>Pango::Layout</classname> object for printing should be created by calling the <methodname>PrintContext::create_pango_layout()</methodname> method. The <classname>PrintContext</classname> object also provides the page metrics, via <methodname>get_width()</methodname> and <methodname>get_height()</methodname>. The number of pages can be set with <methodname>PrintOperation::set_n_pages()</methodname>. To actually render the Pango text in <literal>on_draw_page</literal>, get a <classname>Cairo::Context</classname> with <methodname>PrintContext::get_cairo_context()</methodname> and show the <classname>Pango::LayoutLine</classname>s that appear within the requested page number.
zh_CN: 文本渲染是使用Pango完成的。<classname>Pango::Layout</classname>对象应通过调用<methodname>PrintContext::create_pango_layout()</methodname>方法来创建。<classname>PrintContext</classname>对象还通过<methodname>get_width()</methodname>和<methodname>get_height()</methodname>方法提供了页面范围。页数可以通过调用<methodname>PrintOperation::set_n_pages()</methodname>进行设置。要在<literal>on_draw_page</literal>中渲染文本，请使用<methodname>PrintContext::get_cairo_context()</methodname>获取<classname>Cairo::Context</classname>并显示在请求的页码中出现的<classname>Pango::LayoutLine</classname>。

en: See <link linkend="sec-printing-example-simple">an example</link> of exactly how this can be done.
zh_CN: 请看<link linkend="sec-printing-example-simple">具体示例</link>如何做到这点。

en: Asynchronous operations
zh_CN: 异步操作

en: By default, <methodname>PrintOperation::run()</methodname> returns when a print operation is completed. If you need to run a non-blocking print operation, call <methodname>PrintOperation::set_allow_async()</methodname>. Note that <methodname>set_allow_async()</methodname> is not supported on all platforms, however the <literal>done</literal> signal will still be emitted.
zh_CN: 在默认情况下，<methodname>PrintOperation::run()</methodname>在打印操作完成时返回。如果你需要运行非阻塞的打印操作，请调用<methodname>PrintOperation::set_allow_async()</methodname>。请注意，并非所有平台都支持<methodname>set_allow_async()</methodname>，但<literal>done</literal>信号仍然会被发出。

en: <methodname>run()</methodname> may return <literal>PrintOperation::Result::IN_PROGRESS</literal>. To track status and handle the result or error you need to implement signal handlers for the <literal>done</literal> and <literal>status_changed</literal> signals:
zh_CN: <methodname>run()</methodname>可能会返回<literal>PrintOperation::Result::IN_PROGRESS</literal>。要跟踪状态并处理结果或错误，你需要实现<literal>done</literal>和<literal>status_changed</literal>信号的信号处理函数。

en: Second, check for an error and connect to the <literal>status_changed</literal> signal. For instance:
zh_CN: 然后，检查错误并连接到<literal>status_changed</literal>信号，例如：

en: Finally, check the status. For instance,
zh_CN: 最后检查状态。例如：

en: Export to PDF
zh_CN: 导出为PDF

en: The 'Print to file' option is available in the print dialog, without the need for extra implementation. However, it is sometimes useful to generate a pdf file directly from code. For instance,
zh_CN: "打印到文件"选项在打印对话框可用，不需要额外实现。但是有时候从代码直接生成PDF文件会很有用。例如：

en: Extending the print dialog
zh_CN: 扩展打印对话框

en: Set the title of the tab via <methodname>PrintOperation::set_custom_tab_label()</methodname>, create a new widget and return it from the <literal>create_custom_widget</literal> signal handler. You'll probably want this to be a container widget, packed with some others.
zh_CN: 通过<methodname>PrintOperation::set_custom_tab_label()</methodname>设置标签的标题，创建一个新的部件然后从<literal>create_custom_widget</literal>的信号处理函数中返回它。你可能希望它是一个容器部件，在其中包含一些其他部件。

en: Get the data from the widgets in the <literal>custom_widget_apply</literal> signal handler.
zh_CN: 从部件的<literal>custom_widget_apply</literal>的信号处理函数中获取数据。

en: You may add a custom tab to the print dialog: <_:itemizedlist-1/>
zh_CN: 你可以在打印对话框中添加自定义标签： <_:itemizedlist-1/>

en: Although the <literal>custom_widget_apply</literal> signal provides the widget you previously created, to simplify things you can keep the widgets you expect to contain some user input as class members. For example, let's say you have a <classname>Gtk::Entry</classname> called <literal>m_Entry</literal> as a member of your <classname>CustomPrintOperation</classname> class:
zh_CN: 尽管<literal>custom_widget_apply</literal>信号提供了你之前创建的部件，但是为了简化操作，你可以保存一些用户输入作为部件类的成员。例如，你可能希望你有一个叫做<literal>m_Entry</literal>的<classname>Gtk::Entry</classname>拥有<classname>CustomPrintOperation</classname>作为类成员：

en: The example in examples/book/printing/advanced demonstrates this.
zh_CN: examples/book/printing/advanced示例对此进行了演示。

en: Preview
zh_CN: 预览

en: The native GTK print dialog has a preview button, but you may also start a preview directly from an application:
zh_CN: 原生的GTK打印对话框有一个预览按钮，但是你也可以自己从应用程序开始预览：

en: On Unix, the default preview handler uses an external viewer program. On Windows, the native preview dialog will be shown. If necessary you may override this behaviour and provide a custom preview dialog. See the example located in /examples/book/printing/advanced.
zh_CN: 在Unix上，默认的预览处理程序将使用外部查看器程序。在Windows上将显示原生预览对话框。如果有必要，你可以覆盖此默认行为并为此提供一个自定义的预览对话框。请参阅位于/examples/book/printing/advanced的示例。

en: The following example demonstrates how to print some input from a user interface. It shows how to implement <literal>on_begin_print</literal> and <literal>on_draw_page</literal>, as well as how to track print status and update the print settings.
zh_CN: 以下示例演示了如何从用户界面打印一些输出。它显示了如何实现<literal>on_begin_print</literal>和<literal>on_draw_page</literal>，以及如何跟踪打印状态和更新打印设置。

en: Printing - Simple
zh_CN: 打印 - 简单

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/printing/simple/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/printing/simple/">源代码</ulink>

en: Recently Used Documents
zh_CN: 最近使用过的文件

en: <application>gtkmm</application> provides an easy way to manage recently used documents. This functionality is implemented in the <classname>Gtk::RecentManager</classname> class.
zh_CN: <application>gtkmm</application>提供了一种管理最近使用文件的简便方法。该功能在<classname>Gtk::RecentManager</classname>类中实现。

en: Each item in the list of recently used files is identified by its URI, and can have associated metadata. The metadata can be used to specify how the file should be displayed, a description of the file, its mime type, which application registered it, whether it's private to the registering application, and several other things.
zh_CN: 最近使用文件列表中的每一项都由其URI进行标识，并可以具有相关的元数据。元数据可以用于指定如何显示文件、如何描述文件、及其它的MIME类型、哪个应用程序注册了它、对于注册的应用程序是不是私有的等。

en: RecentManager
zh_CN: 最近管理器(RecentManager)

en: <classname>RecentManager</classname> acts as a database of recently used files. You use this class to register new files, remove files from the list, or look up recently used files. There is one list of recently used files per user.
zh_CN: <classname>RecentManager</classname>充当最近使用文件的数据库。你可以使用此类注册新文件、从列表中删除文件、查找最近使用文件。每个用户都拥有一个最近使用的文件列表。

en: You can create a new <classname>RecentManager</classname>, but you'll most likely just want to use the default one. You can get a reference to the default <classname>RecentManager</classname> with <methodname>get_default()</methodname>.
zh_CN: 你可以创建一个新的<classname>RecentManager</classname>，但你可能只想用默认的那个。你可以通过<methodname>get_default()</methodname>获取默认<classname>RecentManager</classname>的引用。

en: Adding Items to the List of Recent Files
zh_CN: 将项目添加到最近文件列表

en: To add a new file to the list of recent documents, in the simplest case, you only need to provide the URI. For example:
zh_CN: 在最简单的情况下，要添加项目到最近文件列表只需要提供一个URI即可。例如：

en: If you want to register a file with metadata, you can pass a <classname>RecentManager::Data</classname> parameter to <methodname>add_item()</methodname>. The metadata that can be set on a particular file item is as follows:
zh_CN: 如果你想要使用元数据注册一个文件，你可以将<classname>RecentManager::Data</classname>参数传递给<methodname>add_item()</methodname>。可以在特定的文件项上设置的元数据如下所示：

en: <varname>app_exec</varname>: The command line to be used to launch this resource. This string may contain the "f" and "u" escape characters which will be expanded to the resource file path and URI respectively
zh_CN: <varname>app_exec</varname>：用于启动此资源的命令行。此字符串可以包含"f"和"u"转义字符，它们将分别扩展为资源文件路径和URI

en: <varname>app_name</varname>: The name of the application that registered the resource
zh_CN: <varname>app_name</varname>：此资源注册的应用程序名

en: <varname>description</varname>: A short description of the resource as a UTF-8 encoded string
zh_CN: <varname>description</varname>：资源的简单描述（UTF-8编码字符串）

en: <varname>display_name</varname>: The name of the resource to be used for display as a UTF-8 encoded string
zh_CN: <varname>display_name</varname>：用于显示的资源名（UTF-8编码字符串）

en: <varname>groups</varname>: A list of groups associated with this item. Groups are essentially arbitrary strings associated with a particular resource. They can be thought of as 'categories' (such as "email", "graphics", etc) or tags for the resource.
zh_CN: <varname>groups</varname>：与该项相关联的组列表。组本质上是与特定资源相关联的任意字符串。可以将它们视为资源的类别（例如：电子邮件、图形等）或标签

en: <varname>is_private</varname>: Whether this resource should be visible only to applications that have registered it or not
zh_CN: <varname>is_private</varname>：此资源是否仅对已注册该资源的应用程序可见

en: <varname>mime_type</varname>: The MIME type of the resource
zh_CN: <varname>mime_type</varname>：此资源的MIME类型

en: In addition to adding items to the list, you can also look up items from the list and modify or remove items.
zh_CN: 除了向列表中添加项目以外，你还可以从列表项中删除、修改、查找项目。

en: Looking up Items in the List of Recent Files
zh_CN: 在最近文件列表中查找项目

en: To look up recently used files, <classname>RecentManager</classname> provides several functions. To look up a specific item by its URI, you can use the <methodname>lookup_item()</methodname> function, which will return a <classname>RecentInfo</classname> class. If the specified URI did not exist in the list of recent files, <methodname>lookup_item()</methodname> throws a <classname>RecentManagerError</classname> exception. For example:
zh_CN: <classname>RecentManager</classname>提供了几个函数用以查找最近使用过的文件。你可以使用<methodname>lookup_item()</methodname>函数通过URI来查找特定项目，该函数将返回一个<classname>RecentInfo</classname>类对象。如果指定的URI于最近文件列表中不存在，则<methodname>lookup_item()</methodname>将抛出一个<classname>RecentManagerError</classname>异常。例如：

en: A <classname>RecentInfo</classname> object is essentially an object containing all of the metadata about a single recently-used file. You can use this object to look up any of the properties listed <link linkend="list-file-metadata">above</link>.
zh_CN: 本质上，<classname>RecentInfo</classname>是个包含了一个最近使用文件的所有元数据的对象。你可以使用该对象查找<link linkend="list-file-metadata">这里</link>所列出的任何属性。

en: If you don't want to look for a specific URI, but instead want to get a list of all recently used items, <classname>RecentManager</classname> provides the <methodname>get_items()</methodname> function. The return value of this function is a <classname>std::vector</classname> of all recently used files. The following code demonstrates how you might get a list of recently used files:
zh_CN: 如果你不想要查找一个特定的URI，而是想获取整个最近使用的项目列表，<classname>RecentManager</classname>为此提供了<methodname>get_items()</methodname>函数。这个函数返回值是一个<classname>std::vector</classname>，其包含了所有最近使用的文件。以下代码演示了你该如何获取最近使用文件列表：

en: The maximum age of items in the recently used files list can be set with <methodname>Gtk::Settings::property_gtk_recent_files_max_age()</methodname>. Default value: 30 days.
zh_CN: 可以使用<methodname>Gtk::Settings::property_gtk_recent_files_max_age()</methodname>设置最近使用文件列表中项目的最长使用期限。默认时长是：30天。

en: Modifying the List of Recent Files
zh_CN: 修改最近使用文件列表

en: There may be times when you need to modify the list of recent files. For instance, if a file is moved or renamed, you may need to update the file's location in the recent files list so that it doesn't point to an incorrect location. You can update an item's location by using <methodname>move_item()</methodname>.
zh_CN: 有时候你会需要修改最近使用文件列表。例如，当一个文件被移动或重命名，你需要更新该文件在最近使用文件列表中的位置，以使其不会指向错误的位置。你可以使用<methodname>move_item()</methodname>来更新项目的位置。

en: In addition to changing a file's URI, you can also remove items from the list, either one at a time or by clearing them all at once. The former is accomplished with <methodname>remove_item()</methodname>, the latter with <methodname>purge_items()</methodname>.
zh_CN: 除了更改文件的URI以外，你还可以从列表中删除项目或是一次性清除所有项目。前者使用<methodname>remove_item()</methodname>，后者使用<methodname>purge_items()</methodname>。

en: The functions <methodname>move_item()</methodname>, <methodname>remove_item()</methodname> and <methodname>purge_items()</methodname> have no effect on the actual files that are referred to by the URIs, they only modify the list of recent files.
zh_CN: <methodname>move_item()</methodname>、<methodname>remove_item()</methodname>和<methodname>purge_items()</methodname>并不影响URI所引用的真实文件，它们只是对最近文件列表进行修改。

en: <classname>FileChooser</classname> is an interface that can be implemented by widgets displaying a list of files. <application>gtkmm</application> provides three built-in implementations for choosing recent files or other files: <classname>FileChooserWidget</classname>, <classname>FileChooserDialog</classname>, and <classname>FileChooserNative</classname>.
zh_CN: <classname>FileChooser</classname>是一个可以由用于显示文件列表的部件实现的接口。<application>gtkmm</application>提供了三种用于选择最近文件或其他文件的内置实现：<classname>FileChooserWidget</classname>、<classname>FileChooserDialog</classname>、<classname>FileChooserNative</classname>。

en: <classname>FileChooserWidget</classname> is a simple widget for displaying a list of recently used files or other files. <classname>FileChooserWidget</classname> is the basic building block for <classname>FileChooserDialog</classname>, but you can embed it into your user interface if you want to.
zh_CN: <classname>FileChooserWidget</classname>是一个用于显示最近使用文件列表或其他文件的简单部件。<classname>FileChooserWidget</classname>是<classname>FileChooserDialog</classname>的基本构建块，但是你根据需要可以将其嵌入到用户界面中。

en: Simple FileChooserDialog example
zh_CN: 简单的文件选择对话框示例

en: Shown below is a simple example of how to use the <classname>FileChooserDialog</classname> class in a program. This simple program has a menubar with a <guimenuitem>File Chooser Dialog</guimenuitem> menu item. When you select this menu item, a dialog pops up showing a list of files. If you select <guimenuitem>Recent</guimenuitem> in the sidebar, the list of recently used files is shown.
zh_CN: 下面显示的是一个如何在程序中使用<classname>FileChooserDialog</classname>类的简单示例。这个简单示例程序有一个带有<guimenuitem>File Chooser Dialog</guimenuitem>菜单项的菜单栏。选择此菜单项时，将弹出一个显示文件列表的对话框。如果你选中侧边栏的<guimenuitem>Recent</guimenuitem>，则对话框将显示最近使用文件列表。

en: If this is the first time you're using a program that uses the Recent Files framework, the dialog may be empty at first. Otherwise it should show the list of recently used documents registered by other applications.
zh_CN: 如果这是你第一次使用使用了最近文件框架的应用程序，那么对话框最初可能是空的。否则它应该显示其他应用程序注册的最近使用文件列表。

en: After selecting the <guimenuitem>File Chooser Dialog</guimenuitem> menu item and the <guimenuitem>Recent</guimenuitem> sidebar item, you should see something similar to the following window.
zh_CN: 选择<guimenuitem>File Chooser Dialog</guimenuitem>菜单项和<guimenuitem>Recent</guimenuitem>侧边项后，你将看到与下方窗口类似的内容。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/recent_files">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/recent_files">源代码</ulink>

en: The constructor for <classname>ExampleWindow</classname> creates the menu and the toolbar using <classname>Builder</classname> (see <xref linkend="chapter-menus-and-toolbars"/> for more information). It then adds the menu and the toolbar to the window.
zh_CN: <classname>ExampleWindow</classname>的构造函数使用<classname>Builder</classname>创建菜单和工具栏（更多有关信息请参阅<xref linkend="chapter-menus-and-toolbars"/>）。然后将菜单和工具栏添加到窗口中。

en: Filtering Files
zh_CN: 筛选文件

en: For any of the <classname>FileChooser</classname> classes, if you don't wish to display all of the items in the list of files, you can filter the list to show only those that you want. You can filter the list with the help of the <classname>FileFilter</classname> class. This class allows you to filter files by their name (<methodname>add_pattern()</methodname>), or their mime type (<methodname>add_mime_type()</methodname>).
zh_CN: 对于任意<classname>FileChooser</classname>类，如果你不想显示文件列表中的所有项目，你可以筛选列表以仅显示所需的项目。你可以使用<classname>FileFilter</classname>帮助你对列表进行筛选。这个类允许你按文件名（<methodname>add_pattern()</methodname>）或MIME类型（<methodname>add_mime_type()</methodname>）筛选文件。

en: After you've created and set up the filter to match only the items you want, you can apply a filter to a chooser widget with the <methodname>FileChooser::add_filter()</methodname> function.
zh_CN: 创建并设置筛选器以使其只匹配你所需项目之后，你可以使用<methodname>FileChooser::add_filter()</methodname>函数将筛选器应用于你所选的部件。

en: Keyboard Events
zh_CN: 键盘事件

en: X events differ in some ways from other signals. These differences are described in the <link linkend="sec-xeventsignals">X Event signals</link> section in the appendix. Here we will use keyboard events to show how X events can be used in a program.
zh_CN: X事件与其他信号在某些方面有所不同。这些差异在附录的<link linkend="sec-xeventsignals">X事件信号</link>小节中说明。在这，我们将使用键盘事件说明如何在程序中使用X事件。

en: Overview
zh_CN: 总览

en: Whenever you press or release a key, an event is emitted. You can connect a signal handler to handle such events.
zh_CN: 每当你按下或放开一个按键，就会发出一个事件。你可以连接到信号处理函数来处理此类事件。

en: The event signal handler will receive an argument that depends on the type of event. For keyboard events it's a <type>GdkEventKey*</type>. As discribed in the <link linkend="sec-xeventsignals">appendix</link>, the event signal handler returns a <type>bool</type> value, to indicate that the signal is fully handled (<literal>true</literal>) or allow event propagation (<literal>false</literal>).
zh_CN: 事件处理函数接受的参数取决于事件的类型。对于键盘事件，它接受一个<type>GdkEventKey*</type>参数。如<link linkend="sec-xeventsignals">附录</link>中所述，事件处理函数返回一个<type>bool</type>值，以表示信号已经被完全处理（返回<literal>true</literal>）或允许事件传播（<literal>false</literal>）。

en: To determine which key was pressed or released, you read the value of <varname>GdkEventKey::keyval</varname> and compare it with a constant in the <filename>&lt;gdk/gdkkeysyms.h&gt;</filename> header file. The states of modifier keys (shift, ctrl, etc.) are available as bit-flags in <varname>GdkEventKey::state</varname>.
zh_CN: 要确定哪个键被按下或放开，你需要读取<varname>GdkEventKey::keyval</varname>的值并将其与头文件<filename>&lt;gdk/gdkkeysyms.h&gt;</filename>中的常量进行比较。<varname>GdkEventKey::state</varname>的位标志可以用作表示修饰键（shift、ctrl等）的状态。

en: Here's a simple example:
zh_CN: 这是一个简单的例子：

en: In this example there are three keyboard shortcuts: <keycap>Alt</keycap>+<keycap>1</keycap> selects the first radio button, <keycap>Alt</keycap>+<keycap>2</keycap> selects the second one, and the <keycap>Esc</keycap> key hides (closes) the window. The default event signal handler is overridden, as described in the <link linkend="sec-overriding-default-signal-handlers">Overriding default signal handlers</link> section in the appendix.
zh_CN: 在此示例中，有三个键盘快捷键：<keycap>Alt</keycap>+<keycap>1</keycap>选择第一个单选按钮、<keycap>Alt</keycap>+<keycap>2</keycap>选择第二个单选按钮、<keycap>Esc</keycap>隐藏（关闭）窗口。默认信号处理程序被覆盖如附录中<link linkend="sec-overriding-default-signal-handlers">覆盖默认信号处理程序</link>小节所述。

en: Keyboard Events - Simple
zh_CN: 键盘事件 - 简单

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/keyboard_events/simple/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/keyboard_events/simple/">源代码</ulink>

en: Event Propagation
zh_CN: 事件传播

en: Event propagation means that, when an event is emitted on a particular widget, it can be passed to its parent widget (and that widget can pass it to its parent, and so on) and, if the parent has an event handler, that handler will be called.
zh_CN: 事件传播意味着，当事件在特定的部件中发出时，它可以被传递到该部件的父部件（这个部件又可以将信号传递给它的父部件，以此类推），如果父部件有对该事件的事件处理程序，该处理程序将被调用。

en: Contrary to other events, keyboard events are first sent to the toplevel window (<classname>Gtk::Window</classname>), where it will be checked for any keyboard shortcuts that may be set (accelerator keys and mnemonics, used for selecting menu items from the keyboard). After this (and assuming the event wasn't handled), it is sent to the widget which has focus, and the propagation begins from there.
zh_CN: 与其他事件相反，键盘事件首先被发送到顶级窗口（<classname>Gtk::Window</classname>），在此检查任何可能被设置的键盘快捷键（用于从键盘选择菜单项的快捷键、助记符）。然后（假设事件没有被处理）将其发送到焦点部件，然后从此部件开始传播。

en: The event will propagate until it reaches the top-level widget, or until you stop the propagation by returning <literal>true</literal> from an event handler.
zh_CN: 事件将一直传播直到顶级窗口为止或直到你通过事件处理程序返回<literal>true</literal>为止。

en: Notice, that after canceling an event, no other function will be called (even if it is from the same widget).
zh_CN: 请注意，取消事件之后，不再会调用其他函数（哪怕它来自同一个部件）。

en: In this example there are three event handlers that are called after <classname>Gtk::Window</classname>'s default event handler, one in the <classname>Gtk::Entry</classname>, one in the <classname>Gtk::Grid</classname> and one in the <classname>Gtk::Window</classname>.
zh_CN: 在此示例中，<classname>Gtk::Window</classname>在默认事件处理程序之后调用了三个事件处理程序，一个在<classname>Gtk::Entry</classname>中、一个在<classname>Gtk::Grid</classname>中、一个在<classname>Gtk::Window</classname>中。

en: In the <classname>Gtk::Window</classname>, we have also the default handler overridden (<methodname>on_key_release_event()</methodname>), and another handler being called before the default handler (<methodname>windowKeyReleaseBefore()</methodname>).
zh_CN: 在<classname>Gtk::Window</classname>中我们还覆盖了默认处理程序（<methodname>on_key_release_event()</methodname>），并在调用默认处理程序之前调用了另一个处理程序（<methodname>windowKeyReleaseBefore()</methodname>）。

en: The purpose of this example is to show the steps the event takes when it is emitted.
zh_CN: 本示例的目的是显示事件发出时进行的步骤。

en: When you write in the entry, a key release event will be emitted, which will go first to the toplevel window (<classname>Gtk::Window</classname>), since we have one event handler set to be called before, that's what is called first (<methodname>windowKeyReleaseBefore()</methodname>). Then the default handler is called (which we have overridden), and after that the event is sent to the widget that has focus, the <classname>Entry</classname> in our example and, depending on whether we let it propagate, it can reach the <classname>Grid</classname>'s and the <classname>Window</classname>'s event handlers. If it propagates, the text you're writing will appear in the <classname>Label</classname> above the <classname>Entry</classname>.
zh_CN: 当你在条目中写入的时候，将发出一个按键放开事件，该事件将先进入顶层窗口（<classname>Gtk::Window</classname>），因为我们之前设置了一个事件处理程序，所以<methodname>windowKeyReleaseBefore()</methodname>将先被调用。然后调用已被覆盖的默认信号处理程序，然后将事件传播到具有焦点的部件，也就是示例中的<classname>Entry</classname>，根据事件处理程序的返回值，该事件可以被传播到<classname>Grid</classname>和<classname>Window</classname>。如果该事件被传播，你写入的文本将出现在<classname>Entry</classname>上方的<classname>Label</classname>中。

en: Keyboard Events - Event Propagation
zh_CN: 键盘事件 - 事件传播

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/keyboard_events/propagation/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/keyboard_events/propagation/">源代码</ulink>

en: Timeouts, I/O and Idle Functions
zh_CN: 超时，I/O和空闲函数

en: Timeouts
zh_CN: 超时

en: You may be wondering how to make <application>gtkmm</application> do useful work while it's idling along. Happily, you have several options. Using the following methods you can create a timeout method that will be called every few milliseconds.
zh_CN: 你可能想知道如何使<application>gtkmm</application>在空闲的时候做一些有用的工作。幸运的是你有几种选择。你可以创建一个每几毫秒就调用的超时方法。

en: The first argument is a <classname>slot</classname> you wish to have called when the timeout occurs. The second argument is the number of milliseconds between calls to that method. You receive a <classname>sigc::connection</classname> object that can be used to deactivate the connection using its <methodname>disconnect()</methodname> method:
zh_CN: 第一个参数是超时时你希望被调用的<classname>slot</classname>。第二个参数是调用该方法的时间间隔（多少毫秒）。你将收到一个<classname>sigc::connection</classname>对象，可以在该对象上调用<methodname>disconnect()</methodname>方法断开连接。

en: Another way of destroying the connection is your signal handler. It has to be of the type <classname>sigc::slot&lt;bool()&gt;</classname>. As you see from the definition your signal handler has to return a value of the type <literal>bool</literal>. A definition of a sample method might look like this:
zh_CN: 破坏连接的另一种方法是通过你的信号处理函数的返回值。其类型必须是<classname>sigc::slot&lt;bool()&gt;</classname>。从定义可以看出信号处理函数必须返回一个<literal>bool</literal>类型的值。示例方法的定义可能如下所示：

en: You can stop the timeout method by returning <literal>false</literal> from your signal handler. Therefore, if you want your method to be called repeatedly, it should return <literal>true</literal>.
zh_CN: 你可以通过让你的信号处理函数返回<literal>false</literal>以停止此超时方法。因此，如果你还想重复调用此方法，则你需要让信号处理函数返回<literal>true</literal>。

en: Here's an example of this technique:
zh_CN: 这是此技术的示例：

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/timeout/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/timeout/">源代码</ulink>

en: Monitoring I/O
zh_CN: 监视I/O

en: A nifty feature of Glib (one of the libraries underlying <application>gtkmm</application>) is the ability to have it check for data on a file descriptor for you. This is especially useful for networking applications. The following method is used to do this:
zh_CN: Glib（<application>gtkmm</application>的底层库之一）有一个很好的特性是它具有帮你检查文件描述符中的数据的能力。这对于需要联网的应用程序十分的有用。使用以下方法来执行此操作：

en: The first argument is a slot you wish to have called when the specified event (see argument 3) occurs on the file descriptor you specify using argument two. Argument three may be one or more (using <literal>|</literal>) of:
zh_CN: 第一个参数是你希望在第二个参数指定的文件描述符上发生指定事件（见第三个参数的描述）时被调用的槽。第三个参数可能是一下的一项或多项（若想是多项则对以下多个使用<literal>|</literal>，例如：<literal>Glib::IO_IN | Glib::IO_OUT | Glib::IO_PRI</literal>）：

en: Glib::IO_IN - Call your method when there is data ready for reading on your file descriptor.
zh_CN: Glib::IO_IN - 当你提供的文件描述符有数据准备好被读取时调用你的方法。

en: Glib::IO_OUT - Call your method when the file descriptor is ready for writing.
zh_CN: Glib::IO_OUT - 当提供的文件描述符准备好被写入时调用你的方法。

en: Glib::IO_PRI - Call your method when the file descriptor has urgent data to be read.
zh_CN: Glib::IO_PRI - 当提供的文件描述符有紧急数据要读取时调用你的方法。

en: Glib::IO_ERR - Call your method when an error has occurred on the file descriptor.
zh_CN: Glib::IO_ERR - 当提供的文件描述符上发生错误的时候调用你的方法。

en: Glib::IO_HUP - Call your method when hung up (the connection has been broken usually for pipes and sockets).
zh_CN: Glib::IO_HUP - 挂起时（常见于管道和套接字的连接被断开）调用你的方法。

en: The return value is a <classname>sigc::connection</classname> that may be used to stop monitoring this file descriptor using its <methodname>disconnect()</methodname> method. The <parameter>slot</parameter> signal handler should be declared as follows:
zh_CN: 返回值是一个<classname>sigc::connection</classname>对象，你可以在其上调用<methodname>disconnect()</methodname>方法以停止对该文件描述符的监视。信号处理函数<parameter>slot</parameter>应声明如下：

en: where <parameter>condition</parameter> is as specified above. As usual the slot is created with <function>sigc::mem_fun()</function> (for a member method of an object), or <function>sigc::ptr_fun()</function> (for a function).
zh_CN: 参数<parameter>condition</parameter>如上所述。通常使用<function>sigc::mem_fun()</function>（通过一个对象的成员函数创建）或<function>sigc::ptr_fun()</function>（通过一个普通函数创建）函数创建槽。

en: A little example follows. To use the example just execute it from a terminal; it doesn't create a window. It will create a pipe named <literal>testfifo</literal> in the current directory. Then start another shell and execute <literal>echo "Hello" &gt; testfifo</literal>. The example will print each line you enter until you execute <literal>echo "Q" &gt; testfifo</literal>.
zh_CN: 下面是个示例。要使用该示例，只需要在终端上执行它即可；它不会创建一个窗口。它将在当前目录创建一个名为<literal>testfifo</literal>的具名管道。然后启动另一个shell并执行<literal>echo "Hello" &gt; testfifo</literal>。该示例将打印你输入的每一行直到你执行<literal>echo "Q" &gt; testfifo</literal>

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/input/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/input/">源代码</ulink>

en: Idle Functions
zh_CN: 空闲函数

en: If you want to specify a method that gets called when nothing else is happening, use the following:
zh_CN: 如果你想要指定一个在无事发生时调用的方法，请使用以下函数：

en: This causes <application>gtkmm</application> to call the specified method whenever nothing else is happening. You can add a priority (lower numbers are higher priorities). There are two ways to remove the signal handler: calling <methodname>disconnect()</methodname> on the <classname>sigc::connection</classname> object, or returning <literal>false</literal> in the signal handler, which should be declared as follows:
zh_CN: 这会导致<application>gtkmm</application>在无事发生时调用指定的方法。你可以为其添加优先级（数字越小优先级越高）。删除该信号处理程序的方法有两个：在<classname>sigc::connection</classname>对象上调用<methodname>disconnect()</methodname>、在信号处理程序中返回<literal>false</literal>，信号处理程序的声明应如下所示：

en: Since this is very similar to the methods above this explanation should be sufficient to understand what's going on. However, here's a little example:
zh_CN: 这与前一小节的方法极其类似，所以在此不再进行过多的解释。以下是个小例子：

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/idle/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/idle/">源代码</ulink>

en: This example points out the difference of idle and timeout methods a little. If you need methods that are called periodically, and speed is not very important, then you want timeout methods. If you want methods that are called as often as possible (like calculating a fractal in background), then use idle methods.
zh_CN: 这个例子指出了空闲与超时方法的微小区别。如果你需要定期调用，并且速度并不重要则你应该使用超时方法。如果你需要尽可能多的调用方法（例如在后台计算分形）那你应该使用空闲方法。

en: Try executing the example and increasing the system load. The upper progress bar will increase steadily; the lower one will slow down.
zh_CN: 尝试执行此示例并逐渐增加系统的负载。上方的进度条将稳定的逐渐增加；下方的则会增加的越来越慢。

en: Memory management
zh_CN: 内存管理

en: Normal C++ memory management
zh_CN: 标准C++内存管理

en: <application>gtkmm</application> allows the programmer to control the lifetime (that is, the construction and destruction) of any widget in the same manner as any other C++ object. This flexibility allows you to use <literal>new</literal> and <literal>delete</literal> to create and destroy objects dynamically or to use regular class members (that are destroyed automatically when the class is destroyed) or to use local instances (that are destroyed when the instance goes out of scope). This flexibility is not present in some C++ GUI toolkits, which restrict the programmer to only a subset of C++'s memory management features.
zh_CN: <application>gtkmm</application>允许程序员像管理任意其他C++对象一样对任意部件的生命周期（即构造和析构）进行控制。这种灵活性使你可以用<literal>new</literal>和<literal>delete</literal>动态创建和销毁对象，或使用常规的类成员（销毁类时部件将被自动销毁），或使用局部实例（当实例超出其作用域时被销毁）。这种灵活性在某些C++ GUI工具包中不存在，这些工具包限制程序员只能使用C++内存管理特性中的一部分。

en: Here are some examples of normal C++ memory management:
zh_CN: 以下是一些使用标准C++进行内存管理的示例：

en: Class Scope widgets
zh_CN: 类作用域部件

en: If a programmer does not need dynamic memory allocation, automatic widgets in class scope may be used. One advantage of automatic widgets in class scope is that memory management is grouped in one place. The programmer does not risk memory leaks from failing to <literal>delete</literal> a widget.
zh_CN: 如果程序员不需要动态分配内存，则可以在类作用域中使用具有自动储存期的部件。在类作用域中使用自动储存期的部件的优点之一是内存管理被集中在一个地方。程序员不需要承担因<literal>delete</literal>部件出现差错而导致内存泄漏的风险。

en: The primary disadvantage of using class scope widgets is revealing the class implementation rather than the class interface in the class header.
zh_CN: 使用类作用域部件的主要缺点是在包含类声明的头文件中展示了类的实现而不只是类的接口。

en: Function scope widgets
zh_CN: 函数作用域部件

en: If a programmer does not need a class scope widget, a function scope widget may also be used. The advantages to function scope over class scope are the increased data hiding and reduced dependencies.
zh_CN: 如果程序员不需要类作用域部件，那么也可以使用函数作用域部件。函数作用域相比于类作用域的优点是增加了数据的隐蔽性和隐藏了依赖。

en: Dynamic allocation with new and delete
zh_CN: 使用new和delete进行动态分配

en: Usually, the programmer will prefer to allow containers to automatically destroy their children by creating them using <function>Gtk::make_managed()</function> (see below). This is not strictly required, as the <literal>new</literal> and <literal>delete</literal> operators may also be used, but modern C++ style discourages those in favour of safer models of memory management, so it is better to create widgets using <function>Gtk::make_managed()</function> and let their parent destroy them, than to manually perform dynamic allocation. <_:programlisting-1/> Here, the programmer deletes <varname>pButton</varname> to prevent a memory leak.
zh_CN: 通常，程序员更喜欢使用<function>Gtk::make_managed()</function>（参见下文）创建允许容器自动销毁的子部件。这并非强制性的要求，你也可以使用<literal>new</literal>和<literal>delete</literal>操作符，但是现代C++风格鼓励使用更安全的内存管理模型，因此最好使用<function>Gtk::make_managed()</function>创建部件，并让他们的父部件销毁它们，而不是手动执行动态内存分配。<_:programlisting-1/> 在这，程序员删除<varname>pButton</varname>以防止内存泄漏。

en: Managed Widgets
zh_CN: 托管部件

en: Alternatively, you can let a widget's container control when the widget is destroyed. In most cases, you want a widget to last only as long as the container it is in. To delegate the management of a widget's lifetime to its container, create it with <function>Gtk::make_managed()</function> and then pack it into its container with <methodname>Gtk::Box::append()</methodname> or a similar method. Now the widget will be destroyed whenever its container is destroyed.
zh_CN: 另外，你可以让部件的容器控制部件被销毁的时机。多数情况下你会希望部件的生存周期与包含它的容器的生命周期一样长。要将部件的生命周期管理委托给其容器，请使用<function>Gtk::make_managed()</function>创建部件，然后使用诸如<methodname>Gtk::Box::append()</methodname>这类的方法将其装入容器中。这样部件就会随着容器一并销毁。

en: Dynamic allocation with make_managed() and append()
zh_CN: 使用make_managed()和append()进行动态分配

en: <application>gtkmm</application> provides ways including the <function>make_managed()</function> function and <methodname>Gtk::Box::append()</methodname> method to simplify creation and destruction of widgets whose lifetime can be managed by a parent.
zh_CN: <application>gtkmm</application>提供了包括<function>make_managed()</function>函数和<methodname>Gtk::Box::append()</methodname>方法在内的用于简化创建和销毁部件的很多方法。这些部件的生命周期可以由其父部件进行管理。

en: Every widget except a top-level window must be added to a parent container in order to be displayed. The <function>manage()</function> function marks a widget so that when that widget is added to a parent container, said container becomes responsible for deleting the widget, meaning the user no longer needs to do so. The original way to create widgets whose lifetime is managed by their parent in this way was to call <function>manage()</function>, passing in the result of a <literal>new</literal> expression that created a dynamically allocated widget.
zh_CN: 除了顶级窗口以外的任何部件都需要添加到一个父容器中才能够被显示。<function>manage()</function>函数对部件进行标记，以便将该部件添加到父容器时，由其父容器负责删除该部件，这意味着用户不需要如此做。创建生命周期由其父部件进行管理的部件的原始方法是调用<function>manage()</function>，并将向其传入使用<literal>new</literal>表达式创建的动态分配的部件。

en: However, usually, when you create such a widget, you will already know that its parent container should be responsible for destroying it, In addition, modern C++ style discourages use of the <literal>new</literal> operator, which was required when passing a newly created widget to <function>manage()</function>. Therefore, <application>gtkmm</application> has added <function>make_managed()</function>, which combines creation and marking with <function>manage()</function> into a single step. This avoids you having to write <literal>new</literal>, which is discouraged in modern C++ style, and more clearly expresses intent to create a managed widget.
zh_CN: 但是通常当你创建这样的部件时，你已经知道其父部件应该负责销毁它。此外现代C++风格不推荐使用<literal>new</literal>操作符，而将新创建的部件传递给<function>manage()</function>时需要使用<literal>new</literal>。因此，<application>gtkmm</application>添加了<function>make_managed()</function>函数，这个函数将两个步骤合并到了一起。这避免了让你编写现代C++风格不建议的带有<literal>new</literal>的代码，并更清楚的表达了创建托管部件的意图。

en: Now, when objects of type <classname>MyContainer</classname> are destroyed, the button will also be deleted. It is no longer necessary to delete <varname>pButton</varname> to free the button's memory; its deletion has been delegated to the <classname>MyContainer</classname> object.
zh_CN: 现在，当你销毁<classname>MyContainer</classname>类型对象时，该按钮也被销毁。不再需要主动<literal>delete</literal><varname>pButton</varname>以释放其内存；对其的删除操作委托给了<classname>MyContainer</classname>对象。

en: Note that if you never added the widget to any parent container, or you did but later <methodname>Gtk::Container::remove()</methodname>d it from said parent, <application>gtkmm</application> restores the widget’s lifetime management to whatever state it had before <function>manage()</function> was called, which typically means that the responsibility for <literal>delete</literal>ing the widget returns to the user.
zh_CN: 请注意，如果你从未将该部件添加到任何父容器中，或者你添加后在其父容器调用了<methodname>Gtk::Container::remove()</methodname>将其从父容器中删除了，<application>gtkmm</application>将会使部件的生命周期管理恢复到调用<function>manage()</function>之前的状态，这通常意味着删除部件的责任被归还给了用户。

en: Of course, a top-level container will not be added to another container. The programmer is responsible for destroying the top-level container using one of the traditional C++ techniques. For instance, your top-level Window might just be an instance in your <function>main()</function> function.
zh_CN: 当然，顶级容器不会被添加到另一个容器中。程序员负责使用一种传统的C++技术销毁顶级容器。例如，你的顶级窗口可能只是<function>main()</function>函数中的一个实例。

en: Shared resources
zh_CN: 共享资源

en: Some objects, such as <classname>Gdk::Pixbuf</classname>s and <classname>Pango::Font</classname>s, are obtained from a shared store. Therefore you cannot instantiate your own instances. These classes typically inherit from <classname>Glib::Object</classname>. Rather than requiring you to reference and unreference these objects, <application>gtkmm</application> uses the <classname>Glib::RefPtr&lt;&gt;</classname> smartpointer. Cairomm has its own smartpointer, <classname>Cairo::RefPtr&lt;&gt;</classname>.
zh_CN: 一些对象是从共享储存中获取的，例如<classname>Gdk::Pixbuf</classname>和<classname>Pango::Font</classname>。因此你无法实例化自己的实例。这些类通常继承自<classname>Glib::Object</classname>。<application>gtkmm</application>使用智能指针<classname>Glib::RefPtr&lt;&gt;</classname>而不是要求你引用和解引用这些对象。开罗有自己的智能指针：<classname>Cairo::RefPtr&lt;&gt;</classname>。

en: Objects such as <classname>Gdk::Pixbuf</classname> can only be instantiated with a <methodname>create()</methodname> function. For instance,
zh_CN: 诸如<classname>Gdk::Pixbuf</classname>之类的对象只能通过<methodname>create()</methodname>函数进行实例化。例如：

en: You have no way of getting a bare <classname>Gdk::Pixbuf</classname>. In the example, <varname>pixbuf</varname> is a smart pointer, so you can do this, much like a normal pointer:
zh_CN: 你无法暴露<classname>Gdk::Pixbuf</classname>对象。在示例中，<varname>pixbuf</varname>是一个智能指针，因此可以像正常指针一样执行此操作：

en: When <varname>pixbuf</varname> goes out of scope an <methodname>unref()</methodname> will happen in the background and you don't need to worry about it anymore. There's no <literal>new</literal> so there's no <literal>delete</literal>.
zh_CN: 当<varname>pixbuf</varname>超出作用域时，将在后台调用<methodname>unref()</methodname>，你无需为它担心。没有进行<literal>new</literal>因此也不需要进行<literal>delete</literal>。

en: If you copy a <classname>RefPtr</classname>, for instance <_:programlisting-1/> , or if you pass it as a method argument or a return type, then <classname>RefPtr</classname> will do any necessary referencing to ensure that the instance will not be destroyed until the last <classname>RefPtr</classname> has gone out of scope.
zh_CN: 如果你复制一个<classname>RefPtr</classname>，例如：<_:programlisting-1/>，或者你将其作为一个方法的参数或返回类型进行传递，<classname>RefPtr</classname>将做必要的引用以确保在最后一个<classname>RefPtr</classname>超出作用域之前该实例不会被销毁。

en: See the <link linkend="chapter-refptr">appendix</link> for detailed information about RefPtr.
zh_CN: 更多与RefPtr有关的信息，请参见<link linkend="chapter-refptr">附录</link>。

en: Bjarne Stroustrup, "The C++ Programming Language" Forth Edition - section 34.3
zh_CN: Bjarne Stroustrup,《C++编程语言》第四版 第34章第3小节

en: Nicolai M. Josuttis, "The C++ Standard Library" - section 4.2
zh_CN: Nicolai M. Josuttis,《C++标准库》第4章第2节

en: If you wish to learn more about smartpointers, you might look in these books: <_:itemizedlist-1/>
zh_CN: 如果你想了解与智能指针更多的有关信息，请阅读以下书籍：<_:itemizedlist-1/>

en: Glade and Gtk::Builder
zh_CN: Glade和Gtk::Builder

en: Although you can use C++ code to instantiate and arrange widgets, this can soon become tedious and repetitive. And it requires a recompilation to show changes. The <application>Glade</application> application allows you to layout widgets on screen and then save an XML description of the arrangement. Your application can then use the <application>Gtk::Builder</application> API to load that XML file at runtime and obtain a pointer to specifically named widget instances.
zh_CN: 尽管你可以使用C++代码对部件进行实例化和排列，但是这很快就会变得枯燥且重复。并且需要重新编译才能显示更改。<application>Glade</application>应用程序允许你在屏幕上布局部件并然后将布局保存为XML描述。你的应用程序可以在之后使用<application>Gtk::Builder</application>API在运行时加载该XML文件，并获取特定名称部件实例的指针。

en: Less C++ code is required.
zh_CN: 需要的C++代码更少。

en: UI changes can be seen more quickly, so UIs are able to improve.
zh_CN: 可以更快的看到UI的更改，更便于改进UI。

en: Designers without programming skills can create and edit UIs.
zh_CN: 没有编程技能的设计人员可以创建和编辑UI。

en: This has the following advantages: <_:orderedlist-1/>
zh_CN: 这具有以下优点：<_:orderedlist-1/>

en: You still need C++ code to deal with User Interface changes triggered by user actions, but using <application>Gtk::Builder</application> for the widget layout allows you to focus on implementing that functionality.
zh_CN: 你仍然需要编写C++代码以处理由用户操作触发的UI更改，但是将<application>Gtk::Builder</application>用于部件布局允许你更专注的实现该功能。

en: Loading the .glade file
zh_CN: 加载.glade文件

en: <classname>Gtk::Builder</classname> must be used via a <classname>Glib::RefPtr</classname>. Like all such classes, you need to use a <methodname>create()</methodname> method to instantiate it. For instance, <_:programlisting-1/> This will instantiate the windows defined in the <filename>.glade</filename> file.
zh_CN: <classname>Gtk::Builder</classname>必须通过<classname>Glib::RefPtr</classname>来使用。与所有此类类一样，你需要通过使用<methodname>create()</methodname>方法实例化它。例如：<_:programlisting-1/>这将实例化<filename>.glade</filename>文件中定义的窗口。

en: To instantiate just one window, or just one of the child widgets, you can specify the name of a widget as the second parameter. For instance,
zh_CN: 如果只想实例化一个窗口或实例化一个子部件，你可以将部件的名称指定为第二个参数。例如：

en: Accessing widgets
zh_CN: 访问部件

en: To access a widget, for instance to <methodname>show()</methodname> a dialog, use the <methodname>get_widget()</methodname> method, providing the widget's name. This name should be specified in the <application>Glade</application> Properties window. If the widget could not be found, or is of the wrong type, then the pointer will be set to nullptr.
zh_CN: 要访问部件，例如<methodname>show()</methodname>一个对话框，请使用<methodname>get_widget()</methodname>方法，并向其提供一个部件名。这个名称应该在<application>Glade</application>的窗口属性中指定。如果找不到该部件或是部件的类型不对，则指针将被设为<literal>nullptr</literal>。

en: <application>Gtk::Builder</application> checks for a null pointer, and checks that the widget is of the expected type, and will show warnings on the command line about these.
zh_CN: <application>Gtk::Builder</application>会进行空指针和部件类型检查，并在命令行上显示相关的警告。

en: Remember that you are not instantiating a widget with <methodname>get_widget()</methodname>, you are just obtaining a pointer to one that already exists. You will always receive a pointer to the same instance when you call <methodname>get_widget()</methodname> on the same <classname>Gtk::Builder</classname>, with the same widget name. The widgets are instantiated during <methodname>Gtk::Builder::create_from_file()</methodname>.
zh_CN: 请注意，你并没有使用<methodname>get_widget()</methodname>实例化部件，你只是获得了指向已经存在的部件的指针。当你在同一个<classname>Gtk::Builder</classname>上用同一个名称调用<methodname>get_widget()</methodname>你总是会得到指向同一实例的指针。部件在函数<methodname>Gtk::Builder::create_from_file()</methodname>执行期间被实例化。

en: <methodname>get_widget()</methodname> returns child widgets that are <function>manage()</function>ed (see the <link linkend="chapter-memory">Memory Management</link> chapter), so they will be deleted when their parent container is deleted. <classname>Windows</classname> (such as <classname>Dialogs</classname>) cannot be managed because they have no parent container, so you must delete them at some point. The documentation of <classname>Gtk::Builder</classname> has more to say about the memory management of different kinds of objects.
zh_CN: <methodname>get_widget()</methodname>返回一个经<function>manage()</function>处理的子部件（参阅<link linkend="chapter-memory">内存管理</link>章节），因此在删除其父部件时它们将被一并删除。无法管理<classname>Windows</classname>（例如<classname>Dialogs</classname>）因为它们没有父容器，所以你必须在某个时候删除它们。<classname>Gtk::Builder</classname>的文档中有更多关于对不同类型的对象如何进行内存管理的介绍。

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Builder.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Builder.html">参考</ulink>

en: This simple example shows how to load a <application>Glade</application> file at runtime and access the widgets with <application>Gtk::Builder</application>.
zh_CN: 这个简单示例展示了如何在运行时加载<application>Glade</application>文件并使用<application>Gtk::Builder</application>访问部件。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/builder/basic">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/builder/basic">源代码</ulink>

en: Using derived widgets
zh_CN: 使用派生部件

en: You can use <classname>Gtk::Builder</classname> and <application>Glade</application> to layout your own custom widgets derived from <application>gtkmm</application> widget classes. This keeps your code organized and encapsulated, separating declarative presentation from business logic, avoiding having most of your source just be setting properties and packing in containers.
zh_CN: 你可以使用<classname>Gtk::Builder</classname>和<application>Glade</application>布局你从<application>gtkmm</application>部件类派生的自定义部件。这使得你的代码保持有序和封装性，将声明式表述与业务逻辑分离开来，避免你的大多数源代码都是在设置属性和装填容器。

en: Use <methodname>Gtk::Builder::get_widget_derived()</methodname> like so:
zh_CN: 像这样用<methodname>Gtk::Builder::get_widget_derived()</methodname>：

en: Your derived class must have a constructor that takes a pointer to the underlying C type, and the <classname>Gtk::Builder</classname> instance. All relevant classes of <application>gtkmm</application> typedef their underlying C type as <classname>BaseObjectType</classname> (<classname>Gtk::Dialog</classname> typedefs <classname>BaseObjectType</classname> as <type>GtkDialog</type>, for instance).
zh_CN: 你的派生类必须有一个将指向底层C类型的指针和<classname>Gtk::Builder</classname>实例作为参数的构造函数。所有与<application>gtkmm</application>相关的类的都将其的底层C类型别名(typedef)为<classname>BaseObjectType</classname>（例如：<classname>Gtk::Dialog</classname>将<type>GtkDialog</type>别名为<classname>BaseObjectType</classname>）。

en: You must call the base class's constructor in the initialization list, providing the C pointer. For instance,
zh_CN: 你必须在初始化列表中调用基类的构造函数，并提供C指针。例如：

en: You could then encapsulate the manipulation of the child widgets in the constructor of the derived class, maybe using <methodname>get_widget()</methodname> or <methodname>get_widget_derived()</methodname> again. For instance,
zh_CN: 然后你可以将对子部件的操作封装于派生类的构造函数中，可以在构造函数中再次使用<methodname>get_widget()</methodname>或<methodname>get_widget_derived()</methodname>。例如：

en: It's possible to pass additional arguments from <methodname>get_widget_derived()</methodname> to the constructor of the derived widget. For instance, this call to <methodname>get_widget_derived()</methodname> <_:programlisting-1/> can invoke this constructor <_:programlisting-2/>
zh_CN: 可以传递额外的参数给<methodname>get_widget_derived()</methodname>，他们将被转发给派生部件的构造函数。例如这样调用<methodname>get_widget_derived()</methodname>：<_:programlisting-1/>可以调用此构造函数：<_:programlisting-2/>

en: Gtk::Builder and Glib::Property
zh_CN: Gtk::Builder和Glib::Property

en: If your derived widget uses <classname>Glib::Property</classname>, it becomes slightly more complicated. A derived widget that contains <classname>Glib::Property</classname> members must be registered with its own name in the <type>GType</type> system. It must be registered before any of the <methodname>create_from_*()</methodname> or <methodname>add_from_*()</methodname> methods are called, meaning that you may have to create an instance of your derived widget just to have its class registered. Your derived widget must have a constructor that has the parameters required by <methodname>get_widget_derived()</methodname> and calls the <classname>Glib::ObjectBase</classname> constructor to register the <type>GType</type>.
zh_CN: 如果你派生的部件使用了<classname>Glib::Property</classname>，它将变得更复杂了一些。包涵<classname>Glib::Property</classname>成员的派生部件必须在<type>GType</type>系统中用自己的名称进行注册。必须在调用任何<methodname>create_from_*()</methodname>或<methodname>add_from_*()</methodname>方法之前进行注册，这意味着你可能需要完成对该类的注册才能创建派生部件的实例。你派生的部件必须有一个具有<methodname>get_widget_derived()</methodname>所需的所有参数以及调用<classname>Glib::ObjectBase</classname>构造函数以注册<type>GType</type>的构造函数。

en: When using <application>gtkmm</application> with a version of <application>glibmm</application> from 2.62 onwards, it is possible also to specify properties of derived widgets, declared in C++ using <application>gtkmm</application>, within <filename>.glade</filename> files and load/set these using <classname>Gtk::Builder</classname>. See the documentation of <classname>Gtk::Builder</classname> for more details on how to achieve this. Glade won’t recognise such properties as-is, but it should be able to through use of <ulink url="https://developer.gnome.org/gladeui/stable/properties.html"> property class definitions</ulink> and a catalog declaring those new properties.
zh_CN: 如果将<application>gtkmm</application>与<application>glibmm</application>2.62以上的版本一起使用，则还可以在<filename>.glade</filename>文件中指定使用<application>gtkmm</application>在C++代码中声明的派生部件的属性，并使用<classname>Gtk::Builder</classname>加载/设置这些属性。更多实现此功能的详细信息请参阅<classname>Gtk::Builder</classname>的文档。Glade不会按原样识别这些属性，但这应该能通过使用<ulink url="https://developer.gnome.org/gladeui/stable/properties.html">属性类定义</ulink>和声明一个新属性目录来实现。

en: This example shows how to load a <application>Glade</application> file at runtime and access the widgets via derived classes.
zh_CN: 本示例展示了如何在运行时加载<application>Glade</application>文件以及如何通过派生类访问部件。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/builder/derived">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/builder/derived">源代码</ulink>

en: Internationalization and Localization
zh_CN: 国际化和本地化

en: <application>gtkmm</application> applications can easily support multiple languages, including non-European languages such as Chinese and right-to-left languages such as Arabic. An appropriately-written and translated <application>gtkmm</application> application will use the appropriate language at runtime based on the user's environment.
zh_CN: <application>gtkmm</application>应用程序可以很轻松的支持包括非欧洲语言（如中文）和从右向左语言（如阿拉伯语）在内的多种语言。正确编写且进行翻译的<application>gtkmm</application>应用程序可以在运行时根据用户环境使用合适的语言。

en: You might not anticipate the need to support additional languages, but you can never rule it out. And it's easier to develop the application properly in the first place rather than retrofitting later.
zh_CN: 你可能没有预料到需要支持其他语言，但你永远不能排除这种可能性。而且事先准备好支持多语言比后来改进要容易的多。

en: The process of writing source code that allows for translation is called <literal>internationalization</literal>, often abbreviated to <literal>i18n</literal>. The <literal>Localization</literal> process, sometimes abbreviated as <literal>l10n</literal>, provides translated text for other languages, based on that source code.
zh_CN: 编写允许进行翻译的源代码的过程被称为<literal>internationalization</literal>，通常被缩写为<literal>i18n</literal>。而根据该源代码提供其他语言的翻译文本的过程<literal>Localization</literal>通常被简写为<literal>l10n</literal>。

en: The main activity in the internationalization process is finding strings seen by users and marking them for translation. You do not need to do it all at once - if you set up the necessary project infrastructure correctly then your application will work normally regardless of how many strings you've covered.
zh_CN: 国际化过程中的主要活动是查找用户能看到的字符串并将其标记为需要可翻译。你不需要一次性完成所有的操作 - 只要你的项目准备好了进行国际化无论你有多少个字符串被标记为可翻译都不会影响程序的正常运行。

en: String literals should be typed in the source code in English, but surrounded by a macro. The <application>gettext</application> (or intltool) utility can then extract the marked strings for translation, and substitute the translated text at runtime.
zh_CN: 源代码中的字符串字面量应该以英文键入，但要使用宏包围。<application>gettext</application>（或intltool）实用程序可以提取被标记的字符串进行翻译，并在运行时将其替换为翻译后的文本。

en: Preparing your project
zh_CN: 准备你的项目

en: In the instructions below we will assume that you will not be using <application>gettext</application> directly, but <application>intltool</application>, which was written specifically for <literal>GNOME</literal>. <application>intltool</application> uses <function>gettext()</function>, which extracts strings from source code, but <application>intltool</application> can also combine strings from other files, for example from desktop menu details, and GUI resource files such as <application>Glade</application> files, into standard <application>gettext</application> <filename>.pot/.po</filename> files.
zh_CN: 在下面的说明中我们假定你不直接使用<application>gettext</application>，而是使用专门为<literal>GNOME</literal>编写的<application>intltool</application>。<application>intltool</application>使用<function>gettext()</function>从源代码中提取字符串，但是<application>intltool</application>也从其他文件（例如桌面菜单详情、glade的GUI资源文件）中提取字符串写入到标准的<application>gettext</application><filename>.pot/.po</filename>文件中。

en: We also assume that you are using autotools (e.g. <application>automake</application> and <application>autoconf</application>) to build your project, and that you are using <ulink url="https://gitlab.gnome.org/GNOME/gnome-common/blob/master/autogen.sh"> <literal>./autogen.sh</literal> from <application>gnome-common</application></ulink> or a similar <literal>autogen.sh</literal> file, which, among other things, takes care of some <application>intltool</application> initialization.
zh_CN: 我们还假设你正在使用自动构建工具（例如：<application>automake</application>和<application>autoconf</application>）构建你的项目，并且你正在使用<ulink url="https://gitlab.gnome.org/GNOME/gnome-common/blob/master/autogen.sh">来自<application>gnome-common</application>的<literal>./autogen.sh</literal></ulink>或与之类似的<literal>autogen.sh</literal>文件，在这里它负责初始化<application>intltool</application>。

en: An alternative to <application>gnome-common</application>'s <literal>autogen.sh</literal> may look like this:
zh_CN: <application>gnome-common</application>的<literal>autogen.sh</literal>的替代方案可能如下所示：

en: Create a sub-directory named <literal>po</literal> in your project's root directory. This directory will eventually contain all of your translations. Within it, create a file named <literal>LINGUAS</literal> and a file named <literal>POTFILES.in</literal>. It is common practice to also create a <literal>ChangeLog</literal> file in the <literal>po</literal> directory so that translators can keep track of translation changes.
zh_CN: 在你项目的根目录下创建一个名称为<literal>po</literal>的子文件夹。该目录将包含你的所有翻译。在其中创建一个名为<literal>LINGUAS</literal>和一个名为<literal>POTFILES.in</literal>的文件。通常做法是在<literal>po</literal>文件夹再创建一个<literal>ChangeLog</literal>文件以便翻译人员跟踪翻译更改。

en: <literal>LINGUAS</literal> contains an alphabetically sorted list of codes identifying the languages for which your program is translated (comment lines starting with a <literal>#</literal> are ignored). Each language code listed in the <literal>LINGUAS</literal> file must have a corresponding <literal>.po</literal> file. So, if your program has German and Japanese translations, your <literal>LINGUAS</literal> file would look like this:
zh_CN: <literal>LINGUAS</literal>包含按字母顺序排列的代码列表，这些代码标识程序已翻译的语言（以<literal>#</literal>开头的行是注释将被忽略）。<literal>LINGUAS</literal>文件中每个位于代码列表中语言都需要有与之对应的<literal>.po</literal>文件。因此如果你的程序有德语和日语翻译，你的<literal>LINGUAS</literal>应如下所示：

en: (In addition, you'd have the files <literal>ja.po</literal> and <literal>de.po</literal> in your <literal>po</literal> directory which contain the German and Japanese translations, respectively.)
zh_CN: （此外，你的<literal>po</literal>文件夹必须有包含德语和日语翻译的<literal>ja.po</literal>和<literal>de.po</literal>文件）

en: <literal>POTFILES.in</literal> is a list of paths to all files which contain strings marked up for translation, starting from the project root directory. So for example, if your project sources were located in a subdirectory named <literal>src</literal>, and you had two files that contained strings that should be translated, your <literal>POTFILES.in</literal> file might look like this:
zh_CN: <literal>POTFILES.in</literal>是一个开始于项目根目录，包含所有被标记为需要翻译字符串的文件路径列表。例如你的项目源代码位于<literal>src</literal>子目录中，其中有两个文件包含有需要被翻译的字符串，则你的<literal>POTFILES.in</literal>可能如下所示：

en: If you are using <application>gettext</application> directly, you can only mark strings for translation if they are in source code file. However, if you use <application>intltool</application>, you can mark strings for translation in a variety of other file formats, including <application>Glade</application> UI files, xml, <ulink url="http://standards.freedesktop.org/desktop-entry-spec/latest/">.desktop files</ulink> and several more. So, if you have designed some of the application UI in <application>Glade</application> then also add your <filename>.glade</filename> files to the list in <literal>POTFILES.in</literal>.
zh_CN: 如果你直接使用<application>gettext</application>，则你只能标记源代码文件中的字符串为需要被翻译。如果你使用<application>intltool</application>，则可以对多种格式的文件中的字符串进行标记，如<application>Glade</application>UI文件、XML、<ulink url="http://standards.freedesktop.org/desktop-entry-spec/latest/">.desktop文件</ulink>等。因此如果你使用<application>Glade</application>设计了应用程序UI，则你还需要将<filename>.glade</filename>添加到你的<literal>POTFILES.in</literal>列表中。

en: Now that there is a place to put your translations, you need to initialize <application>intltool</application> and <application>gettext</application>. Add the following code to your <literal>configure.ac</literal>, substituting 'programname' with the name of your program:
zh_CN: 现在已经有了放置翻译的地方，你需要初始化<application>intltool</application>和<application>gettext</application>。将一下代码添加到你的<literal>configure.ac</literal>，将"programname"替换为你的程序的名称：

en: This <varname>PROGRAMNAME_LOCALEDIR</varname> variable will be used later in the <literal>Makefile.am</literal> file, to define a macro that will be used when you initialize <application>gettext</application> in your source code.
zh_CN: <varname>PROGRAMNAME_LOCALEDIR</varname>将在稍后被<literal>Makefile.am</literal>文件使用。以定义在源代码中初始化<application>gettext</application>时将用到的宏。

en: <literal>AM_GLIB_GNU_GETTEXT</literal> has been an alternative to <literal>AM_GNU_GETTEXT</literal> and <literal>AM_GNU_GETTEXT_VERSION</literal>, but <literal>AM_GLIB_GNU_GETTEXT</literal> is now deprecated, and shall not be used in new code.
zh_CN: <literal>AM_GLIB_GNU_GETTEXT</literal>已由<literal>AM_GNU_GETTEXT</literal>和<literal>AM_GNU_GETTEXT_VERSION</literal>替代，且<literal>AM_GLIB_GNU_GETTEXT</literal>已被弃用，不应在任何新代码中使用。

en: Add <literal>po</literal> to the <literal>SUBDIRS</literal> variable. Without this, your translations won't get built and installed when you build the program
zh_CN: 将<literal>po</literal>添加到<literal>SUBDIRS</literal>变量中。如果没有这个，在构建程序时不会生成和安装翻译。

en: Define <literal>INTLTOOL_FILES</literal> as: <_:programlisting-1/>
zh_CN: 定义<literal>INTLTOOL_FILES</literal>为：<_:programlisting-1/>

en: Add <literal>INTLTOOL_FILES</literal> to the <literal>EXTRA_DIST</literal> list of files. This ensures that when you do a <command>make dist</command>, these files will be included in the source tarball.
zh_CN: 将<literal>INTLTOOL_FILES</literal>添加到<literal>EXTRA_DIST</literal>文件列表。这样可以确保执行<command>make dist</command>时这些文件包含在源压缩包中。

en: Update your <literal>DISTCLEANFILES</literal>: <_:programlisting-1/>
zh_CN: 更新你的<literal>DISTCLEANFILES</literal>：<_:programlisting-1/>

en: Depending on the types of files that contain translatable strings, add code such as <_:programlisting-1/>
zh_CN: 根据包含可翻译字符串的文件类型，添加以下代码：<_:programlisting-1/>

en: In the top-level Makefile.am: <_:itemizedlist-1/>
zh_CN: 在顶层<literal>Makefile.am</literal>中：<_:itemizedlist-1/>

en: In your <literal>src/Makefile.am</literal>, update your <literal>AM_CPPFLAGS</literal> to add the following preprocessor macro definition:
zh_CN: 在你的<literal>src/Makefile.am</literal>中，更新你的<literal>AM_CPPFLAGS</literal>以添加以下预处理宏定义：

en: This macro will be used when you initialize <literal>gettext</literal> in your source code.
zh_CN: 在你的源代码中初始化<literal>gettext</literal>时将使用这个宏。

en: Marking strings for translation
zh_CN: 标记要翻译的字符串

en: String literals should be typed in the source code in English, but they should be surrounded by a call to the <function>gettext()</function> function. These strings will be extracted for translation and the translations may be used at runtime instead of the original English strings.
zh_CN: 源代码中的字符串字面量应该以英文键入，但应将其包含在对<function>gettext()</function>函数的调用中。这些字符串将被提取以进行翻译，并且在运行时翻译可以替代原始的英文字符串。

en: The <application>GNU gettext</application> package allows you to mark strings in source code, extract those strings for translation, and use the translated strings in your application.
zh_CN: <application>GNU gettext</application>允许你标记源代码中的字符串，提取这些字符串进行翻译，并在你的应用程序中使用翻译好的字符串。

en: However, <application>Glib</application> defines <function>gettext()</function> support macros which are shorter wrappers in an easy-to-use form. To use these macros, include <literal>&lt;glibmm/i18n.h&gt;</literal>, and then, for example, substitute: <_:programlisting-1/> with: <_:programlisting-2/>
zh_CN: <application>Glib</application>定义了<function>gettext()</function>支持宏，这些宏更为简单易用，要使用这些宏请<literal>#include &lt;glibmm/i18n.h&gt;</literal>然后将：<_:programlisting-1/>替换为：<_:programlisting-2/>

en: For reference, it is possible to generate a file which contains all strings which appear in your code, even if they are not marked for translation, together with file name and line number references. To generate such a file named <literal>my-strings</literal>, execute the following command, within the source code directory:
zh_CN: 可以生成一个包含代码中出现的所有字符串（即使没有被标记为需要翻译）以及其文件名与行号引用的文件作为参考。要生成名为<literal>my-strings</literal>的文件，请在源代码目录执行以下命令：

en: Finally, to let your program use the translation for the current locale, add this code to the beginning of your <filename>main.cc</filename> file, to initialize gettext.
zh_CN: 最后，要让你的程序使用当前环境的翻译，请将以下代码添加到你的<filename>main.cc</filename>文件的开头，以初始化<function>gettext()</function>。

en: How gettext works
zh_CN: gettext如何工作

en: The <application>intltool-update</application> or <application>xgettext</application> script extracts the strings and puts them in a <filename>mypackage.pot</filename> file. The translators of your application create their translations by first copying this <filename>.pot</filename> file to a <filename>localename.po</filename> file. A locale identifies a language and an encoding for that language, including date and numerical formats. Later, when the text in your source code has changed, the <application>msgmerge</application> or <application>intltool-update</application> script is used to update the <filename>localename.po</filename> files from the regenerated <filename>.pot</filename> file.
zh_CN: <application>intltool-update</application>或<application>xgettext</application>脚本提取字符串并将其放入<filename>mypackage.pot</filename>文件中。应用程序的翻译人员首先将此<filename>.pot</filename>文件复制到<filename>localename.po</filename>中以创建翻译。语言环境标识一种语言和该语言使用的编码，包括日期和数字使用的格式。在之后，当源代码中的文本更改时，使用<application>msgmerge</application>或<application>intltool-update</application>脚本重新生成的<filename>.pot</filename>文件更新<filename>localename.po</filename>文件。

en: At install time, the <filename>.po</filename> files are converted to a binary format (with the extension <filename>.mo</filename>) and placed in a system-wide directory for locale files, for example <filename>/usr/share/locale/</filename>.
zh_CN: 在安装时，<filename>.po</filename>将被转换为二进制格式（扩展名为<filename>.mo</filename>），并将其放置于系统所有的区域设置文件夹中，例如<filename>/usr/share/locale/</filename>。

en: When the application runs, the <application>gettext</application> library checks the system-wide directory to see if there is a <filename>.mo</filename> file for the user's locale environment (you can set the locale with, for instance, "export LANG=de_DE.UTF-8" from a bash console). Later, when the program reaches a <literal>gettext</literal> call, it looks for a translation of a particular string. If none is found, the original string is used.
zh_CN: 当应用程序运行时，<application>gettext</application>将检查系统目录是否存在与用户语言环境对应的<filename>.mo</filename>文件（你可以使用以下命令指定语言环境，例如：在bash控制台上输入<command>export LANG=de_DE.UTF-8</command>）。稍后在程序到达<literal>gettext</literal>调用时，它将从中寻找特定字符串的翻译，如果未找到则使用原始字符串。

en: Testing and adding translations
zh_CN: 测试和添加翻译

en: To convince yourself that you've done well, you may wish to add a translation for a new locale. In order to do that, go to the <filename>po</filename> subdirectory of your project and execute the following command:
zh_CN: 为了说服自己做得很好，你可能希望为新的语言环境添加翻译。为此请转到项目的<filename>po</filename>子文件夹并执行以下命令：

en: That will create a file named <filename>programname.pot</filename>. Now copy that file to <filename>languagecode.po</filename>, such as <filename>de.po</filename> or <filename>hu.po</filename>. Also add that language code to <literal>LINGUAS</literal>. The <filename>.po</filename> file contains a header and a list of English strings, with space for the translated strings to be entered. Make sure you set the encoding of the <filename>.po</filename> file (specified in the header, but also as content) to <literal>UTF-8</literal>.
zh_CN: 这将创建一个名为<filename>programname.pot</filename>的文件。现在将该文件复制到<filename>languagecode.po</filename>，例如<filename>de.po</filename>或<filename>hu.po</filename>。接着将该语言代码添加到<literal>LINGUAS</literal>文件中。<filename>.po</filename>文件包含标头和英语字符串列表，并为翻译文本预留了空间。请确保将<filename>.po</filename>文件的编码设置（在标头中指定，但也指定其内容的编码）为了<literal>UTF-8</literal>。

en: It's possible that certain strings will be marked as <literal>fuzzy</literal> in the <filename>.po</filename> file. These translations will not substitute the original string. To make them appear, simply remove the <literal>fuzzy</literal> tag.
zh_CN: <filename>.po</filename>文件中有些字符串可能被标记为<literal>fuzzy</literal>。这些翻译将不会替代原始字符串。如果要使其显示，只需要将<literal>fuzzy</literal>标记删除即可（通常该标记意味着翻译需要更新，不检查翻译直接删除标记是不对的）。

en: Resources
zh_CN: 资源

en: <ulink url="https://wiki.gnome.org/TranslationProject/DevGuidelines"> L10N Guidelines for Developers</ulink>
zh_CN: <ulink url="https://wiki.gnome.org/TranslationProject/DevGuidelines">本地化开发人员指南</ulink>

en: <ulink url="http://bazaar.launchpad.net/~intltool/intltool/trunk/view/head:/README">Intltool README</ulink>
zh_CN: <ulink url="http://bazaar.launchpad.net/~intltool/intltool/trunk/view/head:/README">Intltool自述文件</ulink>

en: <ulink url="https://wiki.gnome.org/TranslationProject/GitHowTo">How to use Git for GNOME translators</ulink>
zh_CN: <ulink url="https://wiki.gnome.org/TranslationProject/GitHowTo">GNOME译者如何使用Git</ulink>

en: <ulink url="http://www.gnu.org/software/gettext/manual/gettext.html">gettext manual</ulink>
zh_CN: <ulink url="http://www.gnu.org/software/gettext/manual/gettext.html">gettext手册</ulink>

en: <ulink url="http://ftp.gnome.org/pub/GNOME/sources/gtkmm_hello/"><literal>gtkmm_hello</literal> example package</ulink>
zh_CN: <ulink url="http://ftp.gnome.org/pub/GNOME/sources/gtkmm_hello/"><literal>gtkmm_hello</literal>示例包</ulink>

en: <ulink url="http://ftp.gnome.org/pub/GNOME/sources/gnomemm_hello/"><literal>gnomemm_hello</literal> example package</ulink>
zh_CN: <ulink url="http://ftp.gnome.org/pub/GNOME/sources/gnomemm_hello/"><literal>gnomemm_hello</literal>示例包</ulink>

en: More information about what lies behind the internationalization and localization process is presented and demonstrated in: <_:itemizedlist-1/>
zh_CN: 更多与国际化与本地化有关的信息，请参阅以下内容：<_:itemizedlist-1/>

en: Expecting UTF8
zh_CN: 期望使用UTF8

en: A properly internationalized application will not make assumptions about the number of bytes in a character. That means that you shouldn't use pointer arithmetic to step through the characters in a string, and it means you shouldn't use <classname>std::string</classname> or standard C functions such as <function>strlen()</function> because they make the same assumption.
zh_CN: 好的国际化应用程序不会假设字符中的字节数。这意味着你不应该使用指针算数遍历字符串中的字符，也意味着你不应该使用<classname>std::string</classname>以及像<function>strlen()</function>这样的与字符串有关的标准C函数，因为他们都对字符的字节数做了假设。

en: However, you probably already avoid bare char* arrays and pointer arithmetic by using <classname>std::string</classname>, so you just need to start using <classname>Glib::ustring</classname> instead. See the <link linkend="sec-basics-ustring">Basics</link> chapter about <classname>Glib::ustring</classname>.
zh_CN: 你可能已经通过使用<classname>std::string</classname>避免了使用原始的<literal>char*</literal>和<literal>char[]</literal>进行指针算数。那么你只需要换成使用<classname>Glib::ustring</classname>即可。更多详情请参阅<link linkend="sec-basics-ustring">Glib::ustring基础</link>章节。

en: Glib::ustring and std::iostreams
zh_CN: Glib::ustring和std::iostreams

en: Unfortunately, the integration with the standard iostreams is not completely foolproof. <application>gtkmm</application> converts <classname>Glib::ustring</classname>s to a locale-specific encoding (which usually is not UTF-8) if you output them to an <classname>ostream</classname> with <function>operator&lt;&lt;</function>. Likewise, retrieving <classname>Glib::ustring</classname>s from <classname>istream</classname> with <function>operator&gt;&gt;</function> causes a conversion in the opposite direction. But this scheme breaks down if you go through a <classname>std::string</classname>, e.g. by inputting text from a stream to a <classname>std::string</classname> and then implicitly converting it to a <classname>Glib::ustring</classname>. If the string contained non-ASCII characters and the current locale is not UTF-8 encoded, the result is a corrupted <classname>Glib::ustring</classname>. You can work around this with a manual conversion. For instance, to retrieve the <classname>std::string</classname> from a <classname>ostringstream</classname>:
zh_CN: 不幸的是，与标准<classname>iostreams</classname>的集成并非绝对安全的。如果你将<classname>Glib::ustring</classname>使用<function>operator&lt;&lt;</function>输出到<classname>ostream</classname>中，则<application>gtkmm</application>会将<classname>Glib::ustring</classname>转换为使用特定语言编码（通常不会是UTF-8编码）。而使用<function>operator&gt;&gt;</function>将<classname>istream</classname>输入到<classname>Glib::ustring</classname>会发生相反的转换。但是如果你通过<classname>std::string</classname>进行则该方案会失效，例如，从文本输入流转换成<classname>std::string</classname>再隐式转换为<classname>Glib::ustring</classname>。如果该字符串中包含非ASCII字符且当前的语言环境不使用UTF-8编码，则得到的结果是一个损坏的<classname>Glib::ustring</classname>。你可以通过手动转换编码解决此问题。例如，若要从<classname>ostringstream</classname>中接受<classname>std::string</classname>：

en: Pitfalls
zh_CN: 陷阱

en: There are a few common mistakes that you would discover eventually yourself. But this section might help you to avoid them.
zh_CN: 有几个你最终会自己发现的错误。但本小节可能能帮助你避免它们。

en: Same strings, different semantics
zh_CN: 不同语义的同一字符串。

en: Sometimes two English strings are identical but have different meanings in different contexts, so they would probably not be identical when translated. Since the English strings are used as look-up keys, this causes problems.
zh_CN: 有时，两个英文字符串是相同的但是在不同的上下文中有不同的含义，因此他们的译文不一定相同。此时用英文字符串作为查找键会引起问题。

en: In these cases, you should add extra characters to the strings. For instance, use <literal>"jumps[noun]"</literal> and <literal>"jumps[verb]"</literal> instead of just <literal>"jumps"</literal> and strip them again outside the <function>gettext</function> call. If you add extra characters you should also add a comment for the translators before the <function>gettext</function> call. Such comments will be shown in the <filename>.po</filename> files. For instance:
zh_CN: 在这个情况下，你应该在字符串中添加额外的字符。例如，使用<literal>"jumps[noun]"</literal>和<literal>"jumps[verb]"</literal>而不是用<literal>"jumps"</literal>并在调用<function>gettext</function>后将它们剥离。如果你添加了额外的字符，你还应该在调用<function>gettext</function>之前为译者添加注释。这样的注释将被显示于<filename>.po</filename>中。例如：

en: If you use <application>Glib</application>'s support macros, it's easier. Use <function>C_()</function> instead of <function>_()</function>. For instance:
zh_CN: 如果你使用<application>Glib</application>宏，将会更为方便。你只需要使用<function>C_()</function>替换<function>_()</function>。例如：

en: Composition of strings
zh_CN: 合成字符串

en: C programmers use <function>sprintf()</function> to compose and concatenate strings. C++ favours streams, but unfortunately, this approach makes translation difficult, because each fragment of text is translated separately, without allowing the translators to rearrange them according to the grammar of the language.
zh_CN: C程序员使用<function>sprintf()</function>合成和拼接字符串。而C++支持流，不幸的是，使用这种方法生成的字符串将给翻译带来困难，因为文本被分成了多个片段，译者必须分开翻译多个片段而不能进行重新排列，这会导致很多字符串无法被正确翻译。

en: For instance, this code would be problematic:
zh_CN: 例如，此代码将会出现问题：

en: So you should either avoid this situation or use <ulink url="http://developer.gnome.org/glibmm/unstable/classGlib_1_1ustring.html"><function>Glib::ustring::compose()</function></ulink> which supports syntax such as:
zh_CN: 因此你应该避免这种情况的出现或者使用<ulink url="http://developer.gnome.org/glibmm/unstable/classGlib_1_1ustring.html"><function>Glib::ustring::compose()</function></ulink>以支持如下所示的语法：

en: Assuming the displayed size of strings
zh_CN: 假设显示字符串所需的空间

en: You never know how much space a string will take on screen when translated. It might very possibly be twice the size of the original English string. Luckily, most <application>gtkmm</application> widgets will expand at runtime to the required size.
zh_CN: 你永远不知道一个字符串被翻译后要在屏幕上显示它需要消耗多少空间。它可能是原始英文字符串的两倍甚至更多。幸运的是 <application>gtkmm</application>的多数部件都能在运行时自动扩展到需要的尺寸。

en: Unusual words
zh_CN: "黑话"

en: You should avoid cryptic abbreviations, slang, or jargon. They are usually difficult to translate, and are often difficult for even native speakers to understand. For instance, prefer "application" to "app"
zh_CN: 你应该避免使用不常见的用于例如缩写、俚语、行话。通常它们对于译者来说很难翻译，甚至将该语言作为母语的译者也无法理解。例如，最好使用"application"而不是"app"

en: Using non-ASCII characters in strings
zh_CN: 在字符串中使用非ASCII字符

en: Currently, <application>gettext</application> does not support non-ASCII characters (i.e. any characters with a code above 127) in source code. For instance, you cannot use the copyright sign (©).
zh_CN: 当前，<application>gettext</application>并不支持在源代码中使用非ASCII字符。例如，你不能使用版权标志（©）

en: To work around this, you could write a comment in the source code just before the string, telling the translators to use the special character if it is available in their languages. For English, you could then make an American English <filename>en_US.po</filename> translation which used that special character.
zh_CN: 要解决这个问题你可以使用注释提醒译者可以使用他们语言中可用的特殊字符。对于英语用户你可以在美国英语<filename>en_US.po</filename>翻译中使用特殊字符。

en: Getting help with translations
zh_CN: 获取翻译帮助

en: If your program is free software, there is a whole <literal>GNOME</literal> subproject devoted to helping you make translations, the <ulink url="https://wiki.gnome.org/TranslationProject/"><literal>GNOME</literal> Translation Project</ulink>.
zh_CN: 如果你的程序是免费软件，有一个致力于帮助你制作翻译的<literal>GNOME</literal>子项目：<ulink url="https://wiki.gnome.org/TranslationProject/"><literal>GNOME</literal>翻译项目</ulink>。

en: The way it works is that you upload your source code to a git repository where translators can access it, then contact the gnome-i18n mailing list and ask to have your program added to the <ulink url="http://l10n.gnome.org/module/">list of modules to translate</ulink>.
zh_CN: 它的工作方式是将你的源代码上传到git储存库，以便翻译人员可以访问它，然后联系gnome-i18n请求将你的程序添加到<ulink url="http://l10n.gnome.org/module/">待翻译模块列表</ulink>中。

en: Then you make sure you update the file <filename>POTFILES.in</filename> in the <filename>po/</filename> subdirectory (<command>intltool-update -m</command> can help with this) so that the translators always access updated <filename>myprogram.pot</filename> files, and simply freeze the strings at least a couple of days before you make a new release, announcing it on gnome-i18n. Depending on the number of strings your program contains and how popular it is, the translations will then start to tick in as <filename>languagename.po</filename> files.
zh_CN: 然后请确保更新<filename>po/</filename>子目录下的<filename>POTFILES.in</filename>（<command>intltool-update -m</command>可以提供帮助），以便译者始终可以访问更新好的<filename>myprogram.pot</filename>文件，并在发布新版本之前的两三天在gnome-i18n邮件列表上宣布冻结字符串更改。根据程序所包含的字符串数数量以及程序的受欢迎程度，译者将逐渐向你提交<filename>languagename.po</filename>文件。

en: Note that most language teams only consist of 1-3 persons, so if your program contains a lot of strings, it might last a while before anyone has the time to look at it. Also, most translators do not want to waste their time (translating is a very time-consuming task) so if they do not assess your project as being really serious (in the sense that it is polished and being maintained) they may decide to spend their time on some other project.
zh_CN: 请注意，大多数语言的翻译团队仅有1-3位成员，所以如果你的程序包含了很多的字符串，则可能需要很长时间才有译者查看它。此外，大多数译者都不想浪费时间，因此如果他们认为你的项目质量很低，他们可能不会想为你提供翻译。

en: Custom Widgets
zh_CN: 自定义部件

en: <application>gtkmm</application> makes it very easy to derive new widgets by inheriting from an existing widget class, either by deriving from a container and adding child widgets, or by deriving from a single-item widget, and changing its behaviour. But you might occasionally find that no suitable starting point already exists. In this case, you can implement a widget from scratch.
zh_CN: <application>gtkmm</application>可以很轻松的通过继承现有部件类、从容器派生并向其中添加子部件、从单项部件派生并修改其行为等手段派生新的部件。但有时你会发现找不到合适的起点。在这种情况下你可以从头实现部件。

en: Custom Containers
zh_CN: 自定义容器

en: <methodname>get_request_mode_vfunc()</methodname>: Return what <literal>Gtk::SizeRequestMode</literal> is preferred by the container.
zh_CN: <methodname>get_request_mode_vfunc()</methodname>：返回容器的<literal>Gtk::SizeRequestMode</literal>偏好。

en: <methodname>measure_vfunc()</methodname>: Calculate the minimum and natural width or height of the container.
zh_CN: <methodname>measure_vfunc()</methodname>：返回容器的最小自然宽度或高度。

en: <methodname>on_size_allocate()</methodname>: Position the child widgets, given the height and width that the container has actually been given.
zh_CN: <methodname>on_size_allocate()</methodname>：根据容器实际宽度和高度定位子部件。

en: When deriving a custom container widget directly from <classname>Gtk::Widget</classname>, you should override the following virtual methods: <_:itemizedlist-1/>
zh_CN: 直接从<classname>Gtk::Widget</classname>派生自定义容器部件时，应重写一下虚方法：<_:itemizedlist-1/>

en: The <methodname>get_request_mode_vfunc()</methodname>, <methodname>measure_vfunc()</methodname>, and <methodname>on_size_allocate()</methodname> virtual methods control the layout of the child widgets. For instance, if your container has 2 child widgets, with one below the other, your <methodname>get_request_mode_vfunc()</methodname> might request height-for-width layout. Then your <methodname>measure_vfunc()</methodname> might report the maximum of the widths of the child widgets when asked to report width, and it might report the sum of their heights when asked to report height. If you want padding between the child widgets then you would add that to the width and height too. Your widget's container will use this result to ensure that your widget gets enough space, and not less. By examining each widget's parent, and its parent, this logic will eventually decide the size of the top-level window.
zh_CN: <methodname>get_request_mode_vfunc()</methodname>、<methodname>measure_vfunc()</methodname>、<methodname>on_size_allocate()</methodname>虚方法控制子部件的布局。例如，如果你的容器有两个子部件，一个在另一个的下方，则你的<methodname>get_request_mode_vfunc()</methodname>可能会请求布局高度适应宽度。然后你的<methodname>measure_vfunc()</methodname>可能会要求报告宽度的时候报告子部件的最大宽度，在要求报告高度的时候要求子部件的高度之和。如果你想要在子部件之间进行填充，则你应将填充部分算入宽高中。你的容器部件将用这个结果确保部件获得足够的空间。通过对每个部件的父部件进行检查最终确认顶级窗口的大小。

en: You are not guaranteed to get the <literal>Gtk::SizeRequestMode</literal> that you request. Therefore <methodname>measure_vfunc()</methodname> must return sensible values for all reasonable values of its input parameters. For a description of <methodname>measure_vfunc()</methodname>'s parameters see also the description of <methodname>Gtk::Widget::measure()</methodname>, which may be better documented than <methodname>measure_vfunc()</methodname>.
zh_CN: 你无法确保得到你请求的<literal>Gtk::SizeRequestMode</literal>。因此，<methodname>measure_vfunc()</methodname>必须为其所有合理的输入参数值返回合适的值。有关<methodname>measure_vfunc()</methodname>参数的描述，查看<methodname>Gtk::Widget::measure()</methodname>的描述可能比查看<methodname>measure_vfunc()</methodname>的文档更好。

en: <methodname>on_size_allocate()</methodname> receives the actual height and width that the parent container has decided to give to your widget. This might be more than the minimum, or even more than the natural size, for instance if the top-level window has been expanded. You might choose to ignore the extra space and leave a blank area, or you might choose to expand your child widgets to fill the space, or you might choose to expand the padding between your widgets. It's your container, so you decide.
zh_CN: <methodname>on_size_allocate()</methodname>接收父容器决定给你的部件的实际高度和宽度。例如，如果顶层窗口被扩展，则该值将大于最小值，甚至大于自然大小。你可以选择忽略多余的空间留出一个空白区域，或者选择扩展子部件以填充该空间，或者是选择扩展部件之间的填充。

en: This example implements a container with two child widgets, one above the other. Of course, in this case it would be far simpler just to use a vertical <classname>Gtk::Box</classname> or <classname>Gtk::Grid</classname>.
zh_CN: 本示例实现了一个具有两个子部件的容器，一个在另一个上面。当然在这种情况下直接使用垂直<classname>Gtk::Box</classname>或<classname>Gtk::Grid</classname>会更简单。

en: Custom Container
zh_CN: 自定义容器

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/custom/custom_container/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/custom/custom_container/">源代码</ulink>

en: By deriving directly from <classname>Gtk::Widget</classname> you can do all the drawing for your widget directly, instead of just arranging child widgets. For instance, a <classname>Gtk::Label</classname> draws the text of the label, but does not do this by using other widgets.
zh_CN: 通过从<classname>Gtk::Widget</classname>派生部件你可以为部件绘制所有的图形，而不仅仅是排列子部件。例如：<classname>Gtk::Label</classname>不需要使用其他部件即可绘制标签文本。

en: <methodname>get_request_mode_vfunc()</methodname>: (optional) Return what <literal>Gtk::SizeRequestMode</literal> is preferred by the widget.
zh_CN: <methodname>get_request_mode_vfunc()</methodname>：覆写此虚函数是可选的，返回此部件的<literal>Gtk::SizeRequestMode</literal>偏好。

en: <methodname>measure_vfunc()</methodname>: Calculate the minimum and natural width or height of the widget.
zh_CN: <methodname>measure_vfunc()</methodname>：计算此部件的最小自然高度或宽度。

en: <methodname>on_size_allocate()</methodname>: Position the widget, given the height and width that it has actually been given.
zh_CN: <methodname>on_size_allocate()</methodname>：提供将实际给予部件的宽度和高度以定位部件。

en: <methodname>on_realize()</methodname>: Associate a <classname>Gdk::Surface</classname> with the widget.
zh_CN: <methodname>on_realize()</methodname>：将一个<classname>Gdk::Surface</classname>与部件相关联。

en: <methodname>on_unrealize()</methodname>: (optional) Break the association with the <classname>Gdk::Surface</classname>.
zh_CN: <methodname>on_unrealize()</methodname>：覆写此虚函数是可选的，断开<classname>Gdk::Surface</classname>与部件的关联。

en: <methodname>on_map()</methodname>: (optional)
zh_CN: <methodname>on_map()</methodname>：覆写此虚函数是可选的。

en: <methodname>on_unmap()</methodname>: (optional)
zh_CN: <methodname>on_unmap()</methodname>：覆写此虚函数是可选的。

en: <methodname>snapshot_vfunc()</methodname>: Create a render node, e.g. a <classname>Cairo::Context</classname> node, and draw on it.
zh_CN: <methodname>snapshot_vfunc()</methodname>：创建一个渲染节点（例如：一个<classname>Cairo::Context</classname>节点），并在其上进行绘制。

en: When deriving from <classname>Gtk::Widget</classname>, you should override the following virtual methods. The methods marked (optional) need not be overridden in all custom widgets. The base class's methods may be appropriate. <_:itemizedlist-1/>
zh_CN: 当你从<classname>Gtk::Widget</classname>派生部件时，你应该覆写以下虚函数。其中标记为可选的的虚函数不必在所有自定义部件中都进行覆写。它们的基类方法通常情况下已经很合适。<_:itemizedlist-1/>

en: The first 3 methods in the previous table are also overridden in custom containers. They are briefly described in the <link linkend="sec-custom-containers">Custom Containers</link> section.
zh_CN: 上述前三个函数在自定义容器中也被覆写。它们在<link linkend="sec-custom-containers">自定义容器</link>小节做了简要说明。

en: Class Init and Instance Init Functions
zh_CN: 类初始化和实例初始化函数

en: Some <application>GTK</application> functions, if called at all, must be called from the class init function. Some other <application>GTK</application> functions, if called, must be called from the instance init function. If your custom widget must call any of those functions, you can derive a class from <classname>Glib::ExtraClassInit</classname> and derive your custom class from that class. The following example shows how that's done.
zh_CN: 一些<application>GTK</application>函数必须在类的init函数中才能调用。另一些<application>GTK</application>函数必须在实例的init函数中才能调用。如果你的自定义部件必须调用这些函数中的任意一个，那么你可以从<classname>Glib::ExtraClassInit</classname>派生一个类，并从该类派生你的自定义类。以下示例演示了如何完成这些操作。

en: Custom Style Information
zh_CN: 自定义样式信息

en: Your widget class, whether it's derived directly from <classname>Gtk::Widget</classname> or from another widget class, can read some style information from a CSS (Cascading Style Sheets) file. The users of your widget, or the users of an application program with your widget, can then modify the style of your widget without modifying the source code. Useful classes are <classname>Gtk::StyleContext</classname> and <classname>Gtk::CssProvider</classname>. With the methods of <classname>Gtk::StyleContext</classname> you can read the values of your widget's style information. CSS files are described in the documentation of <application>GTK</application>. The following example shows a simple use of <methodname>Gtk::StyleContext::get_padding()</methodname>.
zh_CN: 无论你的部件类是从<classname>Gtk::Widget</classname>还是从其他部件类派生的，它都可以从CSS文件中读取样式信息。然后对于使用你的部件的用户或是使用你的部件的应用程序的用户而言，他们可以不需要修改源代码就能修改部件的样式。用于实现此功能的类是<classname>Gtk::StyleContext</classname>和<classname>Gtk::CssProvider</classname>。你可以使用<classname>Gtk::StyleContext</classname>类的方法读取部件样式信息。<application>GTK</application>文档描述了其对于CSS文件的支持情况。以下是示例演示了<methodname>Gtk::StyleContext::get_padding()</methodname>的简单用法。

en: This example implements a widget which draws Penrose triangles.
zh_CN: 本示例实现了绘制彭罗斯三角形的部件

en: Custom Widget
zh_CN: 自定义部件

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/custom/custom_widget/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/custom/custom_widget/">源代码</ulink>

en: Multi-threaded programs
zh_CN: 多线程程序

en: The constraints
zh_CN: 约束条件

en: These interactions arise from the fact that, amongst other things, a class inheriting from <classname>sigc::trackable</classname> will, via that inheritance, have a <classname>std::list</classname> object keeping track of slots created by calls to <function>sigc::mem_fun()</function> representing any of its non-static methods (more particularly it keeps a list of callbacks which will null the connected slots on its destruction). Each <classname>sigc::slot</classname> object also keeps, via <classname>sigc::slot_rep</classname>, its own <classname>sigc::trackable</classname> object to track any <classname>sigc::connection</classname> objects which it needs to inform about its demise, and also has a function to deregister itself from any <classname>sigc::trackable</classname> on disconnection or destruction. <classname>sigc::signal</classname> objects also keep lists of slots, which will be updated by a call to their <methodname>connect()</methodname> method or calls to any <classname>sigc::connection</classname> object relating to such a connection.
zh_CN: 这些交互产生了以下事实：从<classname>sigc::trackable</classname>继承的类将从该继承获得一个<classname>std::list</classname>对象，该对象用于对调用<function>sigc::mem_fun()</function>所创建的槽（它表示任意非静态成员函数）进行跟踪（更特别的是它还保留了一个回调列表，在其被销毁时将已连接的槽置空）。每个<classname>sigc::slot</classname>通过<classname>sigc::slot_rep</classname>保留其自己的<classname>sigc::trackable</classname>对象，用以跟踪任何它需要通知其已消亡的<classname>sigc::connection</classname>对象，并且具有在任何<classname>sigc::trackable</classname>断开连接或销毁时注销自身的能力。<classname>sigc::signal</classname>对象还保留了槽列表，这个列表将通过调用它的<methodname>connect()</methodname>方法或任何与该连接有关的<classname>sigc::connection</classname>对象进行更新。

en: Care is required when writing programs based on <application>gtkmm</application> using multiple threads of execution, arising from the fact that <application>libsigc++</application>, and in particular <classname>sigc::trackable</classname>, are not thread-safe. That's because none of the complex interactions that occur behind the scenes when using <application>libsigc++</application> are protected by a mutex or other means of synchronization. <_:footnote-1/>
zh_CN: 由于<application>libsigc++</application>（尤其是<classname>sigc::trackable</classname>）不是线程安全的，所以在编写基于<application>gtkmm</application>的多线程程序时需要格外小心。这是因为使用<application>libsigc++</application>时在幕后发生的复杂交互不受互斥量或其他同步方式的保护。

en: The rules
zh_CN: 规则

en: This requires a number of rules to be observed when writing multi-threaded programs using <application>gtkmm</application>. These are set out below, but one point to note is that extra care is required when deriving classes from <classname>sigc::trackable</classname>, because the effects are unintuitive (see particularly points 4 and 5 below).
zh_CN: 在使用<application>gtkmm</application>编写多线程程序时需要遵守许多规则。这些规则下下面列出，但要注意的一点是从<classname>sigc::trackable</classname>派生类时需要格外小心，因为效果很不直观（特别是下述4、5条）。

en: Use <classname>Glib::Dispatcher</classname> to invoke <application>gtkmm</application> functions from worker threads (this is dealt with in more detail in the next section).
zh_CN: 使用<classname>Glib::Dispatcher</classname>在工作线程中调用<application>gtkmm</application>函数（这点将在下一节详细介绍）

en: A <classname>sigc::signal</classname> object should be regarded as owned by the thread which created it. Only that thread should connect a <classname>sigc::slot</classname> object to the signal object, and only that thread should <methodname>emit()</methodname> or call <methodname>operator()()</methodname> on the signal, or null any connected <classname>sigc::slot</classname> object. It follows (amongst other things) that any signal object provided by a <application>gtkmm</application> widget should only be operated on in the main GUI thread and any object deriving from <classname>sigc::trackable</classname> having its non-static methods referenced by slots connected to the signal object should only be destroyed in that thread.
zh_CN: <classname>sigc::signal</classname>对象被创建其的线程所拥有。只有该线程应该将<classname>sigc::slot</classname>对象连接到信号对象，并且只有该线程应该在<methodname>emit()</methodname>信号或在信号上调用<methodname>operator()()</methodname>或是将已连接的<classname>sigc::slot</classname>对象置空。因此任何由<application>gtkmm</application>部件提供的信号对象都只应该在主GUI线程进行操作，以及任何从<classname>sigc::trackable</classname>派生的对象（其非静态方法由连接到信号对象的槽引用）都应该在该线程中销毁。

en: Any <classname>sigc::connection</classname> object should be regarded as owned by the thread in which the method returning the <classname>sigc::connection</classname> object was called. Only that thread should call <classname>sigc::connection</classname> methods on the object.
zh_CN: 任何<classname>sigc::connection</classname>对象都应视线程的拥有者在此线程调用了返回<classname>sigc::connection</classname>对象的方法。只有该线程才应在此对象上调用<classname>sigc::connection</classname>方法。

en: A <classname>sigc::slot</classname> object created by a call to <function>sigc::mem_fun()</function> which references a method of a class deriving from <classname>sigc::trackable</classname> should never be copied to another thread, nor destroyed by a different thread than the one which created it.
zh_CN: 通过调用<function>sigc::mem_fun()</function>函数创建的<classname>sigc::slot</classname>对象具有由<classname>sigc::trackable</classname>所派生类的成员函数的引用，请勿将其复制到另一个线程中，也不要让除创建线程以外的线程销毁它。

en: If a particular class object derives from <classname>sigc::trackable</classname>, only one thread should create <classname>sigc::slot</classname> objects representing any of the class's non-static methods by calling <function>sigc::mem_fun()</function>. The first thread to create such a slot should be regarded as owning the relevant object for the purpose of creating further slots referencing <emphasis>any</emphasis> of its non-static methods using that function, or nulling those slots by disconnecting them or destroying the trackable object.
zh_CN: 如果从<classname>sigc::trackable</classname>派生一个特定的类对象，只应有一个线程通过调用<function>sigc::mem_fun()</function>创建代表该类任意非静态成员函数的<classname>sigc::slot</classname>对象。第一个创建这样的槽的线程被视为拥有相关对象的线程。这个线程可以对该类的<emphasis>任意</emphasis>非静态成员函数使用该函数以创建槽，或者在<classname>sigc::trackable</classname>对象断开连接和被销毁时将那些槽无效化。

en: Although <application>glib</application> is itself thread-safe, any <application>glibmm</application> wrappers which use <application>libsigc++</application> will not be. So for example, only the thread in which a main loop runs should call <methodname>Glib::SignalIdle::connect()</methodname>, <methodname>Glib::SignalIO::connect()</methodname>, <methodname>Glib::SignalTimeout::connect()</methodname>, <methodname>Glib::SignalTimeout::connect_seconds</methodname> for that main loop, or manipulate any <classname>sigc::connection</classname> object returned by them.
zh_CN: 尽管<application>glib</application>自身是线程安全的，但是任何使用了<application>libsigc++</application>的<application>glibmm</application>封装都不会是线程安全的。因此只有在运行主循环的线程的主循环中才能调用<methodname>Glib::SignalIdle::connect()</methodname>、<methodname>Glib::SignalIO::connect()</methodname>、<methodname>Glib::SignalTimeout::connect()</methodname>、<methodname>Glib::SignalTimeout::connect_seconds</methodname>或是处理由它们返回的<classname>sigc::connection</classname>对象。

en: The connect*_once() variants, <methodname>Glib::SignalIdle::connect_once()</methodname>, <methodname>Glib::SignalTimeout::connect_once()</methodname>, <methodname>Glib::SignalTimeout::connect_seconds_once()</methodname>, are thread-safe for any case where the slot is not created by a call to <function>sigc::mem_fun()</function> which represents a method of a class deriving from <classname>sigc::trackable</classname>.
zh_CN: 对于<methodname>Glib::SignalIdle::connect_once()</methodname>、<methodname>Glib::SignalTimeout::connect_once()</methodname>、<methodname>Glib::SignalTimeout::connect_seconds_once()</methodname>等connect*_once()变体函数而言，只要它们使用的槽不是通过对<classname>sigc::trackable</classname>派生类的成员函数调用<function>sigc::mem_fun()</function>创建的，那么它们在任何情况下都是线程安全的。

en: Using Glib::Dispatcher
zh_CN: 使用<classname>Glib::Dispatcher</classname>

en: The slots connected to <classname>sigc::signal</classname> objects execute in the thread which calls <methodname>emit()</methodname> or <methodname>operator()()</methodname> on the signal. <classname>Glib::Dispatcher</classname> does not behave this way: instead its connected slots execute in the thread in which the <classname>Glib::Dispatcher</classname> object was constructed (which must have a glib main loop). If a <classname>Glib::Dispatcher</classname> object is constructed in the main GUI thread (which will therefore be the receiver thread), any worker thread can emit on it and have the connected slots safely execute <application>gtkmm</application> functions.
zh_CN: 连接到<classname>sigc::signal</classname>对象的槽将会在调用信号<methodname>emit()</methodname>、<methodname>operator()()</methodname>方法的线程被调用。而<classname>Glib::Dispatcher</classname>的行为与此相反：与其连接的槽将在构造<classname>Glib::Dispatcher</classname>对象的线程执行（该线程必须正在运行Glib主循环）。如果在GUI主线程上构造了<classname>Glib::Dispatcher</classname>，任何工作线程都可以在其上调用<methodname>emit()</methodname>并让槽安全的执行连接的<application>gtkmm</application>函数。

en: Some thread safety rules on the use of <classname>Glib::Dispatcher</classname> still apply. As mentioned, a <classname>Glib::Dispatcher</classname> object must be constructed in the receiver thread (the thread in whose main loop it will execute its connected slots). By default this is the main program thread, although there is a <classname>Glib::Dispatcher</classname> constructor which can take the <classname>Glib::MainContext</classname> object of any thread which has a main loop. Only the receiver thread should call <methodname>connect()</methodname> on the <classname>Glib::Dispatcher</classname> object, or manipulate any related <classname>sigc::connection</classname> object, unless additional synchronization is employed. However, any worker thread can safely emit on the <classname>Glib::Dispatcher</classname> object without any locking once the receiver thread has connected the slots, provided that it is constructed before the worker thread is started (if it is constructed after the thread has started, additional synchronization will normally be required to ensure visibility).
zh_CN: 一些线程安全规则对于<classname>Glib::Dispatcher</classname>依旧适用。如前所述，必须在接收器线程（将在该线程的主循环中执行连接的槽）构造<classname>Glib::Dispatcher</classname>对象。默认情况下接收器线程应该是程序的主进程，尽管<classname>Glib::Dispatcher</classname>有一个可以接受<classname>Glib::MainContext</classname>对象为参数并且可以在任何运行Glib主循环的线程中调用的构造函数。只有接受者线程才应该在<classname>Glib::Dispatcher</classname>对象上调用<methodname>connect()</methodname>或操纵相关的<classname>sigc::connection</classname>对象，除非你为此提供了额外的同步措施。一旦接收器线程连接了槽，任何工作现场都可以不加锁直接在<classname>Glib::Dispatcher</classname>对象上调用<methodname>emit()</methodname>，但前提是该对象是在工作线程启动前构造的，如果不是则需要进行额外的同步以确保可见性。

en: Aside from the fact that connected slots always execute in the receiver thread, <classname>Glib::Dispatcher</classname> objects are similar to <classname>sigc::signal&lt;void()&gt;</classname> objects. They therefore cannot pass unbound arguments nor return a value. The best way to pass unbound arguments is with a thread-safe (asynchronous) queue. At the time of writing <application>glibmm</application> does not have one, although most people writing multi-threaded code will have one available to them (they are relatively easy to write although there are subtleties in combining thread safety with strong exception safety).
zh_CN: 除了连接的槽在接收者线程执行以外，<classname>Glib::Dispatcher</classname>对象的行为与<classname>sigc::signal&lt;void()&gt;</classname>对象十分相似。因此它们不能传递未绑定的参数，也不能返回值。要传递未绑定参数最好的方法是使用线程安全的（同步）队列。尽管大多数编写多线程代码的人都会有一个可用的多线程代码，但是编写<application>glibmm</application>时没有（尽管线程安全与强异常安全结合有些微妙，但编写它们相对容易）。

en: A <classname>Glib::Dispatcher</classname> object can be emitted on by the receiver thread as well as by a worker thread, although this should be done within reasonable bounds. On unix-like systems <classname>Glib::Dispatcher</classname> objects share a single common pipe, which could in theory at least fill up on a very heavily loaded system running a program with a very large number of <classname>Dispatcher</classname> objects in use. Were the pipe to fill up before the receiver thread's main loop has had an opportunity to read from it to empty it, and the receiver thread attempt to emit and so write to it when it is in that condition, the receiver thread would block on the write, so deadlocking. Where the receiver thread is to emit, a normal <classname>sigc::signal&lt;void()&gt;</classname> object could of course be used instead.
zh_CN: 接收者线程和工作线程都可以调用<classname>Glib::Dispatcher</classname>的<methodname>emit()</methodname>方法，虽然此操作需要在合理的范围内进行。在类Unix系统上<classname>Glib::Dispatcher</classname>共享同一个公共管道，从理论上讲在一个负载很大的系统上运行使用很大数量<classname>Dispatcher</classname>对象的程序至少可以填满系统。如果在接收者线程的主循环有机会读取并清空管道之前，管道已填满且接收器线程在此时尝试对<classname>Dispatcher</classname>调用<methodname>emit()</methodname>并因此对管道进行写入，这样会导致死锁。当然在接收者线程想要发出信号可以使用普通的<classname>sigc::signal&lt;void()&gt;</classname>对象。

en: This is an example program with two threads, one GUI thread, like in all <application>gtkmm</application> programs, and one worker thread. The worker thread is created when you press the <literal>Start work</literal> button. It is deleted when the work is finished, when you press the <literal>Stop work</literal> button, or when you press the <literal>Quit</literal> button.
zh_CN: 这是一个具有两个线程的示例程序，一个与所有<application>gtkmm</application>程序一样的GUI线程，和一个工作线程。当你按下<literal>Start work</literal>按钮时将创建工作线程，当工作完成或你按下<literal>Stop work</literal>按钮或是你按下<literal>Quit</literal>按钮时该线程将被删除。

en: A <classname>Glib::Dispatcher</classname> is used for sending notifications from the worker thread to the GUI thread. The <classname>ExampleWorker</classname> class contains data which is accessed by both threads. This data is protected by a <classname>std::mutex</classname>. Only the GUI thread updates the GUI.
zh_CN: <classname>Glib::Dispatcher</classname>被用于工作线程向GUI线程发送通知。<classname>ExampleWorker</classname>包含两个线程都可以访问的数据。该数据被一个<classname>std::mutex</classname>保护。只有GUI线程对GUI进行更新。

en: Compiling and linking a multi-threaded program can require special compiler and linker options. If you use the <application>g++</application> compiler, add the <literal>-pthread</literal> option. Other compilers may require other options. If you build with <application>meson</application>, it handles the multi-threading complications for you, if you add <function>dependency('threads')</function>.
zh_CN: 编译和链接多线程程序可能需要特殊的编译和链接参数。如果你使用<application>g++</application>编译器你需要添加<literal>-pthread</literal>选项。其他编译器可能会要求使用其他选项。如果你使用<application>meson</application>构建程序，如果你在构建脚本中添加了<function>dependency('threads')</function>，它会帮你处理多线程的复杂性。

en: Multi-Threaded Program
zh_CN: 多线程程序

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/multithread">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/multithread">源代码</ulink>

en: Recommended Techniques
zh_CN: 推荐技术

en: This section is simply a gathering of wisdom, general style guidelines and hints for creating <application>gtkmm</application> applications.
zh_CN: 本小节将向你展示一些创建<application>gtkmm</application>应用程序的智慧、风格指南和提示。

en: Use GNU <application>autoconf</application> and <application>automake</application>! They are your friends :) <application>Automake</application> examines C files, determines how they depend on each other, and generates a <filename>Makefile</filename> so the files can be compiled in the correct order. <application>Autoconf</application> permits automatic configuration of software installation, handling a large number of system quirks to increase portability.
zh_CN: 使用GNU <application>autoconf</application>和<application>automake</application>。<application>Automake</application>检查C文件，确定它们之间的依赖关系，并生成<filename>Makefile</filename>，从而以正确的顺序编译文件。<application>Autoconf</application>允许自动配置软件的安装，处理大量来自系统本身的差异以增强可移植性。

en: Subclass Widgets to better organize your code. You should probably subclass your main <classname>Window</classname> at least. Then you can make your child Widgets and signal handlers members of that class.
zh_CN: 子类部件可以更好的组织你的代码。至少你的主窗口类应该继承<classname>Window</classname>。这样你可以使主窗口的子部件和信号处理函数成为该类的成员。

en: Create your own signals instead of passing pointers around. Objects can communicate with each other via signals and signal handlers. This is much simpler than objects holding pointers to each other and calling each other's methods. <application>gtkmm</application>'s classes uses special versions of <classname>sigc::signal</classname>, but you should use normal <classname>sigc::signal</classname>s, as described in the <application>libsigc++</application> documentation.
zh_CN: 创建你自己的信号而不是传递指针。对象可以通过信号和信号处理函数相互通信。这比持有指向彼此的指针并以此调用彼此的成员函数要简单明了的多。<application>gtkmm</application>类使用特殊版本的<classname>sigc::signal</classname>，但你应该使用<application>libsigc++</application>所述的正常<classname>sigc::signal</classname>。

en: Application Lifetime
zh_CN: 应用程序生命周期

en: Most applications will have only one <classname>Window</classname>, or only one main window. These applications can use the <methodname>Gtk::Application::run(Gtk::Window&amp; window)</methodname> or <methodname>Gtk::Application::run(Gtk::Window&amp; window, int argc, char** argv)</methodname> overloads. They show the window and return when the window has been hidden. This might happen when the user closes the window, or when your code decides to <methodname>hide()</methodname> the window. You can prevent the user from closing the window (for instance, if there are unsaved changes) by overriding <methodname>Gtk::Window::on_delete_event()</methodname>.
zh_CN: 大多数应用程序只有一个<classname>Window</classname>或一个主窗口。这些应用程序可以使用<methodname>Gtk::Application::run(Gtk::Window&amp; window)</methodname>或<methodname>Gtk::Application::run(Gtk::Window&amp; window, int argc, char** argv)</methodname>重载。它们显示窗口并当用户关闭窗口或你的代码决定调用<methodname>hide()</methodname>时返回。你可以通过覆写<methodname>Gtk::Window::on_delete_event()</methodname>成员函数来阻止用户关闭窗口（例如，当有未保存变更你可能想弹出对话框询问用户是否确定要关闭窗口，再根据用户选择确定是否要关闭窗口）。

en: Most of our examples use this technique.
zh_CN: 我们的大多数示例都是用这种技术。

en: Using a <application>gtkmm</application> widget
zh_CN: 使用<application>gtkmm</application>部件

en: Our examples all tend to have the same structure. They follow these steps for using a <classname>Widget</classname>:
zh_CN: 我们的示例都倾向于使用相同的结构。它们按以下步骤使用<classname>Widget</classname>：

en: Declare a variable of the type of <classname>Widget</classname> you wish to use, generally as member variable of a derived container class. You could also declare a pointer to the widget type, and then create it with <literal>new</literal> in your code. Even when using the widget via a pointer, it's still probably best to make that pointer a member variable of a container class so that you can access it later.
zh_CN: 声明一个你想要使用的<classname>Widget</classname>类型变量，通常是作为容器派生类的成员变量。你还可以声明一个指向部件类型的指针，然后在你的代码中使用<literal>new</literal>创建它。即使通过指针使用部件，也应该使该指针成为容器类的成员变量，以便你后续访问它。

en: Set the attributes of the widget. If the widget has no default constructor, then you will need to initialize the widget in the initalizer list of your container class's constructor.
zh_CN: 设置部件的属性。如果部件没有默认构造函数，则你需要在容器类的构造函数的初始化列表中初始化部件。

en: Connect any signals you wish to use to the appropriate handlers.
zh_CN: 为所以你需要使用的信号连接合适的信号处理函数。

en: Pack the widget into a container using the appropriate call, e.g. <methodname>Gtk::Box::append()</methodname>.
zh_CN: 调用适当的函数将部件装入容器中，例如：<methodname>Gtk::Box::append()</methodname>。

en: If you don't want all widgets to be shown, call <methodname>Gtk::Widget::hide()</methodname> on the widgets that you don't want to show. If a container widget is hidden, all of its child widgets are also hidden, even if <methodname>hide()</methodname> is not called on the child widgets.
zh_CN: 如果你不希望显示部件，请对不想要显示的部件调用<methodname>Gtk::Widget::hide()</methodname>可以将其隐藏，当一个容器部件被隐藏，它的所有子部件将一并被隐藏，即便你没有在那些子部件上调用<methodname>hide()</methodname>。

en: Building applications
zh_CN: 构建应用程序

en: This chapter is similar to the "Building applications" chapter in the <ulink url="https://developer.gnome.org/gtk4/unstable/">GTK4 Reference Manual</ulink>. The same application is built, but <application>gtkmm</application> is used instead of <application>GTK</application>.
zh_CN: 本章节与<ulink url="https://developer.gnome.org/gtk4/unstable/">GTK4参考文档</ulink>的"Building applications"章节十分类似。

en: The binary file
zh_CN: 二进制文件

en: This gets installed in <filename>/usr/bin</filename>.
zh_CN: 这将被安装在<filename>/usr/bin</filename>。

en: A desktop file
zh_CN: 桌面文件

en: The desktop file provides important information about the application to the desktop shell, such as its name, icon, D-Bus name, commandline to launch it, etc. It is installed in <filename>/usr/share/applications</filename>.
zh_CN: 桌面文件为桌面shell提供了于应用程序有关的重要信息，例如应用程序的名称、图标D-Bus名、启动时的命令行等。此文件将安装在<filename>/usr/share/applications</filename>。

en: An icon
zh_CN: 图标

en: The icon gets installed in <filename>/usr/share/icons/hicolor/48x48/apps</filename>, where it will be found regardless of the current theme.
zh_CN: 图标将被安装在<filename>/usr/share/icons/hicolor/48x48/apps</filename>，无论当前主题是什么你都可以在其中找到图标。

en: A settings schema
zh_CN: 设置模式

en: If the application uses <classname>Gio::Settings</classname>, it will install its schema in <filename>/usr/share/glib-2.0/schemas</filename>, so that tools like dconf-editor can find it.
zh_CN: 如果应用程序使用了<classname>Gio::Settings</classname>，它需要将它的模式安装到<filename>/usr/share/glib-2.0/schemas</filename>，以便dconf-editor之类的工具可以找到它。

en: Other resources
zh_CN: 其他资源

en: Other files, such as <classname>Gtk::Builder</classname> ui files, are best loaded from resources stored in the application binary itself. This eliminates the need for most of the files that would traditionally be installed in an application-specific location in <filename>/usr/share</filename>.
zh_CN: 像<classname>Gtk::Builder</classname>UI文件这样的其他文件，最好从储存应用程序自身的二进制中加载。这样就不需要按照传统将大多数文件安装在<filename>/usr/share</filename>中特定应用程序的位置。

en: An application consists of a number of files: <_:variablelist-1/>
zh_CN: 一个应用程序由许多文件组成：<_:variablelist-1/>

en: <application>gtkmm</application> includes application support that is built on top of <classname>Gio::Application</classname>. In this chapter we'll build a simple application by starting from scratch, adding more and more pieces over time. Along the way, we'll learn about <classname>Gtk::Application</classname>, <classname>Gtk::Builder</classname>, resources, menus, settings, <classname>Gtk::HeaderBar</classname>, <classname>Gtk::Stack</classname>, <classname>Gtk::SearchBar</classname>, <classname>Gtk::ListBox</classname>, and more.
zh_CN: <application>gtkmm</application>包括构建在<classname>Gio::Application</classname>上的应用程序支持。在本章中我们将从头开始构建一个简单的应用程序。然后逐渐向其中添加更多内容。在此过程中我们将学习<classname>Gtk::Application</classname>、<classname>Gtk::Builder</classname>、资源、菜单、设置、<classname>Gtk::HeaderBar</classname>、<classname>Gtk::Stack</classname>、<classname>Gtk::SearchBar</classname>、<classname>Gtk::ListBox</classname>等内容。

en: The full, buildable sources for these examples can be found in the <filename>examples/book/buildapp</filename> directory of the <application>gtkmm-documentation</application> source distribution, or online in the <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp"><application>gtkmm-documentation</application> git repository</ulink>. You can build each example separately by using <command>meson</command> and <command>ninja</command> with the <filename>meson.build</filename> file or by using <command>make</command> with the <filename>Makefile.example</filename> file. For more information, see the <filename>README</filename> included in the <filename>buildapp</filename> directory.
zh_CN: 这些示例的完整可构建源代码可以从<application>gtkmm-documentation</application>源目录的<filename>examples/book/buildapp</filename>文件夹中找到，或者在<ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp"><application>gtkmm-documentation</application>git仓库</ulink>可以找到。你可以通过<filename>meson.build</filename>文件使用<command>meson</command>和<command>ninja</command>，或是通过<filename>Makefile.example</filename>文件使用<command>make</command>以编译每一个示例。更多有关信息，请参见<filename>buildapp</filename>目录中包含的<filename>README</filename>文件。

en: A trivial application
zh_CN: 简单的应用程序

en: When using <classname>Gtk::Application</classname>, the <function>main()</function> function can be very simple. We just call <methodname>Gtk::Application::run()</methodname> on an instance of our application class.
zh_CN: 使用<classname>Gtk::Application</classname>时，<function>main()</function>函数可以非常简单。我们只是在应用程序类实例上调用<methodname>Gtk::Application::run()</methodname>。

en: All the application logic is in the application class, which is a subclass of <classname>Gtk::Application</classname>. Our example does not yet have any interesting functionality. All it does is open a window when it is activated without arguments, and open the files it is given, if it is started with arguments. (Or rather, our application class tries to open the files, but our subclassed application window does not yet do what it's told to do.)
zh_CN: 应用程序的所有逻辑都在应用程序类中，该类是<classname>Gtk::Application</classname>的子类。现在在我们的示例中还没有任何很有趣的功能。它要做的事就是在没有参数的情况下打开一个窗口，或在有参数的启动状态下打开给定的文件（准确的说我们的应用程序类尝试打开文件，但是应用程序的窗口子类并没有执行应执行的操作）。

en: To handle these two cases, we override <methodname>signal_activate()</methodname>'s default handler, which gets called when the application is launched without commandline arguments, and <methodname>signal_open()</methodname>'s default handler, which gets called when the application is launched with commandline arguments.
zh_CN: 为了处理这两种情况，我们覆写了<methodname>signal_activate()</methodname>和<methodname>signal_open()</methodname>的默认处理函数，在没有命令行参数时前者的处理函数被调用，有命令行参数时后者的处理函数被调用。

en: <ulink url="http://developer.gnome.org/glibmm/unstable/classGio_1_1Application.html">Gio::Application Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/glibmm/unstable/classGio_1_1Application.html">Gio::Application参考</ulink>

en: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Application.html">Gtk::Application Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Application.html">Gtk::Application参考</ulink>

en: Another important class that is part of the application support in <application>gtkmm</application> is <classname>Gtk::ApplicationWindow</classname>. It is typically subclassed as well. Our subclass does not do anything yet, so we will just get an empty window.
zh_CN: 作为<application>gtkmm</application>应用程序支持的另一个重要的类是<classname>Gtk::ApplicationWindow</classname>。通常我们也会将其子类化。此时我们的子类还没有做任何事，所以我们只会得到一个空白的窗口。

en: As part of the initial setup of our application, we also create an icon and a desktop file. Note that @bindir@ in the desktop file needs to be replaced with the actual path to the binary before this desktop file can be used.
zh_CN: 作为应用程序初始设置的一部分，我们还为其创建了一个图标和桌面文件。请注意在使用这个桌面文件之前你还需要将文件中的@bindir@替换为应用程序二进制的实际路径。

en: Here is what we've achieved so far:
zh_CN: 到目前为止我们做到了：

en: This does not look very impressive yet, but our application is already presenting itself on the session bus, it has single-instance semantics, and it accepts files as commandline arguments.
zh_CN: 这看起来还无法让人印象深刻，但是我们的应用程序已经在会话总线上展示了自己。现在它具有单实例语义，并且接受命令行参数作为文件路径。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step1">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step1">源代码</ulink>

en: Populating the window
zh_CN: 填充窗口

en: In this step, we use a <classname>Gtk::Builder</classname> instance to associate a <classname>Gtk::Builder</classname> ui file with our application window class.
zh_CN: 再次步骤中，我们使用<classname>Gtk::Builder</classname>实例将<classname>Gtk::Builder</classname> UI文件和我们的应用程序窗口类相关联。

en: Our simple ui file gives the window a title, and puts a <classname>Gtk::Stack</classname> widget as the main content.
zh_CN: 我们的简单UI文件为窗口设定了一个标题，并将一个<classname>Gtk::Stack</classname>文件放入了窗口中。

en: To make use of this file in our application, we revisit our <classname>Gtk::ApplicationWindow</classname> subclass, and call <methodname>Gtk::Builder::create_from_resource()</methodname> and <methodname>Gtk::Builder::get_widget_derived()</methodname> from the <methodname>ExampleAppWindow::create()</methodname> method to get an instance of our subclassed <classname>Gtk::ApplicationWindow</classname>. See the <link linkend="sec-builder-using-derived-widgets">Using derived widgets</link> section for more information about <methodname>get_widget_derived()</methodname>.
zh_CN: 为了在我们的应用程序中使用这个文件，我们重访<classname>Gtk::ApplicationWindow</classname>子类，并在<methodname>ExampleAppWindow::create()</methodname>成员函数中调用<methodname>Gtk::Builder::create_from_resource()</methodname>和<methodname>Gtk::Builder::get_widget_derived()</methodname>以获取我们的<classname>Gtk::ApplicationWindow</classname>子类的实例。更多有关的<methodname>get_widget_derived()</methodname>的信息，请参见<link linkend="sec-builder-using-derived-widgets">使用派生部件</link>小节。

en: You may have noticed that we use the <methodname>_from_resource()</methodname> variant of the method that reads the ui file. Now we need to use <application>GLib</application>'s resource functionality to include the ui file in the binary. This is commonly done by listing all resources in a .gresource.xml file. This file has to be converted into a C source file that will be compiled and linked into the application together with the other source files. To do so, we use the <application>glib-compile-resources</application> utility: <_:screen-1/> The <link linkend="sec-gio-resource">Gio::Resource and glib-compile-resources</link> section contains more information about resource files. If you build with Meson, use the <function>compile_resources()</function> function in Meson's <ulink url="https://mesonbuild.com/Gnome-module.html">GNOME module</ulink>.
zh_CN: 你可能已经注意到了，我们使用<methodname>_from_resource()</methodname>变体方法读取UI文件。现在，我们要使用<application>GLib</application>资源功能将这个UI文件放入二进制中。通常我们通过在.gresource.xml文件中列出所有资源来完成此操作。该文件必须被转换为C源文件，并将其与其他源文件一并编译链接到应用程序中去。为此，我们使用了<application>glib-compile-resources</application>实用程序：<_:screen-1/> <link linkend="sec-gio-resource">Gio::Resource和glib-compile-resources</link>小节包含了与资源文件有关的信息。如果你使用Meson进行编译，请使用Meson <ulink url="https://mesonbuild.com/Gnome-module.html">GNOME模块</ulink>中的<function>compile_resources()</function>函数。

en: Our application now looks like this:
zh_CN: 我们的应用程序现在看起来像这样：

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step2">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step2">源代码</ulink>

en: Opening files
zh_CN: 打开文件

en: In this step, we make our application show the contents of all the files that it is given on the commandline.
zh_CN: 在这一步中，我们使我们的应用程序显示由命令行参数给定的文件的所有内容。

en: To this end, we add a data member to our application window and keep a pointer to the <classname>Gtk::Stack</classname> there. We get the pointer with a call to <methodname>Gtk::Builder::get_widget()</methodname> in the application window's constructor.
zh_CN: 为此，我们向我们的应用程序窗口中添加一个数据成员，此保持一个指向<classname>Gtk::Stack</classname>的指针。我们通过在应用程序窗口的构造函数中调用<methodname>Gtk::Builder::get_widget()</methodname>获得指向该子部件的指针。

en: Now we revisit the <methodname>ExampleAppWindow::open_file_view()</methodname> method that is called for each commandline argument, and construct a <classname>Gtk::TextView</classname> that we then add as a page to the stack.
zh_CN: 现在我们重访对每个命令行参数都会调用的<methodname>ExampleAppWindow::open_file_view()</methodname>成员函数，并构造一个<classname>Gtk::TextView</classname>然后将其作为页面添加到<classname>Gtk::Stack</classname>中。

en: Lastly, we add a <classname>Gtk::StackSwitcher</classname> to the titlebar area in the ui file, and we tell it to display information about our stack.
zh_CN: 最后，我们将<classname>Gtk::StackSwitcher</classname>添加到UI文件的标题栏区域，并告诉它如何显示<classname>Gtk::Stack</classname>的相关信息。

en: The stack switcher gets all its information it needs to display tabs from the stack that it belongs to. Here, we are passing the label to show for each file as the last argument to the <methodname>Gtk::Stack::add()</methodname> method.
zh_CN: 堆切换器(StackSwitcher)从其所属的堆(Stack)中获取其所需的关于显示选项卡的相关信息。在这，作为<methodname>Gtk::Stack::add()</methodname>方法的最后一个参数，我们为每个显示的文件传递一个标签。

en: Our application is beginning to take shape:
zh_CN: 我们的应用程序开始成形：

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step3">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step3">源代码</ulink>

en: A menu
zh_CN: 菜单

en: The menu is shown at the right side of the headerbar. It is meant to collect infrequently used actions that affect the whole application.
zh_CN: 菜单显示在标题栏的右侧。它旨在放置所有应用程序不常用的动作。

en: Just like the application window, we specify our menu in a ui file, and add it as a resource to our binary.
zh_CN: 就像应用程序窗口一样，我们在UI文件中指定一个菜单，并将其作为资源添加到二进制中。

en: To make the menu appear, we have to load the ui file and associate the resulting menu model with the menu button that we've added to the headerbar. Since menus work by activating <classname>Gio::Action</classname>s, we also have to add a suitable set of actions to our application.
zh_CN: 为了使菜单出现，我们必须加载UI文件，并将生成的菜单模型与添加到标题栏右侧的菜单按钮相关联。由于菜单通过激活<classname>Gio::Action</classname>工作，我们还需要向应用程序中添加一组合适的动作。

en: Adding the actions is best done in the <methodname>on_startup()</methodname> default signal handler, which is guaranteed to be called once for each primary application instance.
zh_CN: 最好在<methodname>on_startup()</methodname>的默认信号处理函数中完成添加动作，并确保每个应用程序实例都只调用一次。

en: Our preferences menu item does not do anything yet, but the Quit menu item is fully functional. It can also be activated by the usual Ctrl-Q shortcut. The shortcut is added with <methodname>Gtk::Application::set_accel_for_action()</methodname>.
zh_CN: 现在我们的首选项菜单还什么都不做，但是退出菜单项是有效的。也可以用常用的Ctrl-Q快捷键激活它。快捷键通过<methodname>Gtk::Application::set_accel_for_action()</methodname>添加。

en: The menu looks like this:
zh_CN: 菜单如下所示

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step4">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step4">源代码</ulink>

en: A preference dialog
zh_CN: 首选项对话框

en: A typical application will have some preferences that should be remembered from one run to the next. Even for our simple example application, we may want to change the font that is used for the content.
zh_CN: 经典的应用程序会有一些首选项，它们应该被记住而不需要在下次运行时在进行设置。即使对于我们这个简单的应用程序示例，我们可能也想改变用于文本内容的字体。

en: We are going to use <classname>Gio::Settings</classname> to store our preferences. <classname>Gio::Settings</classname> requires a schema that describes our settings, in our case the <filename>org.gtkmm.exampleapp.gschema.xml</filename> file.
zh_CN: 我们将使用<classname>Gio::Settings</classname>来储存我们的首选项。<classname>Gio::Settings</classname>需要一个用于描述我们的设置的模式，在本例中为<filename>org.gtkmm.exampleapp.gschema.xml</filename>文件。

en: Before we can make use of this schema in our application, we need to compile it into the binary form that <classname>Gio::Settings</classname> expects. GIO provides macros to do this in autotools-based projects. See the description of <ulink url="https://developer.gnome.org/gio/stable/GSettings.html">GSettings</ulink>. Meson provides the <function>compile_schemas()</function> function in the <ulink url="https://mesonbuild.com/Gnome-module.html">GNOME module</ulink>.
zh_CN: 在我们应用程序使用模式之前，我们需要将其编译为<classname>Gio::Settings</classname>能期望的二进制格式。GUI为此提供了基于autotools项目的宏来执行此操作。具体信息请参阅<ulink url="https://developer.gnome.org/gio/stable/GSettings.html">GSettings</ulink>。而Meson在<ulink url="https://mesonbuild.com/Gnome-module.html">GNOME模块</ulink>中提供了<function>compile_schemas()</function>执行此操作。

en: Next, we need to connect our settings to the widgets that they are supposed to control. One convenient way to do this is to use <methodname>Gio::Settings::bind()</methodname> to bind settings keys to object properties, as we do for the transition setting in <classname>ExampleAppWindow</classname>'s constructor.
zh_CN: 接下来，我们需要将设置连接到应该被控制的部件上。一种很方便的方法是使用<methodname>Gio::Settings::bind()</methodname>将对象的属性和设置键相互绑定，就像我们在<classname>ExampleAppWindow</classname>的构造函数中做的过渡设置一样。

en: The code to connect the font setting is a little more involved, since it corresponds to an object property in a <classname>Gtk::TextTag</classname> that we must first create. The code is in <methodname>ExampleAppWindow::open_file_view()</methodname>.
zh_CN: 字体设置的连接要麻烦的多，因为我们需要先创建对应的对象属性的<classname>Gtk::TextTag</classname>。以下代码在<methodname>ExampleAppWindow::open_file_view()</methodname>函数中。

en: At this point, the application will already react if you change one of the settings, e.g. using the <command>gsettings</command> commandline tool. Of course, we expect the application to provide a preference dialog for these. So lets do that now. Our preference dialog will be a subclass of <classname>Gtk::Dialog</classname>, and we'll use the same techniques that we've already seen in <classname>ExampleAppWindow</classname>: a <classname>Gtk::Builder</classname> ui file and settings bindings.
zh_CN: 此时，如果你更改其中一项设置（例如：使用<command>gsettings</command>命令行工具。），则应用程序会做出反应。当然，我们会希望应用程序为这些首选项提供一个对话框。所以我们现在就如此做。我们的首选项对话框将是<classname>Gtk::Dialog</classname>的子类，并且使用我们之前已经在<classname>ExampleAppWindow</classname>中看到的技术：<classname>Gtk::Builder</classname> UI文件和设置绑定。

en: When we've created the <filename>prefs.ui</filename> file and the <classname>ExampleAppPrefs</classname> class, we revisit the <methodname>ExampleApplication::on_action_preferences()</methodname> method in our application class, and make it open a new preference dialog.
zh_CN: 我们创建<filename>prefs.ui</filename>文件和<classname>ExampleAppPrefs</classname>子类之后，我们重访<methodname>ExampleApplication::on_action_preferences()</methodname>成员函数，并使其打开一个新的首选项对话框。

en: After all this work, our application can now show a preference dialog like this:
zh_CN: 完成所有工作后，我们的应用程序现在可以显示如下所示的首选项对话框：

en: An preference dialog
zh_CN: 首选项对话框

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step5">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step5">源代码</ulink>

en: Adding a search bar
zh_CN: 添加搜索栏

en: We continue to flesh out the functionality of our application. For now, we add search. <application>gtkmm</application> supports this with <classname>Gtk::SearchEntry</classname> and <classname>Gtk::SearchBar</classname>. The search bar is a widget that can slide in from the top to present a search entry.
zh_CN: 我们将继续充实我们的应用程序的功能。现在，我们向其中添加搜索功能。<application>gtkmm</application>通过<classname>Gtk::SearchEntry</classname>和<classname>Gtk::SearchBar</classname>对此提供了支持。搜索栏是一个部件，可以从从顶部滑入以显示搜索条目。

en: We add a toggle button to the header bar, which can be used to slide out the search bar below the header bar. The new widgets are added in the <filename>window.ui</filename> file.
zh_CN: 我们向标题栏添加了一个开关按钮，可以用于滑出位于标题栏下方的搜索栏。新的部件将添加到<filename>window.ui</filename>文件中。

en: Implementing the search needs quite a few code changes that we are not going to completely go over here. The central piece of the search implementation is a signal handler that listens for text changes in the search entry, shown here without error handling.
zh_CN: 实现搜索需要进行大量的代码更改，在此我们不对其进行详细的介绍。实现搜索的核心部分是一个信号处理函数，它监听搜索条目的变更，此处显示的示例没有进行错误处理。

en: With the search bar, our application now looks like this:
zh_CN: 有了搜索栏后，我们的应用程序看起来像这样：

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step6">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step6">源代码</ulink>

en: Adding a side bar
zh_CN: 添加侧边栏

en: As another piece of functionality, we are adding a sidebar, which demonstrates <classname>Gtk::Revealer</classname> and <classname>Gtk::ListBox</classname>. The new widgets are added in the <filename>window.ui</filename> file.
zh_CN: 作为另一项功能，我们向应用程序中添加了侧边栏，用于演示<classname>Gtk::Revealer</classname>和<classname>Gtk::ListBox</classname>。新的部件将被添加到<filename>window.ui</filename>文件中。

en: The code to populate the sidebar with buttons for the words found in each file is a little too involved to go into here. But we'll look at the code to add a checkbutton for the new feature to the menu. A menu item is added to the ui file <filename>gears_menu.ui</filename>.
zh_CN: 在每个文件中用找到的单词生成按钮填充侧边栏的代码很复杂，这里我们不进行介绍。我们将对为菜单中添加新功能的多选按钮的代码进行介绍。菜单项将被添加到<filename>gears_menu.ui</filename> UI文件中。

en: To connect the menu item to the new <literal>show-words</literal> setting, we use a <classname>Gio::Action</classname> corresponding to the given <classname>Gio::Settings</classname> key. In <classname>ExampleAppWindow</classname>'s constructor:
zh_CN: 我们使用<classname>Gio::Action</classname>与给定的<classname>Gio::Settings</classname>键相关联，以使菜单项与新的<literal>show-words</literal>设置向连接。在<classname>ExampleAppWindow</classname>构造函数中：

en: What our application looks like now:
zh_CN: 现在我们的应用程序看起来像这样：

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step7">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step7">源代码</ulink>

en: Properties
zh_CN: 属性

en: Widgets and other objects have many useful properties. Here we show some ways to use them in new and flexible ways, by wrapping them in actions with <classname>Gio::PropertyAction</classname> or by binding them with <classname>Glib::Binding</classname>.
zh_CN: 部件和其他对象有很多有用的属性。在这里，我们通过一些新颖的使用方法展示了使用它们的方法。例如，将它们包装在<classname>Gio::PropertyAction</classname>动作中或将它们与<classname>Glib::Binding</classname>绑定。

en: To set this up, we add two labels to the header bar in our <filename>window.ui</filename> file, named <literal>lines_label</literal> and <literal>lines</literal>, and get pointers to them in the application window's constructor, as we've seen a couple of times by now. We add a new "Lines" menu item to the gears menu, which triggers the <literal>show-lines</literal> action.
zh_CN: 我们在<filename>window.ui</filename>文件中的标题栏中添加了两个标签，分别命名为<literal>lines_label</literal>和<literal>lines</literal>，并在应用程序窗口的构造函数中获取指向它们的指针。接着我们向齿轮菜单中添加了一个新的"Lines"菜单项，该菜单项会触发<literal>show-lines</literal>动作。

en: To make this menu item do something, we create a property action for the <literal>visible</literal> property of the <literal>lines</literal> label, and add it to the actions of the window. The effect of this is that the visibility of the label gets toggled every time the action is activated. Since we want both labels to appear and disappear together, we bind the <literal>visible</literal> property of the <literal>lines_label</literal> widget to the same property of the <literal>lines</literal> widget. In <classname>ExampleAppWindow</classname>'s constructor:
zh_CN: 为了使此菜单项能执行某些操作，我们为<literal>lines</literal>标签的<literal>visible</literal>属性创建了一个属性动作，并将其添加到窗口动作中。这样做的效果是，每当动作被激活，标签的可见性就会改变。由于我们希望两个标签的可见性一致，因此我们将<literal>lines_label</literal>部件的<literal>visible</literal>属性绑定到<literal>lines</literal>部件的相同属性上。在<classname>ExampleAppWindow</classname>的构造函数中：

en: We also need a function that counts the lines of the currently active tab, and updates the <literal>lines</literal> label. See the full source if you are interested in the details.
zh_CN: 我们还需要一个函数对当前标签页的行进行计数，并更新<literal>lines</literal>标签。如果你对此感兴趣请阅读完整源代码。

en: This brings our example application to this appearance:
zh_CN: 现在我们的示例应用程序看起来如下：

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step8">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step8">源代码</ulink>

en: Header bar
zh_CN: 标题栏

en: Our application already uses a <classname>Gtk::HeaderBar</classname> instead of a 'normal' window titlebar. The header bar is a direct child of the window, and its type is <literal>titlebar</literal>. This is set in the <filename>window.ui</filename> file.
zh_CN: 我们的应用程序使用了<classname>Gtk::HeaderBar</classname>而不是普通的窗口标题栏。标题栏是窗口的直接子项，其类型为<literal>titlebar</literal>。这些由<filename>window.ui</filename>文件进行设置。

en: Here we'll just make two small changes to the header bar. The <literal>decoration-layout</literal> property is set in the <filename>window.ui</filename> file, to show only the close button, and hide the minimize and maximize buttons. We also include an icon in the resource file, and set up this icon as the window icon. In <classname>ExampleAppWindow</classname>'s constructor:
zh_CN: 在这里我们对标题栏进行了两个小的更改。<literal>decoration-layout</literal>属性在<filename>window.ui</filename>文件中设置，使标题栏只显示关闭按钮，并隐藏最小化和最大化按钮。我们还在资源文件中包含了一个图标，并将其设置为窗口图标。在<classname>ExampleAppWindow</classname>的构造函数中：

en: Here is how the application now looks:
zh_CN: 现在应用程序看起来如下所示：

en: The <filename>window.ui</filename> file sets a header bar title, but this title is not shown. That's because the stack switcher is a child of type <literal>title</literal>. The stack switcher becomes a custom title that hides the title label.
zh_CN: <filename>window.ui</filename>文件设置了标题栏标题，但是此标题未显示。这是因为堆切换器是<literal>title</literal>的子类型。此时堆切换器成为了自定义标题并将正常的标题标签隐藏。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step9">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/buildapp/step9">源代码</ulink>

en: Contributing
zh_CN: 贡献

en: This document, like so much other great software out there, was created for free by volunteers. If you are at all knowledgeable about any aspect of <application>gtkmm</application> that does not already have documentation, please consider contributing to this document.
zh_CN: 本文档和其他出色的软件一样，是由志愿者免费创建的。如果你对任何一个<application>gtkmm</application>没有文档的部分有所了解，请考虑帮助编写/翻译本文档。

en: Ideally, we would like you to <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/-/merge_requests"> provide a merge request</ulink> to the <filename>docs/tutorial/C/index-in.docbook</filename> file. This file is in the <literal>gtkmm-documentation</literal> module in GNOME git.
zh_CN: 理想情况下，我们希望你前往此<ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/-/merge_requests">仓库</ulink>为<filename>docs/tutorial/C/index-in.docbook</filename>提供MR。该文件位于GNOME的gitlab <literal>gtkmm-documentation</literal>模块中。

en: If you do decide to contribute, please post your contribution to the <application>gtkmm</application> mailing list at <ulink url="mailto:gtkmm-list@gnome.org">&lt;gtkmm-list@gnome.org&gt;</ulink> or as an issue or merge request to <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation">GitLab</ulink>. Also, be aware that the entirety of this document is free, and any addition you provide must also be free. That is, people must be able to use any portion of your examples in their programs, and copies of this document (including your contribution) may be distributed freely.
zh_CN: 如果你决定做出贡献，请将你的贡献发送到<application>gtkmm</application>邮件列表，网址为<ulink url="mailto:gtkmm-list@gnome.org">&lt;gtkmm-list@gnome.org&gt;</ulink>，或者前往<ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation">GitLab</ulink>新建issue/MR。另外请注意，本文档的全部内容都是免费的，你添加所有内容也需要是免费的。也就是说人们必须能够在程序中使用示例的任何部分，以及自由分发本文档的副本。

en: The RefPtr smartpointer
zh_CN: RefPtr智能指针

en: <classname>Glib::RefPtr</classname> is a smartpointer. Specifically, it is a reference-counting smartpointer. You might be familiar with <classname>std::unique_ptr&lt;&gt;</classname> and <classname>std::shared_ptr&lt;&gt;</classname>, which are also smartpointers. In <application>gtkmm</application>-4.0 <classname>Glib::RefPtr&lt;&gt;</classname> is an alias for <classname>std::shared_ptr&lt;&gt;</classname>, which is reference-counting. <classname>Glib::RefPtr&lt;&gt;</classname> was introduced long before there was a reference-counting smartpointer in the C++ Standard Library.
zh_CN: <classname>Glib::RefPtr</classname>是一个智能指针。准确的说，它是一个引用计数智能指针。你可能对<classname>std::unique_ptr&lt;&gt;</classname>和<classname>std::shared_ptr&lt;&gt;</classname>十分熟悉，它们也是智能指针。在<application>gtkmm</application>-4.0中<classname>Glib::RefPtr&lt;&gt;</classname>是<classname>std::shared_ptr&lt;&gt;</classname>的别名。<classname>Glib::RefPtr&lt;&gt;</classname>在C++标准库还没有添加引用计数智能指针的时候就已经存在于<application>glibmm</application>了（译注：事实上Glib::RefPtr的行为与std::shared_ptr的行为并不完全一致，且因glibmm等库的文档是由C文档直接生成而来，在一些C库中可以接受NULL作为参数的函数在对应的C++绑定库中的文档中都是可以接受nullptr作为参数，但实际上并不一定能接受nullptr作为参数，有时候需要传递Glib::RefPtr&lt;FOO&gt;()、Gdk::Event()、空的字符串等。参见：<ulink url="https://gitlab.gnome.org/GNOME/glibmm/-/issues/24">问题24</ulink>）。

en: <ulink url="http://developer.gnome.org/glibmm/unstable/classGlib_1_1RefPtr.html">Reference</ulink>
zh_CN: <ulink url="http://developer.gnome.org/glibmm/unstable/classGlib_1_1RefPtr.html">参考</ulink>

en: A smartpointer acts much like a normal pointer. Here are a few examples.
zh_CN: 智能指针的行为很像普通指针。这里有几个例子。

en: Copying
zh_CN: 复制

en: You can copy <classname>RefPtr</classname>s, just like normal pointers. But unlike normal pointers, you don't need to worry about deleting the underlying instance.
zh_CN: 你可以像复制普通指针一样复制<classname>RefPtr</classname>，你不需要担心删除底层实例。

en: Of course this means that you can store <classname>RefPtr</classname>s in standard containers, such as <classname>std::vector</classname> or <classname>std::list</classname>.
zh_CN: 这意味着你可以将<classname>RefPtr</classname>储存于标准容器中，例如：<classname>std::vector</classname>或<classname>std::list</classname>。

en: Dereferencing
zh_CN: 解引用

en: You can dereference a smartpointer with the -&gt; operator, to call the methods of the underlying instance, just like a normal pointer.
zh_CN: 你可以使用-&gt;操作符解引用智能指针，就像使用普通指针访问底层实例的方法一样。

en: You can also use the * operator and the <methodname>get()</methodname> method to access the underlying instance, but it's usually a bad idea to do so. Unless you are careful, you can end up with a pointer or a reference which is not included in the reference count.
zh_CN: 你还可以使用*操作符和<methodname>get()</methodname>方法访问底层实例，不过通常这不是一个好主意。除非你非常的谨慎没有犯错，否则你将得到一个不存在于引用计数中的指向底层实例的指针或底层实例的引用。

en: Casting
zh_CN: 类型转换

en: You can cast <classname>RefPtr</classname>s to base types, just like normal pointers.
zh_CN: 你可以像对正常指针进行类型转换一样，将<classname>RefPtr</classname>转换到基础类型。

en: This means that any method which takes a <type>const Glib::RefPtr&lt;BaseType&gt;&amp;</type> argument can also take a <type>const Glib::RefPtr&lt;DerivedType&gt;&amp;</type>. The cast is implicit, just as it would be for a normal pointer.
zh_CN: 这意味着任何接受<type>const Glib::RefPtr&lt;BaseType&gt;&amp;</type>参数的函数也能接受<type>const Glib::RefPtr&lt;DerivedType&gt;&amp;</type>对象。此转换和普通指针一样是隐式的。

en: You can also cast to a derived type, but the syntax is a little different than with a normal pointer.
zh_CN: 你还可以将其转换为派生类型，但是语法和普通指针的语法略有不同。

en: Checking for nullptr
zh_CN: nullptr检查

en: Just like normal pointers, you can check whether a <classname>RefPtr</classname> points to anything.
zh_CN: 就像普通指针一样，你可以检查<classname>RefPtr</classname>是否指向了任何东西。

en: But unlike normal pointers, <classname>RefPtr</classname>s are automatically initialized to <literal>nullptr</literal> so you don't need to remember to do that yourself.
zh_CN: 和普通指针不一样的是，<classname>RefPtr</classname>将会自动初始化为<literal>nullptr</literal>，不需要你自己进行置空。

en: Constness
zh_CN: 常数

en: The use of the <literal>const</literal> keyword in C++ is not always clear. You might not realise that <type>const Something*</type> declares a pointer to a <type>const Something</type>. The pointer can be changed, but not the <type>Something</type> that it points to.
zh_CN: 在C++中<literal>const</literal>关键字的使用并不总是很清晰。你可能没有意识到<type>const Something*</type>声明了一个指向<type>const Something</type>的指针。这个指针的指向是可以被改变的，其指向的<type>Something</type>不能被改变。

en: Therefore, the <classname>RefPtr</classname> equivalent of <type>Something*</type> for a method parameter is <type>const Glib::RefPtr&lt;Something&gt;&amp;</type>, and the equivalent of <type>const Something*</type> is <type>const Glib::RefPtr&lt;const Something&gt;&amp;</type>.
zh_CN: 因此，在方法参数中与<type>Something*</type>等效的<classname>RefPtr</classname>是<type>const Glib::RefPtr&lt;Something&gt;&amp;</type>，而与<type>const Something*</type>等效的是<type>const Glib::RefPtr&lt;const Something&gt;&amp;</type>。

en: The <literal>const ... &amp;</literal> around both is just for efficiency, like using <classname>const std::string&amp;</classname> instead of <classname>std::string</classname> for a method parameter to avoid unnecessary copying.
zh_CN: 用<literal>const ... &amp;</literal>包围是处于效率考虑，就像在方法参数中使用<classname>const std::string&amp;</classname>而不是用<classname>std::string</classname>一样，这是为了避免不必要的复制。

en: Connecting signal handlers
zh_CN: 连接到信号处理函数

en: <application>gtkmm</application> widget classes have signal accessor methods, such as <methodname>Gtk::Button::signal_clicked()</methodname>, which allow you to connect your signal handler. Thanks to the flexibility of <application>libsigc++</application>, the callback library used by <application>gtkmm</application>, the signal handler can be almost any kind of function, but you will probably want to use a class method. Among <application>GTK</application> C coders, these signal handlers are often named callbacks.
zh_CN: <application>gtkmm</application>的部件类拥有信号访问器方法，例如:<methodname>Gtk::Button::signal_clicked()</methodname>。这些方法允许你将你的信号处理函数与信号相连接。<application>gtkmm</application>所使用的的<application>libsigc++</application>回调库提供了非常强的灵活性，它几乎允许你使用任何函数作为信号的处理程序，不过通常你会希望使用类的成员函数。在<application>GTK</application>的C代码中，这些信号处理程序被称为回调。

en: Here's an example of a signal handler being connected to a signal:
zh_CN: 这是将信号处理函数与信号相连接的示例：

en: There's rather a lot to think about in this (non-functional) code. First let's identify the parties involved:
zh_CN: 在此代码（非功能性）中有很多事情要考虑，首先让我们确定代码的行为：

en: The signal handler is <methodname>on_button_clicked()</methodname>.
zh_CN: 信号处理函数是<methodname>on_button_clicked()</methodname>。

en: We're hooking it up to the <classname>Gtk::Button</classname> object called <varname>button</varname>.
zh_CN: 我们将其连接到一个名为<varname>button</varname>的<classname>Gtk::Button</classname>对象。

en: When the Button emits its <literal>clicked</literal> signal, <methodname>on_button_clicked()</methodname> will be called.
zh_CN: 当<varname>button</varname>发出<literal>clicked</literal>信号时，<methodname>on_button_clicked()</methodname>将被调用。

en: Now let's look at the connection again:
zh_CN: 现在，我们再次看一下连接：

en: Note that we don't pass a pointer to <methodname>on_button_clicked()</methodname> directly to the signal's <methodname>connect()</methodname> method. Instead, we call <function>sigc::ptr_fun()</function>, and pass the result to <methodname>connect()</methodname>.
zh_CN: 请注意，我们不会直接将一个指向<methodname>on_button_clicked()</methodname>的指针传递给信号的<methodname>connect()</methodname>方法。我们将调用<function>sigc::ptr_fun()</function>并将其返回值传递给<methodname>connect()</methodname>。

en: <function>sigc::ptr_fun()</function> generates a <classname>sigc::slot</classname>. A slot is an object which looks and feels like a function, but is actually an object. These are also known as function objects, or functors. <function>sigc::ptr_fun()</function> generates a slot for a standalone function or static method. <function>sigc::mem_fun()</function> generates a slot for a member method of a particular instance.
zh_CN: <function>sigc::ptr_fun()</function>生成一个<classname>sigc::slot</classname>。槽对象看起来很像一个函数，但实际上是一个对象。这类对象也被称为函数对象或是函子。<function>sigc::ptr_fun()</function>为独立函数或静态成员函数生成槽。<function>sigc::mem_fun()</function>为特定实例的成员函数生成槽。

en: Here's a slightly larger example of slots in action:
zh_CN: 这是一个在动作中使用槽的较大示例：

en: The first call to <methodname>connect()</methodname> is just like the one we saw last time; nothing new here.
zh_CN: 第一个<methodname>connect()</methodname>调用与我们之前看到的没有什么区别。

en: The next is more interesting. <function>sigc::mem_fun()</function> is called with two arguments. The first argument is <parameter>some_object</parameter>, which is the object that our new slot will be pointing at. The second argument is a pointer to one of its methods. This particular version of <function>sigc::mem_fun()</function> creates a slot which will, when "called", call the pointed-to method of the specified object, in this case <methodname>some_object.on_button_clicked()</methodname>.
zh_CN: 接下来的一个调用更有趣些。使用两个参数调用<function>sigc::mem_fun()</function>。第一个参数是<parameter>some_object</parameter>，这是我们新的槽将指向的对象。第二个参数是指向其成员函数之一的指针。这个特定版本的<function>sigc::mem_fun()</function>将会创建一个槽，这个槽在被调用的时候将会调用指定对象上函数指针所指向的成员函数，在这个情况下调用的是<methodname>some_object.on_button_clicked()</methodname>。

en: Another thing to note about this example is that we made the call to <methodname>connect()</methodname> twice for the same signal object. This is perfectly fine - when the button is clicked, both signal handlers will be called.
zh_CN: 另一个与此示例有关的注意事项是，我们对同一个信号对象调用了两次<methodname>connect()</methodname>。所以当该按钮被点击时，这两个信号处理函数都将被调用。

en: We just told you that the button's <literal>clicked</literal> signal is expecting to call a method with no arguments. All signals have requirements like this - you can't hook a function with two arguments to a signal expecting none (unless you use an adapter, such as <function>sigc::bind()</function>, of course). Therefore, it's important to know what type of signal handler you'll be expected to connect to a given signal.
zh_CN: 你应该已经注意到了，按钮的<literal>clicked</literal>信号期望调用一个不接受任何参数的函数。事实上所有的信号都有这样的要求。所以你不能将一个接受两个参数的函数与期望所调用函数不接受参数的信号相关联，当然你可以通过使用<function>sigc::bind()</function>之类的适配器在一定程度上绕过这个限制。

en: Writing signal handlers
zh_CN: 编写信号处理函数

en: To find out what type of signal handler you can connect to a signal, you can look it up in the reference documentation or the header file. Here's an example of a signal declaration you might see in the <application>gtkmm</application> headers:
zh_CN: 要找到你可以连接到信号的信号处理函数类型，你可以查看它的参考文档或者是头文件。这是一个你可能在<application>gtkmm</application>头文件中看到的信号声明示例：

en: Other than the signal's name (<literal>focus</literal>), the template arguments are important to note here. The first argument, <type>bool</type>, is the type that the signal handler should return; and the type within parentheses, <type>Gtk::DirectionType</type>, is the type of this signal's first, and only, argument. By looking at the reference documentation, you can see the names of the arguments too.
zh_CN: 除了信号名为<literal>focus</literal>之外，这里的膜拜参数很重要。第一个参数<type>bool</type>，表示信号处理函数的返回值应该是个<type>bool</type>类型。而括号中的<type>Gtk::DirectionType</type>表示信号所期望调用的函数的第一个也是唯一一个参数的类型。通过查看参考文档你还可以看到参数的名称。

en: The same principles apply for signals which have more arguments. Here's one with three (taken from <filename>&lt;gtkmm/textbuffer.h&gt;</filename>):
zh_CN: 对于接受期望调用的函数有更多参数的信号也是一样的阅读规则。以下声明取自<filename>&lt;gtkmm/textbuffer.h&gt;</filename>：

en: It follows the same form. The first type is <type>void</type>, so that should be our signal handler's return type. The following three types are the argument types, in order. Our signal handler's prototype could look like this:
zh_CN: 以一样的阅读规则阅读后可知，该信号所期望调用的函数的返回值类型为<type>void</type>，括号内三种类型为函数的三个参数类型。所以我们的信号处理函数原型可能如下所示：

en: Disconnecting signal handlers
zh_CN: 断开信号处理函数

en: Let's take another look at a Signal's <literal>connect</literal> method:
zh_CN: 让我们再来看看信号的<literal>connect</literal>成员函数：

en: The returned <classname>sigc::connection</classname> can be used to control the connection. By keeping a connection object you can disconnect its associated signal handler using the <methodname>sigc::connection::disconnect()</methodname> method.
zh_CN: 该函数返回的<classname>sigc::connection</classname>对象可以控制连接。通过保存连接对象就可以断开与其相关联的信号处理函数的连接。若你想如此做，只需对对象调用<methodname>sigc::connection::disconnect()</methodname>成员函数即可。

en: Overriding default signal handlers
zh_CN: 覆写默认信号处理函数

en: So far we've told you to perform actions in response to button-presses and the like by handling signals. That's certainly a good way to do things, but it's not the only way.
zh_CN: 到现在为止，你已经学会了通过将自定义的信号处理函数连接到信号来响应按钮按下等动作。这是一种好方法，但不是唯一的方法。

en: Instead of laboriously connecting signal handlers to signals, you can simply make a new class which inherits from a widget - say, a Button - and then override the default signal handler, such as Button::on_clicked(). This can be a lot simpler than hooking up signal handlers for everything.
zh_CN: 你还可以创建一个从部件继承而来的新类，然后覆盖默认的信号处理函数（例如，Button::on_clicked()），这样你就可以省去将信号处理函数连接到信号的步骤。

en: Subclassing isn't always the best way to accomplish things. It is only useful when you want the widget to handle its own signal by itself. If you want some other class to handle the signal then you'll need to connect a separate handler. This is even more true if you want several objects to handle the same signal, or if you want one signal handler to respond to the same signal from different objects.
zh_CN: 子类化并不是银弹。它只在你只希望由部件自身来处理自己的信号时才好用。如果你需要用其他的类来处理信号，你还是需要为此将函数连接到目标信号上。这在你需要用多个对象处理同一个信号或者需要一个信号处理函数处理不同的对象的信号的时候会很不方便。

en: <application>gtkmm</application> classes are designed with overriding in mind; they contain virtual member methods specifically intended to be overridden.
zh_CN: <application>gtkmm</application>类在设计的时候已经考虑到了覆写；它们包含了专门用于被覆写的虚成员函数。

en: Let's look at an example of overriding:
zh_CN: 让我们看一个覆写的例子：

en: Here we define a new class called <classname>OverriddenButton</classname>, which inherits from <classname>Gtk::Button</classname>. The only thing we change is the <methodname>on_clicked()</methodname> method, which is called whenever <classname>Gtk::Button</classname> emits the <literal>clicked</literal> signal. This method prints "Hello World" to <literal>stdout</literal>, and then calls the original, overridden method, to let <classname>Gtk::Button</classname> do what it would have done had we not overridden.
zh_CN: 在这我们定义了一个名为<classname>OverriddenButton</classname>的新类，该类继承自<classname>Gtk::Button</classname>。我们对其唯一的更改是<methodname>on_clicked()</methodname>成员函数，只要<classname>Gtk::Button</classname>发出<literal>clicked</literal>信号该成员函数就会被调用。这个成员函数将字符串"Hello World"打印到<literal>stdout</literal>，然后调用<classname>Gtk::Button</classname>已被覆写本该被调用的成员函数。

en: You don't always need to call the parent's method; there are times when you might not want to. Note that we called the parent method <emphasis>after</emphasis> writing "Hello World", but we could have called it before. In this simple example, it hardly matters much, but there are times when it will. With connected signal handlers, it's not quite so easy to change details like this, and you can do something here which you can't do at all with connected signal handlers: you can call the parent method in the <emphasis>middle</emphasis> of your custom code.
zh_CN: 调用父方法不是必须的，你可以在不想做的时候不调用它。请注意在此我们在做完了想做的事情<emphasis>之后</emphasis>调用了父方法，而你当然可以在此函数的中间或是任何你想调用父方法的位置调用它。这对于通过连接到信号调用的信号处理函数是无法做到的。

en: Binding extra arguments
zh_CN: 绑定额外参数

en: If you use one signal handler to catch the same signal from several widgets, you might like that signal handler to receive some extra information. For instance, you might want to know which button was clicked. You can do this with <function>sigc::bind()</function>. Here's some code from the <link linkend="sec-helloworld2">helloworld2</link> example. <_:programlisting-1/> This says that we want the signal to send an extra <classname>Glib::ustring</classname> argument to the signal handler, and that the value of that argument should be "button 1". Of course we will need to add that extra argument to the declaration of our signal handler: <_:programlisting-2/> Of course, a normal "clicked" signal handler would have no arguments.
zh_CN: 如果你想使用一个信号处理函数从多个部件捕获同一个信号，你可能希望信号处理函数能收到一些额外的信息。例如，你可能想知道那个按钮被点击了。你可以使用<function>sigc::bind()</function>。这是<link linkend="sec-helloworld2">helloworld2</link>示例的部分代码：<_:programlisting-1/> 这表示我们希望信号向信号处理函数发送一个额外的<classname>Glib::ustring</classname>参数，并且该参数的值为"button 1"。当然，我们将会需要向信号处理函数的声明中添加额外的参数:<_:programlisting-2/>。当然，正常的"clicked"信号处理函数是没有参数的。

en: <function>sigc::bind()</function> is not commonly used, but you might find it helpful sometimes. If you are familiar with <application>GTK</application> programming then you have probably noticed that this is similar to the extra <literal>gpointer data</literal> arguments which all GTK callbacks have. This is generally overused in <application>GTK</application> to pass information that should be stored as member data in a derived widget, but widget derivation is very difficult in C. We have far less need of this hack in <application>gtkmm</application>.
zh_CN: <function>sigc::bind()</function>并不常用，不过偶尔会对你有所帮助（译注：很多时候直接使用lambda比调用sigc::bind要好）。如果你对使用<application>GTK</application>编程很熟悉，就会注意到，这和<application>GTK</application>中所有的回调函数都具有一个额外的<literal>gpointer data</literal>参数十分的类似。因为在C语言中要派生一个部件十分的困难，通过让<application>GTK</application>中所有回调函数都具有一个这样的额外参数用于传递本该储存于派生部件成员中的数据可以有效降低代码复杂度。而在<application>gtkmm</application>中派生部件类十分的简单，所以这种强侵入式的写法不再需要了。

en: X Event signals
zh_CN: X事件信号

en: The <classname>Widget</classname> class has some special signals which correspond to the underlying X-Windows events. These are suffixed by <literal>_event</literal>; for instance, <methodname>Widget::signal_button_press_event()</methodname>.
zh_CN: <classname>Widget</classname>有一些对应底层X-Windows事件的特殊信号。它们具有<literal>_event</literal>后缀。例如：<methodname>Widget::signal_button_press_event()</methodname>。

en: You might occasionally find it useful to handle X events when there's something you can't accomplish with normal signals. <classname>Gtk::Button</classname>, for example, does not send mouse-pointer coordinates with its <literal>clicked</literal> signal, but you could handle <literal>button_press_event</literal> if you needed this information. X events are also often used to handle key-presses.
zh_CN: 当有些事情你无法使用常规信号完成时，你可能会发现X事件信号非常有用。例如：<classname>Gtk::Button</classname>的<literal>clicked</literal>信号不会发送鼠标指针的坐标，而<literal>button_press_event</literal>信号会。X事件也用于处理按键。

en: These signals behave slightly differently. The value returned from the signal handler indicates whether it has fully "handled" the event. If the value is <literal>false</literal> then <application>gtkmm</application> will pass the event on to the next signal handler. If the value is <literal>true</literal> then no other signal handlers will need to be called.
zh_CN: 这些信号的行为有所不同。它们的信号处理函数将通过返回值指示有没有完全处理事件。如果返回值为<literal>false</literal>，则<application>gtkmm</application>将会把事件再次发送到下一个信号处理函数。如果返回值为<literal>true</literal>则不再传播信号不再调用其他的信号处理函数。

en: Handling an X event doesn't affect the Widget's other signals. If you handle <literal>button_press_event</literal> for <classname>Gtk::Button</classname>, you'll still be able to get the <literal>clicked</literal> signal. They are emitted at (nearly) the same time.
zh_CN: 处理X事件不会影响部件的其他信号。如果你处理<classname>Gtk::Button</classname>的<literal>button_press_event</literal>信号，你依旧可以得到<literal>clicked</literal>信号。这两个信号将几乎于同一时间被发出。

en: When the mouse is over the button and a mouse button is pressed, <methodname>on_button_press()</methodname> will be called.
zh_CN: 当鼠标悬停在鼠标上方并按下鼠标按钮时，<methodname>on_button_press()</methodname>将被调用。

en: <type>GdkEventButton</type> is a structure containing the event's parameters, such as the coordinates of the mouse pointer at the time the button was pressed. There are several different types of <type>GdkEvent</type> structures for the various events.
zh_CN: <type>GdkEventButton</type>是一个包含事件参数的结构体，其中包含按下按钮时鼠标指针的坐标等一系列信息。对于不同的事件，有不同的<type>GdkEvent</type>结构体类型与之对应。

en: Signal Handler sequence
zh_CN: 信号处理函数序列

en: By default, your signal handlers are called after any previously-connected signal handlers. However, this can be a problem with the X Event signals. For instance, the existing signal handlers, or the default signal handler, might return <literal>true</literal> to stop other signal handlers from being called. To specify that your signal handler should be called before the other signal handlers, so that it will always be called, you can specify <literal>false</literal> for the optional <literal>after</literal> parameter. For instance,
zh_CN: 默认情况下，你的信号处理函数将于所有之前连接到信号的信号处理函数之后被调用。但是这对于X事件信号可能会出问题。例如，现有的信号处理函数或默认信号处理函数如果返回了<literal>true</literal>将会停止事件传播，这时候你的信号处理函数就不会被调用。你可以指定可选参数<literal>after</literal>为<literal>false</literal>，这样你的信号处理函数就总是会被调用。例如：

en: The event is delivered first to the widget the event occurred in. If all signal handlers in that widget return <literal>false</literal> (indicating that the event has not been handled), then the signal will be propagated to the parent widget and emitted there. This continues all the way up to the top-level widget if no one handles the event.
zh_CN: 这个事件将首先被发送到发生事件的部件中。如果该部件的所有信号处理函数都返回<literal>false</literal>。则该信号将被传播到部件的父部件中。如果后续没有人处理事件，信号会一直传播到顶级窗口部件。

en: Exceptions in signal handlers
zh_CN: 信号处理函数中的异常

en: When a program is aborted because of an unhandled C++ exception, it's sometimes possible to use a debugger to find the location where the exception was thrown. This is more difficult than usual if the exception was thrown from a signal handler.
zh_CN: 当程序因未处理C++异常而终止时，有时候可以使用调试器查找抛出异常的位置。但是如果异常是在信号处理函数中抛出的，这将会比平常困难的多。

en: This section describes primarily what you can expect on a Linux system, when you use <ulink url="http://www.gnu.org/software/gdb/">the gdb debugger</ulink>.
zh_CN: 本小节组要介绍使用<ulink url="http://www.gnu.org/software/gdb/">gdb调试器</ulink>在Linux系统上调试异常。

en: First, let's look at a simple example where an exception is thrown from a normal function (no signal handler).
zh_CN: 首先让我们看一个简单的示例，其中的一个普通函数（非信号处理函数）抛出异常：

en: Here is an excerpt from a <application>gdb</application> session. Only the most interesting parts of the output are shown. <_:programlisting-1/> You can see that the exception was thrown from <filename>without_signal.cc</filename>, line 6 (<code>throw "Something";</code>).
zh_CN: 这是<application>gdb</application>会话的摘要。只显示输出中最有趣的部分：<_:programlisting-1/> 你可以看到在<filename>without_signal.cc</filename>的第六行抛出了异常(<code>throw "Something";</code>)。

en: Now let's see what happens when an exception is thrown from a signal handler. Here's the source code.
zh_CN: 现在，让我们看看从信号处理函数中抛出异常会发生什么。这是源代码：

en: And here's an excerpt from a <application>gdb</application> session. <_:programlisting-1/> The exception is caught in <application>glibmm</application>, and the program ends with a call to <function>g_error()</function>. Other exceptions may result in different behaviour, but in any case the exception from a signal handler is caught in <application>glibmm</application> or <application>gtkmm</application>, and <application>gdb</application> can't see where it was thrown.
zh_CN: 这是<application>gdb</application>会话的摘录：<_:programlisting-1/> <application>glibmm</application>将捕获了异常，并调用<function>g_error()</function>结束了程序。其他的异常行为可能不一样，不过所有从信号处理函数中抛出的异常都会被<application>glibmm</application>或<application>gtkmm</application>所捕获，并且<application>gdb</application>将无法看到异常被抛出的具体位置。

en: To see where the exception is thrown, you can use the <application>gdb</application> command <userinput>catch throw</userinput>.
zh_CN: 要查看哪里抛出了异常，你可以使用<application>gdb</application>的<userinput>catch throw</userinput>命令。

en: If there are many caught exceptions before the interesting uncaught one, this method can be tedious. It can be automated with the following <application>gdb</application> commands. <_:programlisting-1/> These commands will print a backtrace from each <code>throw</code> and continue. The backtrace from the last (or possibly the last but one) <code>throw</code> before the program stops, is the interesting one.
zh_CN: 如果在感兴趣的未捕获异常之前有多个捕获异常，这个方法将会非常的枯燥。可以使用以下<application>gdb</application>命令自动化进行这个工作。<_:programlisting-1/> 这些命令将在每次抛出时打印回溯信息并继续。通常最后一个或第一个<code>throw</code>是你所需要的。

en: Creating your own signals
zh_CN: 创建属于你的信号

en: Now that you've seen signals and signal handlers in <application>gtkmm</application>, you might like to use the same technique to allow interaction between your own classes. That's actually very simple by using the <application>libsigc++</application> library directly.
zh_CN: 现在你已经看到了<application>gtkmm</application>中的信号于信号处理函数，你可能希望你自己的类使用相同的技术进行交互。你可以很轻松的使用<application>libsigc++</application>库实现这个需求。

en: This isn't purely a <application>gtkmm</application> or GUI issue. <application>gtkmm</application> uses <application>libsigc++</application> to implement its proxy wrappers for the <application>GTK</application> signal system, but for new, non-GTK signals, you can create pure C++ signals, using the <classname>sigc::signal&lt;&gt;</classname> template.
zh_CN: 这不是单纯的<application>gtkmm</application>或GUI问题。<application>gtkmm</application>使用<application>libsigc++</application>实现对<application>GTK</application>信号系统的代理封装。而对于新的非<application>GTK</application>信号，你可以使用<classname>sigc::signal&lt;&gt;</classname>模版创建属于自己的C++信号。

en: For instance, to create a signal that sends 2 parameters, a <type>bool</type> and an <type>int</type>, just declare a <classname>sigc::signal</classname>, like so:
zh_CN: 例如，要创建一个发送参数类型分别为<type>bool</type>和<type>int</type>的信号，只需要按如下所示声明一个<classname>sigc::signal</classname>即可：

en: You could just declare that signal as a public member variable, but some people find that distasteful and prefer to make it available via an accessor method, like so:
zh_CN: 你可以简单的将信号声明为公有成员变量，但是有些人讨厌这种声明，他们更喜欢如下所示的访问器方法：

en: You can then connect to the signal using the same syntax used when connecting to <application>gtkmm</application> signals. For instance,
zh_CN: 然后你可以使用与连接<application>gtkmm</application>信号一样的语法连接到这个信号。例如：

en: This is a full working example that defines and uses custom signals.
zh_CN: 这是一个完整的定义了并使用了自定义信号的示例。

en: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/signals/custom/">Source Code</ulink>
zh_CN: <ulink url="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/signals/custom/">源代码</ulink>

en: Comparison with other signalling systems
zh_CN: 与其他信号系统的比较

en: (An aside: <application>GTK</application> calls this scheme "signalling"; the sharp-eyed reader with GUI toolkit experience will note that this same design is often seen under the name of "broadcaster-listener" (e.g., in Metrowerks' PowerPlant framework for the Macintosh). It works in much the same way: one sets up <literal>broadcasters</literal>, and then connects <literal>listeners</literal> to them; the broadcaster keeps a list of the objects listening to it, and when someone gives the broadcaster a message, it calls all of its objects in its list with the message. In <application>gtkmm</application>, signal objects play the role of broadcasters, and slots play the role of listeners - sort of. More on this later.)
zh_CN: <application>GTK</application>将自己的信号系统方案称为"信号传递"；有使用其他GUI工具包经验的读者可能会注意到，这种设计经常会被称作"广播者-监听者"。它的工作方式大致为：先设置<literal>广播者(broadcasters)</literal>，然后将<literal>监听者(listeners)</literal>与它连接。广播者会保留一个监听者对象列表，当有某人向广播者发送消息时，它将向列表中所有对象发送消息。在<application>gtkmm</application>中，信号对象扮演广播者的角色，而槽扮演监听者的角色。

en: <application>gtkmm</application> signal handlers are strongly-typed, whereas <application>GTK</application> C code allows you to connect a callback with the wrong number and type of arguments, leading to a segfault at runtime. And, unlike <application>Qt</application>, <application>gtkmm</application> achieves this without modifying the C++ language.
zh_CN: <application>gtkmm</application>的信号处理函数是强类型的，而<application>gtk</application>的C代码啊运行你连接到一个使用错误参数数量和类型的回调函数，这会导致运行时出现段错误。并且和<application>Qt</application>不同，<application>gtkmm</application>不需要对C++语言进行修改即可达到此目的。

en: Re. Overriding signal handlers: You can do this in the straight-C world of GTK too; that's what GTK's object system is for. But in GTK, you have to go through some complicated procedures to get object-oriented features like inheritance and overloading. In C++, it's simple, since those features are supported in the language itself; you can let the compiler do the dirty work.
zh_CN: 虽然你也能在C语言中覆写信号处理函数（这是GTK使用对象系统的目的），但是由于语言对于高级特性的支持特别弱，你需要编写一系列复杂的代码才能做到继承和重载。而在C++中，因为语言本身就支持这些特性，所以你可以让编译器代为完成肮脏的工作。

en: This is one of the places where the beauty of C++ really comes out. One wouldn't think of subclassing a GTK widget simply to override its action method; it's just too much trouble. In GTK, you almost always use signals to get things done, unless you're writing a new widget. But because overriding methods is so easy in C++, it's entirely practical - and sensible - to subclass a button for that purpose.
zh_CN: 这是真正体现C++魅力的地方之一。没有人会只为了覆写GTK部件的成员函数就将其子类化，这过于麻烦。除非是为了编写新的部件否则基本上都是利用信号完成任务。而在C++中覆写成员函数非常简单，因此为了修改部件的某个行为而将其子类化是完全可行且明智的。

en: <application>gtkmm</application> and Win32
zh_CN: <application>gtkmm</application>与Win32

en: One of the major advantages of <application>gtkmm</application> is that it is crossplatform. <application>gtkmm</application> programs written on other platforms such as GNU/Linux can generally be transferred to Windows (and vice versa) with few modifications to the source.
zh_CN: <application>gtkmm</application>的主要优点之一是它是跨平台的。在其他平台编写的<application>gtkmm</application>程序只需要修改很少一部分的源代码就可以从GNU/Linux移植到Windows，当然反之亦然。

en: <application>gtkmm</application> currently works with the <ulink url="http://mingw.org/">MinGW/GCC compiler</ulink> with a compiler version that supports C++17, such as gcc 7 or 8. It also works with Microsoft Visual C++ 2017 15.7.x or later (including the freely available express/community editions) on the Windows platform. There is an <ulink url="ftp://ftp.gnome.org/pub/GNOME/binaries/win32/gtkmm">installer</ulink> available for <application>gtkmm</application> on Microsoft Windows, but as of this writing (October 2020) it has not been updated for a long time. Please be aware that although normally it is fine to mix builds done with Visual Studio 2017 and 2019, please do not do so when building <application>gtkmm</application> with its -mm dependencies.
zh_CN: <application>gtkmm</application>当前可以与支持C++17的<ulink url="http://mingw.org/">MinGW/GCC编译器</ulink>一起使用。也可以与VS 2017 15.7.X或更高版本一起使用（免费提供的Express/Community版本也可以）。在Windows平台上有一个<application>gtkmm</application>的<ulink url="ftp://ftp.gnome.org/pub/GNOME/binaries/win32/gtkmm">安装器</ulink>，不过到撰写本章时（2020年10月），这个安装器已经很久没有人维护了（译注：朋友，MSYS2了解一下）。值得注意的是，尽管通常情况下可以混合使用VS2017和2019完成构建，但是在构建带有-mm依赖的<application>gtkmm</application>时千万不要如此做。

en: Refer to the <ulink url="https://gitlab.gnome.org/GNOME/gtkmm/tree/master/README.win32">README.win32</ulink>, as well as the <ulink url="https://gitlab.gnome.org/GNOME/gtkmm/tree/master/MSVC_NMake/README">README</ulink> files in the <application>gtkmm</application>, pangomm and glibmm for instructions on how to build <application>gtkmm</application> on Windows.
zh_CN: 请参阅<ulink url="https://gitlab.gnome.org/GNOME/gtkmm/tree/master/README.win32">README.win32</ulink>以及此<ulink url="https://gitlab.gnome.org/GNOME/gtkmm/tree/master/MSVC_NMake/README">自述文件</ulink>中关于如何在WIndwos上构建<application>gtkmm</application>的说明。

en: Working with gtkmm's Source Code
zh_CN: 使用gtkmm源代码

en: If you are interested in helping out with the development of <application>gtkmm</application>, or fixing a bug in <application>gtkmm</application>, you'll probably need to build the development version of <application>gtkmm</application>. However, you should not install a development version over your stable version. Instead, you should install it alongside your existing <application>gtkmm</application> installation, in a separate path.
zh_CN: 如果你有兴趣协助开发<application>gtkmm</application>或修复<application>gtkmm</application>中的bug，你可能需要构建<application>gtkmm</application>的开发版。但是你不应该将开发版本覆盖稳定版。你应该选择已存在<application>gtkmm</application>版本的目录外的路径安装开发版。

en: The easiest way to do this is using <ulink url="https://wiki.gnome.org/Projects/Jhbuild">jhbuild</ulink>. <application>jhbuild</application> is a program that makes building GNOME software much easier by calculating dependencies and building things in the correct order. This section will give a brief explanation of how to set up <application>jhbuild</application> to build and install <application>gtkmm</application> from the source repository (git). For up-to-date information on <application>jhbuild</application>, please refer to the <ulink url="http://developer.gnome.org/jhbuild/unstable/">jhbuild manual</ulink>.
zh_CN: 构建gtkmm的最简单方法是使用<ulink url="https://wiki.gnome.org/Projects/Jhbuild">jhbuild</ulink>编译。<application>jhbuild</application>是一个可以使构建Gnome软件更容易的程序，它可以通过计算依赖关系做到按正确的顺序进行构建。本小节将简要说明如何设置<application>jhbuild</application>从<application>gtkmm</application>的源代码仓库构建并安装开发版的<application>gtkmm</application>。想了解<application>jhbuild</application>的最新信息，请参考<ulink url="http://developer.gnome.org/jhbuild/unstable/">jhbuild手册</ulink>。

en: Note that to build <application>gtkmm</application> from git, you'll often need to build many of its dependencies from git as well. <application>jhbuild</application> makes this easier than it would normally be, but it will take quite a while to build and install them all. You will probably encounter build problems, though these will usually be corrected quickly if you report them.
zh_CN: 请注意，要从git构建<application>gtkmm</application>，通常你还需要从git构建许多的依赖项。<application>jhbuild</application>使此操作比平常更容易，但是构建和安装这些依赖依旧需要相当长的时间。在这过程中你可能会遇到构建问题，因为master分支并不总是能构建成功的，当然构建问题通常很快就会被修复。

en: <application>gnome-build-meta</application> is an alternative to <application>jhbuild</application>. It is described at the <ulink url="https://wiki.gnome.org/Newcomers/BuildSystemComponent">Building system components</ulink> wiki page, but here we concentrate on <application>jhbuild</application>.
zh_CN: <application>gnome-build-meta</application>是<application>jhbuild</application>的替代方案。<ulink url="https://wiki.gnome.org/Newcomers/BuildSystemComponent">构建系统组件</ulink>维基页面对其进行了详细的介绍，在这里我们只介绍<application>jhbuild</application>。

en: Setting up jhbuild
zh_CN: 设置jhbuild

en: To set up <application>jhbuild</application>, follow the basic installation instructions from the <ulink url="http://developer.gnome.org/jhbuild/unstable/">jhbuild manual</ulink>. After you have installed <application>jhbuild</application>, you should copy the sample <application>jhbuild</application> configuration file into your home directory by executing the following command from the <application>jhbuild</application> directory: <_:screen-1/>
zh_CN: 要设置<application>jhbuild</application>，请遵循<ulink url="http://developer.gnome.org/jhbuild/unstable/">jhbuild手册</ulink>中的基本安装说明。安装<application>jhbuild</application>后，应通过在<application>jhbuild</application>目录执行以下命令将示例<application>jhbuild</application>配置文件复制到你的主目录中：<_:screen-1/>

en: The <application>gtkmm</application> module is defined in the <filename>gnome-suites-core-deps-latest.modules</filename> moduleset. So edit your <filename>jhbuildrc</filename> file and set your moduleset setting like so:
zh_CN: <application>gtkmm</application>模块在文件<filename>gnome-suites-core-deps-latest.modules</filename>中的模块组(moduleset)定义。因此你需要按以下方式编辑你的<filename>jhbuildrc</filename>文件并设置你的模块组：

en: After setting the correct moduleset, you need to tell <application>jhbuild</application> which module or modules to build. To build <application>gtkmm</application> and all of its dependencies, set <varname>modules</varname> like so:
zh_CN: 正确设置模块组之后，你需要告诉<application>jhbuild</application>哪些模块需要构建。想要构建<application>gtkmm</application>以及所有相关的依赖项，请按如下所示设置<varname>modules</varname>：

en: You can build several modules by setting the <varname>modules</varname> variable to a meta-package, e.g. <literal>meta-gnome-core</literal>, or listing more than one module name. The <varname>modules</varname> variable specifies which modules will be built when you don't explicitly specify anything on the command line. You can always build a different moduleset later by specifying it on the commandline (e.g. <command>jhbuild build gtkmm</command>).
zh_CN: 你可以通过设置<varname>modules</varname>为元包(meta-package)来构建多个模块。当你未在命令行上指定任何内容的时候，<varname>modules</varname>变量将指定构建哪些模块。你始终可以用命令行指定其他模块组来构建其他模块组（例如：<command>jhbuild build gtkmm</command>）。

en: Setting a prefix
zh_CN: 设置前缀

en: By default, <application>jhbuild</application>'s configuration is configured to install all software built with <application>jhbuild</application> under the <filename>~/jhbuild/install</filename> prefix. You can choose a different prefix, but it is recommended that you keep this prefix different from other software that you've installed (don't set it to <filename>/usr</filename>!) If you've followed the jhbuild instructions then this prefix belongs to your user, so you don't need to run jhbuild as <literal>root</literal>.
zh_CN: 在默认情况下，<application>jhbuild</application>被配置为在<filename>~/jhbuild/install</filename>前缀安装所有由<application>jhbuild</application>构建的软件。你可以选择其他的前缀，但建议你选择的新前缀与旧前缀保持不同，且不将前缀设置为<filename>/usr</filename>。如果你遵循jhbuild的说明进行操作，该前缀属于你的用户，你将无需以<literal>root</literal>用户权限运行jhbuild。

en: When you downloaded <application>jhbuild</application> from the git repository, you got a number of <filename>.modules</filename> files, specifying dependencies between modules. By default <application>jhbuild</application> does not use the downloaded versions of these files, but reads the latest versions in the git repository. This is usually what you want. If you don't want it, use the <varname>use_local_modulesets</varname> variable in <filename>.jhbuildrc</filename>.
zh_CN: 当你从git仓库下载<application>jhbuild</application>时，你会得到许多的<filename>.modules</filename>文件，这些文件指定了模块之间的依赖关系。在默认情况下<application>jhbuild</application>不使用这些文件的下载版本，而是从git仓库中读取最新的版本。这通常是你想要的行为，如果你不想要如此做，你可以在<filename>.jhbuildrc</filename>文件中定义<varname>use_local_modulesets</varname>以修改此行为。

en: Installing and Using the git version of <application>gtkmm</application>
zh_CN: 安装和使用<application>gtkmm</application>的git版本

en: Once you've configured <application>jhbuild</application> as described above, building <application>gtkmm</application> should be relatively straightforward. The first time you run <application>jhbuild</application>, you should run the following sequence of commands to ensure that <application>jhbuild</application> has the required tools and verify that it is set up correctly: <_:screen-1/>
zh_CN: 如上所述，配置好<application>jhbuild</application>后，构建<application>gtkmm</application>会非常简单。首次运行<application>jhbuild</application>时，你应运行以下命令序列，以确保<application>jhbuild</application>拥有所有所需的工具以及验证设置是否正确：<_:screen-1/>

en: Installing <application>gtkmm</application> with <application>jhbuild</application>
zh_CN: 用<application>jhbuild</application>安装<application>gtkmm</application>

en: If everything worked correctly, you should be able to build <application>gtkmm</application> and all of its dependencies from git by executing <command>jhbuild build</command> (or, if you didn't specify <application>gtkmm</application> in the <varname>modules</varname> variable, with the command <command>jhbuild build gtkmm</command>).
zh_CN: 如果一切正常，你应该已经可以通过执行<command>jhbuild build</command>（如果你没有在<varname>modules</varname>变量中指定<application>gtkmm</application>，那也可以使用命令<command>jhbuild build gtkmm</command>来进行构建）来从git构建<application>gtkmm</application>以及所有有关的依赖项。

en: This command will build and install a series of modules and will probably take quite a long time the first time through. After the first time, however, it should go quite a bit faster since it only needs to rebuild files that changed since the last build. Alternatively, after you've built and installed <application>gtkmm</application> the first time, you can rebuild <application>gtkmm</application> by itself (without rebuilding all of its dependencies) with the command <command>jhbuild buildone gtkmm</command>.
zh_CN: 此命令将构建并安装一系列模块，第一次运行可能需要很长的时间。但是之后运行就会快很多，因为之后他只会重新编译自上次构建依赖变更过的文件。在第一次构建并安装<application>gtkmm</application>后你可以使用命令<command>jhbuild buildone gtkmm</command>重新构建<application>gtkmm</application>（不需要重新构建相关依赖）。

en: Using the git version of <application>gtkmm</application>
zh_CN: 使用git版本的<application>gtkmm</application>

en: After you've installed the git version of <application>gtkmm</application>, you're ready to start using and experimenting with it. In order to use the new version of <application>gtkmm</application> you've just installed, you need to set some environment variables so that your <filename>configure</filename> or <filename>meson.build</filename> script knows where to find the new libraries. Fortunately, <application>jhbuild</application> offers an easy solution to this problem. Executing the command <command>jhbuild shell</command> will start a new shell with all of the correct environment variables set. Now if you re-configure and build your project just as you usually do, it should link against the newly installed libraries. To return to your previous environment, simply exit the <application>jhbuild</application> shell.
zh_CN: 安装git版本的<application>gtkmm</application>后，你就可以开始使用并进行试验了。为了使用刚安装的新版本<application>gtkmm</application>，你需要设置一些环境变量以便你的<filename>configure</filename>或<filename>meson.build</filename>脚本可以找到新的库。<application>jhbuild</application>为此提供了一个简单的解决方案。执行命令<command>jhbuild shell</command>将启动一个设置好了所有环境变量的shell。现在如果你和往常一样重新配置并构建你的项目，它应该链接到新的库。要返回之前的环境你只需要<application>jhbuild</application> shell即可。

en: Once you've built your software, you'll need to run your program within the jhbuild environment as well. To do this, you can again use the <command>jhbuild shell</command> command to start a new shell with the <application>jhbuild</application> environment set up. Alternatively, you can execute a one-off command in the <application>jhbuild</application> environment using the following command: <command>jhbuild run command-name</command>. In this case, the command will be run with the correct environment variables set, but will return to your previous environment after the program exits.
zh_CN: 构建完你的软件后，你还需要在jhbuild环境中运行你的程序。为此，你可以再次使用<command>jhbuild shell</command>命令在设置了<application>jhbuild</application>环境的情况下启动新的shell。或者你可以用以下命令在<application>jhbuild</application>环境下执行单次命令：<command>jhbuild run command-name</command>。在这种情况下，命令将在设置了正确的环境变量的环境中运行，命令退出后，环境将恢复到之前的状态。

en: Wrapping C Libraries with gmmproc
zh_CN: 使用gmmproc封装C库

en: <application>gtkmm</application> uses the <command>gmmproc</command> tool to generate most of its source code, using .defs files that define the APIs of <classname>GObject</classname>-based libraries. So it's quite easy to create additional gtkmm-style wrappers of other glib/GObject-based libraries.
zh_CN: <application>gtkmm</application>的大部分源代码是使用<command>gmmproc</command>工具生成的，它们使用.defs文件定义基于<classname>GObject</classname>的库的API。因此，可以很容易为其他基于glib/Gobject的库创建类似于gtkmm风格的封装。

en: This involves a variety of tools, some of them crufty, but at least they work, and has been used successfully by several projects.
zh_CN: 这涉及到很多工具，其中有一些很笨重，不过还算能用，并且已经被多个项目使用。

en: The build structure
zh_CN: 构建结构

en: Generation of the source code for a gtkmm-style wrapper API requires use of tools such as <command>gmmproc</command> and <filename>generate_wrap_init.pl</filename>, which are included in <application>glibmm</application>. In theory you could write your own build files to use these appropriately, but a much better option is to make use of the build infrastructure provided by the <application>mm-common</application> module. To get started, it helps a lot to pick an existing binding module as an example to look at.
zh_CN: 要生成gtkmm风格的API封装源代码需要使用包含在<application>glibmm</application>的工具，例如<command>gmmproc</command>和<filename>generate_wrap_init.pl</filename>。理论上来说你可以自己编写构建文本以更好的使用它们，不过更好的选择是利用<application>mm-common</application>模块提供的构建基础设施。选择一个已经存在绑定的模块作为示例对于开始使用gmmproc很有帮助。

en: For instance, let's pretend that we are wrapping a C library called libsomething. It provides a <classname>GObject</classname>-based API with types named, for instance, <classname>SomeWidget</classname> and <classname>SomeStuff</classname>.
zh_CN: 假设，我们封装了一个名为libsomething的C库。它提供了基于<classname>GObject</classname> API的具名类型，例如类型名为：<classname>SomeWidget</classname>和<classname>SomeStuff</classname>。

en: Copying the skeleton project
zh_CN: 复制skeleton项目

en: Typically our wrapper library would be called libsomethingmm. We can start by copying the <ulink url="https://gitlab.gnome.org/GNOME/mm-common/tree/master/skeletonmm"> skeleton source tree</ulink> from the <application>mm-common</application> module. Starting with <application>mm-common</application> 1.0.0 this skeleton application is built with the <ulink url="https://mesonbuild.com/">Meson build system</ulink>.
zh_CN: 我们封装的库名为libsomethingmm。我们可以从在<application>mm-common</application>模块中复制<ulink url="https://gitlab.gnome.org/GNOME/mm-common/tree/master/skeletonmm">skeleton源代码树</ulink>开始。自<application>mm-common</application> 1.0.0开始skeleton应用程序使用<ulink url="https://mesonbuild.com/">Meson构建系统</ulink>进行构建。

en: <filename>libsomethingmm</filename>: The top-level directory.
zh_CN: <filename>libsomethingmm</filename>：顶级目录。

en: <filename>libsomething</filename>: Contains the main include file and the pkg-config .pc file.
zh_CN: <filename>libsomething</filename>：包含主要的被包含文件(被#include的文件)和由<application>pkg-config</application>所需的.pc文件。

en: <filename>src</filename>: Contains .hg and .ccg source files.
zh_CN: <filename>src</filename>：包含.hg和.ccg源文件。

en: <filename>libsomethingmm</filename>: Contains hand-written .h and .cc files.
zh_CN: <filename>libsomethingmm</filename>：包含手写的.h和.cc文件。

en: This provides a directory structure for the source .hg and .ccg files and the hand-written .h and .cc files, with <filename>meson.build</filename> files that can specify the various files in use, in terms of Meson variables. The directory structure usually looks like this, after we have renamed the directories appropriately: <_:itemizedlist-1/>
zh_CN: 这为源.hg和.ccg文件、手写的.h和.cc文件提供了目录结构，<filename>meson.build</filename>文件可以通过各种变量指定Meson使用哪些文件进行编译。适当的重命名目录后，目录结构将如下所示：<_:itemizedlist-1/>

en: As well as renaming the directories, we should rename some of the source files. For instance: <_:programlisting-1/> A number of the skeleton files must still be filled in with project-specific content later.
zh_CN: 除了重命名目录外，我们还应该重命名一些源文件。例如：<_:programlisting-1/>然后，还有些skeleton文件需要在特定项目内容完成后填写。

en: Note that files ending in <filename>.in</filename> will be used to generate files with the same name but without the <filename>.in</filename> suffix, by replacing some variables with actual values during the configure stage.
zh_CN: 请注意，在配置阶段中某些变量将会替换为实际值，这将会生成与<filename>.in</filename>相同名称但不带<filename>.in</filename>后缀的文件。

en: Generated files are saved in the build tree, which is separated from the source tree when <command>meson</command> and <command>ninja</command> are used.
zh_CN: 生成的文件被保存在构建树中，当使用<command>meson</command>和<command>ninja</command>时构建树会与源树分离。

en: Modifying build files
zh_CN: 修改构建文件

en: Now we edit the files to adapt them to our needs. You might prefer to use a multiple-file search-replace utility for this, such as <command>regexxer</command>. Note that nearly all of the files provided with the skeleton source tree contain placeholder text. Thus, the substitutions should be performed globally, and not be limited to the Meson files.
zh_CN: 现在我们修改构建文件以适应我们的需求。在这个时候你可能喜欢使用类似于<command>regexxer</command>这样的多文件搜索替换工具。请注意，skeleton源代码树提供的所有文件几乎都包含了占位符。因此，应该进行全局替换而不是仅对Meson文件替换。

en: All mentions of <varname>skeleton</varname> should be replaced by the correct name of the C library you are wrapping, such as "something" or "libsomething". In the same manner, all instances of <varname>SKELETON</varname> should be replaced by "SOMETHING" or "LIBSOMETHING", and all occurrences of <varname>Skeleton</varname> changed to "Something".
zh_CN: 所有提到<varname>skeleton</varname>的地方都应该替换成你想要封装的C库的名称，例如替换成"something"或"libsomething"。同样的，所有的<varname>SKELETON</varname>都应该被替换成"SOMETHING"或"LIBSOMETHING"，以及所有的<varname>Skeleton</varname>都应该被替换为"Something"。

en: Likewise, replace all instances of <varname>Joe Hacker</varname> by the name of the intended copyright holder, which is probably you. Do the same for the <varname>joe@example.com</varname> email address.
zh_CN: 同样的，将所有的<varname>Joe Hacker</varname>替换为预期的版权所有者的名称，也就是你的名称。然后对<varname>joe@example.com</varname>邮件地址进行同样的操作。

en: meson.build in the top-level directory
zh_CN: 顶级目录中的meson.build

en: It is common for binding modules to track the version number of the library they are wrapping. So, for instance, if the C library is at version 1.23.4, then the initial version of the binding module would be 1.23.0. However, avoid starting with an even minor version number as that usually indicates a stable release.
zh_CN: 使绑定模块的版本跟踪被封装的库的版本很常见。例如，C库版本是1.23.4，则绑定模块的初始版本为1.23.0。但是请尽量避免以偶数次要版本开始，因为这通常意味着该版本是稳定版本。

en: In the <function>project()</function> function, change the license and the C++ version, if necessary.
zh_CN: 如果有必要，请在<function>project()</function>函数中修改许可证和C++版本。

en: You probably need to add more required modules than <application>glibmm</application> and <application>skeleton</application> (<application>libsomething</application>).
zh_CN: 你可能需要添加除<application>glibmm</application>和<application>skeleton(libsomething)</application>以外的必需模块。

en: Other meson.build files
zh_CN: 其他meson.build文件

en: <filename>skeleton/meson.build</filename>: Perhaps not much to change here more than the global name substitutions.
zh_CN: <filename>skeleton/meson.build</filename>：在这除了全局替换以外基本上不需要做什么。

en: If we have more .defs and docs.xml files, we add them here.
zh_CN: 在这添加额外的.defs和docs.xml文件

en: We must mention all of our <filename>.hg</filename> and <filename>.ccg</filename> files here.
zh_CN: 必须在这里提及所有的<filename>.hg</filename>和<filename>.ccg</filename>。

en: Any additional hand-written <filename>.h</filename> and <filename>.cc</filename> source files go here.
zh_CN: 所有手写的<filename>.h</filename>和<filename>.cc</filename>源文件都需要写在这。

en: Next we must adapt the other <filename>meson.build</filename> files: <_:itemizedlist-1/>
zh_CN: 接下来我们必须对其他的<filename>meson.build</filename>文件进行修改：<_:itemizedlist-1/>

en: Creating .hg and .ccg files
zh_CN: 创建.hg个.ccg文件

en: We should now create our first <filename>.hg</filename> and <filename>.ccg</filename> files, to wrap one of the objects in the C library. One pair of example source files already exists: <filename>skeleton.ccg</filename> and <filename>skeleton.hg</filename>. Create copies of these files as necessary.
zh_CN: 现在我们应该创建第一个<filename>.hg</filename>和<filename>.ccg</filename>，用以对一个C库中的对象进行封装。存在一对可供参考的示例源文件：<filename>skeleton.ccg</filename>和<filename>skeleton.hg</filename>。请根据需要创建这些文件的副本。

en: In the <link linkend="sec-wrapping-hg-files">.hg and .ccg files</link> section you can learn about the syntax used in these files.
zh_CN: 在<link linkend="sec-wrapping-hg-files">.hg和.ccg文件</link>小节你可以学到这些文件使用的语法。

en: Generating the .defs files.
zh_CN: 生成.defs文件

en: objects (GObjects, widgets, interfaces, boxed-types and plain structs)
zh_CN: 对象(GObjects、部件、接口、装箱类型、普通结构体)

en: functions
zh_CN: 函数

en: enums
zh_CN: 枚举

en: signals
zh_CN: 信号

en: properties
zh_CN: 属性

en: vfuncs
zh_CN: 虚函数(vfuncs)

en: The <filename>.defs</filename> files are text files, in a lisp format, that describe the API of a C library, including its <_:itemizedlist-1/>
zh_CN: <filename>.defs</filename>是一种使用lisp格式的文本文件，它描述了C库的API，其中包括了以下内容：<_:itemizedlist-1/>

en: Includes the other files.
zh_CN: 包含其他文件。

en: Objects and functions.
zh_CN: 对象和函数。

en: Enumerations.
zh_CN: 枚举。

en: Signals and properties.
zh_CN: 信号和属性。

en: vfuncs (function pointer member fields in structs), written by hand.
zh_CN: 虚函数(结构体中的函数指针字段)，手动编写。

en: At the moment, we have separate tools for generating different parts of these <filename>.defs</filename>, so we split them up into separate files. For instance, in the <filename>gtk/src</filename> directory of the <application>gtkmm</application> sources, you will find these files: <_:variablelist-1/>
zh_CN: 目前我们有一些单独的工具用于生成<filename>.defs</filename>文件的一部分，因此我们将它们拆分为单独的文件，例如在gtkmm源的<filename>gtk/src</filename>目录中你将看到以下文件：<_:variablelist-1/>

en: The <filename>skeletonmm/tools/generate_defs_and_docs.sh</filename> script generates all <filename>.defs</filename> files and the <filename>*_docs.xml</filename> file, described in the <link linkend="sec-wrapping-documentation">Documentation</link> section.
zh_CN: <filename>skeletonmm/tools/generate_defs_and_docs.sh</filename>将生成所有的这些<filename>.defs</filename>以及<filename>*_docs.xml</filename>文件，如该小节的<link linkend="sec-wrapping-documentation">文档</link>所述。

en: Generating the methods .defs
zh_CN: 生成_methods.defs文件

en: This <filename>.defs</filename> file describes objects and their functions. It is generated by the <command>h2def.py</command> script which you can find in glibmm's <filename>tools/defs_gen</filename> directory. For instance,
zh_CN: 这个<filename>.defs</filename>文件描述了对象及其函数。它是由<command>h2def.py</command>脚本生成的，你可以在glibmm的<filename>tools/defs_gen</filename>文件夹中找到该脚本。例如：

en: Generating the enums .defs
zh_CN: 生成_enums.defs文件

en: This <filename>.defs</filename> file describes enum types and their possible values. It is generated by the <filename>enum.pl</filename> script which you can find in glibmm's <filename>tools</filename> directory. For instance,
zh_CN: 这个<filename>.defs</filename>文件描述了枚举类型及其可能的值。它是由<filename>enum.pl</filename>脚本生成的，你可以在glibmm的<filename>tools</filename>文件夹中找到该脚本。例如：

en: Generating the signals and properties .defs
zh_CN: 生成_signals.defs文件

en: This <filename>.defs</filename> file describes signals and properties. It is generated by the special <filename>generate_extra_defs</filename> utility that is in every wrapping project, such as <filename>gtkmm/tools/extra_defs_gen/</filename>. For instance
zh_CN: 这个<filename>.defs</filename>文件描述了信号和属性。它是由封装项目自有的<filename>generate_extra_defs</filename>实用程序生成的，你可以在类似于<filename>gtkmm/tools/extra_defs_gen/</filename>的目录下找到它。例如：

en: You must edit the source code of your own <filename>generate_extra_defs</filename> tool in order to generate the <filename>.defs</filename> for the GObject C types that you wish to wrap. In the skeleton source tree, the source file is named <filename>tools/extra_defs_gen/generate_defs_skeleton.cc</filename>. If not done so already, the file should be renamed, with the basename of your new binding substituted for the <varname>skeleton</varname> placeholder. The <filename>tools/extra_defs_gen/meson.build</filename> file should also mention the new source filename.
zh_CN: 你必须编辑自己的<filename>generate_extra_defs</filename>工具的源代码才能为需要封装的GObject C类型生成<filename>.defs</filename>文件。在skeleton源代码树中，源文件名为<filename>tools/extra_defs_gen/generate_defs_skeleton.cc</filename>。你需要将文件重命名为正确的文件名（按前一小节所述），然后在<filename>tools/extra_defs_gen/meson.build</filename>文件中提到新的源文件名。

en: Then edit the <filename>.cc</filename> file to specify the correct types. For instance, your <function>main()</function> function might look like this:
zh_CN: 然后编辑<filename>.cc</filename>以指定正确的类型。例如，你的<function>main()</function>函数可能如下所示：

en: Writing the vfuncs .defs
zh_CN: 编写_vfunc.defs文件

en: This <filename>.defs</filename> file describes virtual functions (vfuncs). It must be written by hand. There is the skeleton file <filename>skeleton/src/skeleton_vfunc.defs</filename> to start from. You can also look at <application>gtkmm</application>'s <filename>gtk/src/gtk_vfuncs.defs</filename> file.
zh_CN: <filename>.defs</filename>文件描述了虚函数（vfuncs）。它必须手写。你可以从<filename>skeleton/src/skeleton_vfunc.defs</filename>文件开始进行修改。你也可以从<application>gtkmm</application>的<filename>gtk/src/gtk_vfuncs.defs</filename>文件开始。

en: The .hg and .ccg files
zh_CN: .hg和.ccg文件

en: The .hg and .ccg source files are very much like .h and .cc C++ source files, but they contain extra macros, such as <function>_CLASS_GOBJECT()</function> and <function>_WRAP_METHOD()</function>, from which <command>gmmproc</command> generates appropriate C++ source code, usually at the same position in the header. Any additional C++ source code will be copied verbatim into the corresponding .h or .cc file.
zh_CN: .hg和.ccg源文件与C++的.h和.cc源文件非常相似，但是它们包含额外的宏，例如<function>_CLASS_GOBJECT()</function>和<function>_WRAP_METHOD()</function>，<command>gmmproc</command>会使用这些宏在头文件中的相同位置生成合适的C++源代码。而所有其他的C++源代码会按原样复制到相应的.h或.cc文件中。

en: A .hg file will typically include some headers and then declare a class, using some macros to add API or behaviour to this class. For instance, <application>gtkmm</application>'s <filename>button.hg</filename> looks roughly like this:
zh_CN: .hg文件通常包含了一些头文件和声明一个类，并使用一些宏向类中添加API或行为。例如，<application>gtkmm</application>的<filename>button.hg</filename>文件看起来大概这样：

en: Specifies the destination directory for generated sources, and the name of the main .defs file that <command>gmmproc</command> should parse.
zh_CN: 指定所生成源代码的目标目录，以及<command>gmmproc</command>应该解析的主要.defs文件的名称。

en: Tells <command>gmmproc</command> to include a header in the generated <filename>private/button_p.h</filename> file.
zh_CN: 告诉<command>gmmproc</command>在生成的文件中包含<filename>private/button_p.h</filename>头文件。

en: Tells <command>gmmproc</command> to add some typedefs, constructors, and standard methods to this class, as appropriate when wrapping a widget.
zh_CN: 告诉<command>gmmproc</command>在封装部件类时在类中添加一些类型定义(typedef)、构造函数、标准方法。

en: Tells <command>gmmproc</command> to add initialization code for the interface.
zh_CN: 告诉<command>gmmproc</command>为接口添加初始化代码。

en: Adds a default constructor.
zh_CN: 添加默认构造函数。

en: <function>_WRAP_METHOD()</function>, <function>_WRAP_SIGNAL()</function>, and <function>_WRAP_PROPERTY()</function>
zh_CN: <function>_WRAP_METHOD()</function>、<function>_WRAP_SIGNAL()</function>和<function>_WRAP_PROPERTY()</function>

en: Add methods to wrap parts of the C API.
zh_CN: 添加用于封装C API的一部分的方法。

en: The macros in this example do the following: <_:variablelist-1/>
zh_CN: 本示例中的宏执行下述操作：<_:variablelist-1/>

en: The .h and .cc files will be generated from the .hg and .ccg files by processing them with <command>gmmproc</command> like so, though this happens automatically when using the above build structure:
zh_CN: 通过这样使用<command>gmmproc</command>处理.hg和.ccg文件，可以从.hg和.ccg文件生成.h和.cc文件，尽管这在使用上述的构建结构时会自动进行：

en: Notice that we provided <command>gmmproc</command> with the path to the .m4 convert files, the path to the .defs file, the name of a .hg file, the source directory, and the destination directory.
zh_CN: 请注意我们为<command>gmmproc</command>提供了.m4转换文件、.defs文件路径、.hg文件名、源代码目录、目标目录。

en: You should avoid including the C header from your C++ header, to avoid polluting the global namespace, and to avoid exporting unnecessary public API. But you will need to include the necessary C headers from your .ccg file.
zh_CN: 你应该避免在C++头文件中包含C头文件，以免污染全局名称空间，以免导出不必要的公共API。但是你需要在你的.ccg文件中包含必要的C头文件。

en: The macros are explained in more detail in the following sections.
zh_CN: 以下各节将对宏进行详细说明。

en: m4 Conversions
zh_CN: m4转换

en: The macros that you use in the .hg and .ccg files often need to know how to convert a C++ type to a C type, or vice-versa. <command>gmmproc</command> takes this information from an .m4 file in your <literal>tools/m4/</literal> or <literal>codegen/m4/</literal> directory. This allows it to call a C function in the implementation of your C++ method, passing the appropriate parameters to that C functon. For instance, this tells <command>gmmproc</command> how to convert a <classname>GtkTreeView</classname> pointer to a <classname>Gtk::TreeView</classname> pointer:
zh_CN: 在.hg和.ccg文件中使用的宏通常需要知道如何将C++类型转换为C类型，反之亦然。<command>gmmproc</command>会从你的<literal>tools/m4/</literal>或<literal>codegen/m4/</literal>目录的.m4文件读取此信息。这样它就可以在C++方法的实现中调用C函数，并将适当的参数传递给该C函数。例如：这告诉<command>gmmproc</command>如何将<classname>GtkTreeView</classname>指针转换为<classname>Gtk::TreeView</classname>指针：

en: <literal>$3</literal> will be replaced by the parameter name when this conversion is used by <command>gmmproc</command>.
zh_CN: 当此转换被<command>gmmproc</command>使用时，<literal>$3</literal>将会被参数名称替换。

en: Some extra macros make this easier and consistent. Look in <application>gtkmm</application>'s .m4 files for examples. For instance:
zh_CN: 使用一些额外的宏可以使其变得更简单和一致。例如<application>gtkmm</application>中的.m4文件：

en: m4 Initializations
zh_CN: 安装m4

en: Often when wrapping methods, it is desirable to store the return of the C function in what is called an output parameter. In this case, the C++ method returns <type>void</type> but an output parameter in which to store the value of the C function is included in the argument list of the C++ method. <command>gmmproc</command> allows such functionality, but appropriate initialization macros must be included to tell <command>gmmproc</command> how to initialize the C++ parameter from the return of the C function.
zh_CN: 在封装方法时，通常最好将C函数的返回值储存在被称为输出参数的参数中。在本例中，C++方法返回<type>void</type>但是有一个用于储存C函数值的输出参数。<command>gmmproc</command>支持此功能，但是必须使用适当的初始化宏来告诉<command>gmmproc</command>如何从C函数的返回值初始化C++参数。

en: For example, if there was a C function that returned a <type>GtkWidget*</type> and for some reason, instead of having the C++ method also return the widget, it was desirable to have the C++ method place the widget in a specified output parameter, an initialization macro such as the following would be necessary:
zh_CN: 例如，如果一个C函数返回了一个<type>GtkWidget*</type>，并且由于某种原因，不想让C++方法返回此部件，而是希望C++方法将此部件放入指定的输出参数中，则如下所示的初始化宏是必须的：

en: <literal>$3</literal> will be replaced by the output parameter name of the C++ method and <literal>$4</literal> will be replaced by the return of the C function when this initialization is used by <command>gmmproc</command>. For convenience, <literal>$1</literal> will also be replaced by the C++ type without the ampersand (&amp;) and <literal>$2</literal> will be replaced by the C type.
zh_CN: <literal>$3</literal>将被C++方法的输出参数名替换，<literal>$4</literal>将在此初始化被<command>gmmproc</command>使用时被C函数的返回值替代。为了方便起见，<literal>$1</literal>也将被不带<literal>&amp;</literal>符的C++类型替换，而<literal>$2</literal>将被替换为C类型。

en: Class macros
zh_CN: 类宏

en: The class macro declares the class itself and its relationship with the underlying C type. It generates some internal constructors, the member <varname>gobject_</varname>, typedefs, the <function>gobj()</function> accessors, type registration, and the <function>Glib::wrap()</function> method, among other things.
zh_CN: 类宏声明了类本身与其底层C类型的关系。它会生成一些内部构造函数、<varname>gobject_</varname>成员、类型定义(typedef)、<function>gobj()</function>访问器、<function>Glib::wrap()</function>成员函数、并进行类型注册等。

en: Other macros, such as <function>_WRAP_METHOD()</function> and <function>_WRAP_SIGNAL()</function> may only be used after a call to a <function>_CLASS_*</function> macro.
zh_CN: 其他像<function>_WRAP_METHOD()</function>和<function>_WRAP_SIGNAL()</function>这样的宏只能在调用<function>_CLASS_*</function>宏之后使用。

en: This macro declares a wrapper for a type that is derived from <classname>GObject</classname>, but whose wrapper is not derived from <classname>Gtk::Object</classname>.
zh_CN: 这个宏为从<classname>GObject</classname>派生的类型声明了一个类型包装器，但是此包装器并不会派生自<classname>Gtk::Object</classname>。

en: <function>_CLASS_GOBJECT( C++ class, C class, C casting macro, C++ base class, C base class )</function>
zh_CN: <function>_CLASS_GOBJECT( C++类, C类, C转换宏, C++基类, C基类 )</function>

en: For instance, from <filename>adjustment.hg</filename>:
zh_CN: 示例来自于<filename>entry.hg</filename>：

en: This macro declares a wrapper for a type whose wrapper is derived from <classname>Gtk::Object</classname>, such as a widget or dialog.
zh_CN: 这个宏为类型声明了一个类型派生包装器，此包装器将派生自<classname>Gtk::Object</classname>，例如部件(Widget)和对话框(Dialog)。

en: <function>_CLASS_GTKOBJECT( C++ class, C class, C casting macro, C++ base class, C base class )</function>
zh_CN: <function>_CLASS_GTKOBJECT( C++类, C类, C转换宏, C++基类, C基类 )</function>

en: For instance, from <filename>button.hg</filename>:
zh_CN: 来自<filename>button.hg</filename>文件中的例子：

en: You will typically use this macro when the class already derives from <classname>Gtk::Object</classname>. For instance, you will use it when wrapping a GTK Widget, because <classname>Gtk::Widget</classname> derives from <classname>Gtk::Object</classname>.
zh_CN: 当类已从<classname>Gtk::Object</classname>派生时，你通常会使用此宏。例如：你将在封装GTK部件时使用它，因为<classname>Gtk::Widget</classname>派生自<classname>Gtk::Object</classname>。

en: You might also derive non-widget classes from <classname>Gtk::Object</classname> so they can be used without <classname>Glib::RefPtr</classname>. For instance, they could then be instantiated with <function>Gtk::make_managed()</function> or on the stack as a member variable. This is convenient, but you should use this only when you are sure that true reference-counting is not needed. We consider it useful for widgets.
zh_CN: 你还可以从<classname>Gtk::Object</classname>派生非部件类，这样你就可以在不通过<classname>Glib::RefPtr</classname>直接使用它们。例如：它们将可以使用<function>Gtk::make_managed()</function>实例化也可以作为成员变量在栈上实例化。这样你可以自行决定是否对它们使用引用计数。我们认为对部件使用引用计数很有用。

en: This macro declares a wrapper for a non-<classname>GObject</classname> struct, registered with <function>g_boxed_type_register_static()</function>.
zh_CN: 这个宏声明了一个非<classname>GObject</classname>结构体类型的包装器，并使用<function>g_boxed_type_register_static()</function>对该类型进行注册。

en: <function>_CLASS_BOXEDTYPE( C++ class, C class, new function, copy function, free function )</function>
zh_CN: <function>_CLASS_BOXEDTYPE( C++类, C类, new函数, copy函数, free函数 )</function>

en: For instance, from <classname>Gdk::RGBA</classname>:
zh_CN: 示例来自<classname>Gdk::RGBA</classname>：

en: This macro declares a wrapper for a simple assignable struct such as <classname>GdkRectangle</classname>. It is similar to <function>_CLASS_BOXEDTYPE</function>, but the C struct is not allocated dynamically.
zh_CN: 这个宏为类似于<classname>GdkRectangle</classname>这样的简单可赋值结构体声明了一个包装器。它和<function>_CLASS_BOXEDTYPE</function>类似，不过其包装的C结构体不是动态分配的。

en: <function>_CLASS_BOXEDTYPE_STATIC( C++ class, C class )</function>
zh_CN: <function>_CLASS_BOXEDTYPE_STATIC( C++类, C类 )</function>

en: For instance, for <classname>Gdk::Rectangle</classname>:
zh_CN: 示例来自<classname>Gdk::Rectangle</classname>：

en: This macro declares a wrapper for an opaque struct that has copy and free functions. The new, copy and free functions will be used to instantiate the default constructor, copy constructor and destructor.
zh_CN: 这个宏为具有复制和释放函数的不透明结构体声明了一个包装器。新建(new)、复制(copy)、释放(free)函数将用于实例化默认构造函数、复制构造函数、析构函数。

en: <function>_CLASS_OPAQUE_COPYABLE( C++ class, C class, new function, copy function, free function )</function>
zh_CN: <function>_CLASS_OPAQUE_COPYABLE( C++类, C类, new函数, copy函数, free函数 )</function>

en: For instance, from <classname>Glib::VariantType</classname>:
zh_CN: 示例来自<classname>Glib::Checksum</classname>：

en: This macro declares a wrapper for a reference-counted opaque struct. The C++ wrapper cannot be directly instantiated and can only be used with <classname>Glib::RefPtr</classname>.
zh_CN: 这个宏为使用引用计数的不透明结构体声明了一个包装器。C++包装器将不能直接实例化，需要与<classname>Glib::RefPtr</classname>一起使用。

en: <function>_CLASS_OPAQUE_REFCOUNTED( C++ class, C class, new function, ref function, unref function )</function>
zh_CN: <function>_CLASS_OPAQUE_REFCOUNTED( C++函数, C函数, new函数, ref函数, unref函数 )</function>

en: For instance, for <classname>Gtk::CssSection</classname>:
zh_CN: 示例来自<classname>Gdk::Rectangle</classname>：

en: This macro can be used to wrap structs which don't fit into any specialized category.
zh_CN: 这个宏用于包装任何不属于专用包装宏的结构体。

en: <function>_CLASS_GENERIC( C++ class, C class )</function>
zh_CN: <function>_CLASS_GENERIC( C++类, C类 )</function>

en: For instance, for <classname>Gdk::TimeCoord</classname>:
zh_CN: 示例来自<classname>Gdk::Rectangle</classname>：

en: This macro declares a wrapper for a type that is derived from <classname>GTypeInterface</classname>.
zh_CN: 这个宏为派生自<classname>GTypeInterface</classname>的类型声明了一个包装器。

en: <function>_CLASS_INTERFACE( C++ class, C class, C casting macro, C interface struct, Base C++ class (optional), Base C class (optional) )</function>
zh_CN: <function>_CLASS_INTERFACE( C++类, C类, C转换宏, C接口结构体, C++基类(可选的), C基类(可选的) )</function>

en: For instance, from <filename>celleditable.hg</filename>:
zh_CN: 示例来自与<filename>celleditable.hg</filename>：

en: Two extra optional parameters were once added, for the case that the interface derives from another interface, which was believed to be the case when the GInterface has another GInterface as a prerequisite. This is a misunderstanding, though. When GInterface A has GInterface B as a prerequisite, it means that every class that implements A shall also implement B. For instance, from <filename>loadableicon.hg</filename> in glibmm-2.4:
zh_CN: 对于接口是从其他接口派生的情况，两个附加参数是可选的，GInterface有另一个GInterface作为先决条件时属于此情况。示例来自于<filename>loadableicon.hg</filename>：

en: Constructor macros
zh_CN: 构造函数宏

en: The <function>_CTOR_DEFAULT()</function> and <function>_WRAP_CTOR()</function> macros add constructors, wrapping the specified <function>*_new()</function> C functions. These macros assume that the C object has properties with the same names as the function parameters, as is usually the case, so that it can supply the parameters directly to a <function>g_object_new()</function> call. These constructors never actually call the <function>*_new()</function> C functions, because <application>gtkmm</application> must actually instantiate derived GTypes, and the <function>*_new()</function> C functions are meant only as convenience functions for C programmers.
zh_CN: <function>_CTOR_DEFAULT()</function>和<function>_WRAP_CTOR()</function>宏封装指定的<function>*_new()</function> C函数并添加构造函数。这些宏假定C对象具有与函数参数名一样的属性名，这样它就可以直接向<function>g_object_new()</function>调用提供参数。这些构造函数实际上从不会调用<function>*_new()</function> C函数，因为<application>gtkmm</application>必须实例化派生的GType，而<function>*_new()</function> C函数只是用于给C程序员提供便利。

en: When using <function>_CLASS_GOBJECT()</function>, the constructors should be protected (rather than public) and each constructor should have a corresponding <function>_WRAP_CREATE()</function> in the public section. This prevents the class from being instantiated without using a <classname>RefPtr</classname>. For instance:
zh_CN: 在使用<function>_CLASS_GOBJECT()</function>时，其构造函数应该是保护(protected)的而不是公有(public)。并且每个公有(public)的构造函数都应该有<function>_WRAP_CREATE()</function>。这样可以防止在不使用<classname>RefPtr</classname>的情况下直接实例化这个类。例如：

en: This macro creates a default constructor with no arguments.
zh_CN: 这个宏创建一个不接受参数的默认构造函数

en: This macro creates a constructor with arguments, equivalent to a <function>*_new()</function> C function. It won't actually call the <function>*_new()</function> function, but will simply create an equivalent constructor with the same argument types. It takes a C++ constructor signature, and a C function name.
zh_CN: 这个宏创建一个接受参数的构造函数，与<function>*_new()</function> C函数等效。但是他不会调用<function>*_new()</function>函数，只会创建有相同参数类型的构造函数。它需要一个C++构造函数签名和一个C函数名。

en: This tells <command>gmmproc</command> that the C <function>*_new()</function> has a final <type>GError**</type> parameter which should be ignored.
zh_CN: 这告诉<command>gmmproc</command>，<function>*_new()</function>的最后一个 <type>GError**</type>是否应该被忽略。

en: It also takes an optional extra argument: <_:variablelist-1/>
zh_CN: 他还有需要额外的可选参数：<_:variablelist-1/>

en: Hand-coding constructors
zh_CN: 手工编码构造函数

en: When a constructor must be partly hand written because, for instance, the <function>*_new()</function> C function's parameters do not correspond directly to object properties, or because the <function>*_new()</function> C function does more than call <function>g_object_new()</function>, the <function>_CONSTRUCT()</function> macro may be used in the .ccg file to save some work. The <function>_CONSTRUCT</function> macro takes a series of property names and values. For instance, from <filename>button.ccg</filename>:
zh_CN: 有时因为<function>*_new()</function> C函数的参数不与对象属性直接对应，或是<function>*_new()</function> C函数不只是简单的调用<function>g_object_new()</function>，你将必须手写一部分构造函数。在此时你可以在》ccg文件中使用<function>_CONSTRUCT()</function>宏来保存一些工作。<function>_CONSTRUCT</function>宏接受一系列属性名与值作为参数。示例来自<filename>button.ccg</filename>：

en: Macros that suppress generation of some code
zh_CN: 抑制某些代码生成的宏

en: Some macros suppress the generation of some code when they are used after a <function>_CLASS_*</function> macro. Some suppress the definition in the generated .cc file, others suppress both the declaration in the .h file and the definition in the .cc file.
zh_CN: 在某些宏在<function>_CLASS_*</function>宏之后使用时，它们会抑制某些代码的生成。一些抑制在.cc文件中生成定义，另一些抑制在.h文件中生成的声明和.cc文件中生成的定义。

en: Suppresses declaration and definition of default constructor in <function>_CLASS_BOXEDTYPE</function>, <function>_CLASS_BOXEDTYPE_STATIC</function> and <function>_CLASS_OPAQUE_COPYABLE</function>.
zh_CN: 抑制<function>_CLASS_BOXEDTYPE</function>、<function>_CLASS_BOXEDTYPE_STATIC</function>、<function>_CLASS_OPAQUE_COPYABLE</function>生成默认构造函数的声明和定义。

en: Suppresses declaration and definition of the constructor that takes a pointer to the wrapped C object in <function>_CLASS_BOXEDTYPE</function> and <function>_CLASS_BOXEDTYPE_STATIC</function>.
zh_CN: 抑制<function>_CLASS_BOXEDTYPE</function>和<function>_CLASS_BOXEDTYPE_STATIC</function>生成接受指向其所包装的C类型的指针的构造函数的声明和定义。

en: Suppresses definition of the constructor that takes a pointer to the wrapped C object in <function>_CLASS_INTERFACE</function> and <function>_CLASS_OPAQUE_COPYABLE</function>.
zh_CN: 抑制<function>_CLASS_INTERFACE</function>和<function>_CLASS_OPAQUE_COPYABLE</function>生成接受指向其所包装的C类型的指针的构造函数的定义。

en: Suppresses definition of the constructor that takes a pointer to the wrapped C object and the constructor that takes construct_params in <function>_CLASS_GOBJECT</function> and <function>_CLASS_GTKOBJECT</function>.
zh_CN: 抑制<function>_CLASS_GOBJECT</function>和<function>_CLASS_GTKOBJECT</function>生成接受指向其所包装的C类型的指针且接受其他构造参数的构造函数的定义。

en: Suppresses definition of destructor in <function>_CLASS_GOBJECT</function> and <function>_CLASS_GTKOBJECT</function>.
zh_CN: 抑制<function>_CLASS_GOBJECT</function>和<function>_CLASS_GTKOBJECT</function>生成析构函数的定义

en: Suppresses declaration and definition of move constructor and move assignment operator in <function>_CLASS_GOBJECT</function> and <function>_CLASS_GTKOBJECT</function>.
zh_CN: 抑制<function>_CLASS_GOBJECT</function><function>_CLASS_GTKOBJECT</function>生成移动构造函数和移动赋值运算符的声明和定义。

en: For example:
zh_CN: 例如：

en: Suppresses definition of <function>Glib::wrap_new()</function> function in <function>_CLASS_GOBJECT</function>.
zh_CN: 抑制<function>_CLASS_GOBJECT</function>生成<function>Glib::wrap_new()</function>的定义。

en: Suppresses definition of <function>Glib::wrap()</function> function in <function>_CLASS_GOBJECT</function> and <function>_CLASS_GTKOBJECT</function>.
zh_CN: 抑制<function>_CLASS_GOBJECT</function>和<function>_CLASS_GTKOBJECT</function>生成<function>Glib::wrap()</function>函数的定义。

en: Suppresses declaration and definition of <function>Glib::wrap()</function> function in <function>_CLASS_GOBJECT</function>, <function>_CLASS_BOXEDTYPE</function>, <function>_CLASS_BOXEDTYPE_STATIC</function>, <function>_CLASS_OPAQUE_COPYABLE</function>, <function>_CLASS_INTERFACE</function> and <function>_CLASS_GTKOBJECT</function>.
zh_CN: 抑制<function>_CLASS_GOBJECT</function>、<function>_CLASS_BOXEDTYPE</function>、<function>_CLASS_BOXEDTYPE_STATIC</function>、<function>_CLASS_OPAQUE_COPYABLE</function>、<function>_CLASS_INTERFACE</function>和<function>_CLASS_GTKOBJECT</function>生成<function>Glib::wrap()</function>函数的声明和定义。

en: Method macros
zh_CN: 方法宏

en: This macro generates the C++ method to wrap a C function.
zh_CN: 这个宏用于生成封装C函数的C++方法。

en: <function>_WRAP_METHOD( C++ method signature, C function name)</function>
zh_CN: <function>_WRAP_METHOD( C++方法签名, C函数名)</function>

en: For instance, from <filename>entry.hg</filename>:
zh_CN: 示例来自于<filename>entry.hg</filename>：

en: The C function (e.g. <function>gtk_entry_set_text</function>) is described more fully in the .defs file, and the <filename>convert*.m4</filename> files contain the necessary conversion from the C++ parameter type to the C parameter type. This macro also generates doxygen documentation comments based on the <filename>*_docs.xml</filename> and <filename>*_docs_override.xml</filename> files.
zh_CN: 在.defs文件中有对C函数更全面的描述，<filename>convert*.m4</filename>文件中包含了从C++参数类型到C参数类型的必要转换。这个宏还基于<filename>*_docs.xml</filename>和<filename>*_docs_override.xml</filename>文件生成doxygen文档注释。

en: Do an extra <function>reference()</function> on the return value, in case the C function does not provide a reference.
zh_CN: 在C函数不提供引用时，对其返回值额外调用一次<function>reference()</function>。

en: Use the last GError** parameter of the C function to throw an exception. The optional "&lt;exceptions&gt;" is a comma-separated list of exceptions that can be thrown. It determines which @throws Doxygen commands are added to the documentation. Default value is <classname>Glib::Error</classname>. If you want a comma in the description of an exception, precede it by a backslash. Example: <code>errthrow "Glib::OptionError Hello\, world, Glib::ConvertError"</code>
zh_CN: 使用C函数的最后一个GError**参数抛出异常，可选的"&lt;exceptions&gt;"是一个以逗号分隔的可抛出异常列表。它决定了哪些@throws Doxygen命令将被加入文档。默认抛出的是<classname>Glib::Error</classname>异常。如果你需要在异常描述中使用逗号，请使用反斜杠对其进行转义。例如：<code>errthrow "Glib::OptionError Hello\, world, Glib::ConvertError"</code>

en: Puts the generated code in #ifdef blocks. Text about the deprecation can be specified as an optional parameter.
zh_CN: 将生成的代码放入#ifdef块中。text是可选参数，用于提供与弃用有关的文本信息。

en: Just call the non-const version of the same function, instead of generating almost duplicate code.
zh_CN: 直接调用同一个函数的非const版本，而不是生成几乎相同的代码。

en: Adds a @newin Doxygen command to the documentation, or replaces the @newin command generated from the C documentation.
zh_CN: 在文档中添加@newin Doxygen命令，或替换从C文档中生成的@newin命令。

en: Puts the generated code in #ifdef blocks.
zh_CN: 将生成的代码放入ifdef &lt;identifier&gt;块中。

en: Specifies the name of the slot parameter of the method, if it has one. This enables <command>gmmproc</command> to generate code to copy the slot and pass the copy on to the C function in its final <literal>gpointer user_data</literal> parameter. The <literal>slot_callback</literal> option must also be used to specify the name of the glue callback function to also pass on to the C function.
zh_CN: 如果方法存在一个槽参数，指定该槽参数的名称。这使得<command>gmmproc</command>可以生成用于复制槽并将其复制传递给C函数的<literal>gpointer user_data</literal>参数的代码。<literal>slot_callback</literal>参数需要使用此选项指定的名称。

en: Used in conjunction with the <literal>slot_name</literal> option to specify the name of the glue callback function that handles extracting the slot and then calling it. The address of this callback is also passed on to the C function that the method wraps.
zh_CN: 与<literal>slot_name</literal>选项一起使用。用<literal>slot_name</literal>所指定的胶水回调函数处理提取槽然后调用它。这个回调函数的函数指针也将被传递给封装此C函数的方法。

en: Tells <command>gmmproc</command> not to pass a copy of the slot to the C function, if the method has one. Instead the slot itself is passed. The slot parameter name and the glue callback function must have been specified with the <literal>slot_name</literal> and <literal>slot_callback</literal> options respectively.
zh_CN: 告知<command>gmmproc</command>如果此方法有槽，不要将槽的副本传递给C函数。而是直接传递槽本身。槽的参数名和胶水回调函数必须分别使用<literal>slot_name</literal>和<literal>slot_callback</literal>选项指定。

en: There are some optional extra arguments: <_:variablelist-1/>
zh_CN: 有一些可选的额外参数：<_:variablelist-1/>

en: Objects used via <classname>RefPtr</classname>: Pass the <classname>RefPtr</classname> as a const reference. For instance, <code>const Glib::RefPtr&lt;Gtk::FileFilter&gt;&amp; filter</code>.
zh_CN: 通过<classname>RefPtr</classname>使用的对象：传递<classname>RefPtr</classname>的const引用。例如：<code>const Glib::RefPtr&lt;Gtk::FileFilter&gt;&amp; filter</code>。

en: Const Objects used via <classname>RefPtr</classname>: If the object should not be changed by the function, then make sure that the object is const, even if the <classname>RefPtr</classname> is already const. For instance, <code>const Glib::RefPtr&lt;const Gtk::FileFilter&gt;&amp; filter</code>.
zh_CN: 通过<classname>RefPtr</classname>使用的const对象：如果函数不应该修改此对象，即使对象已经是const的，也应该确保对象的<classname>RefPtr</classname>是const的。例如：<code>const Glib::RefPtr&lt;const Gtk::FileFilter&gt;&amp; filter</code>。

en: Wrapping <classname>GList*</classname> and <classname>GSList*</classname> parameters: First, you need to discover what objects are contained in the list's data field for each item, usually by reading the documentation for the C function. The list can then be wrapped by a <classname>std::vector</classname> type. For instance, <code>std::vector&lt;Glib::RefPtr&lt;Gdk::Pixbuf&gt;&gt;</code>. You may need to define a Traits type to specify how the C and C++ types should be converted.
zh_CN: 包装<classname>GList*</classname>和<classname>GSList*</classname>参数：首先你需要阅读C函数的文档，确定列表中每项的数据字段包含了那些对象。然后确定如何用<classname>std::vector</classname>进行包装。例如包装为<code>std::vector&lt;Glib::RefPtr&lt;Gdk::Pixbuf&gt;&gt;</code>。你可能需要定义一个Traits类型来指示C类型和C++类型如何相互转换。

en: Wrapping <classname>GList*</classname> and <classname>GSList*</classname> return types: You must discover whether the caller should free the list and whether it should release the items in the list, again by reading the documentation of the C function. With this information you can choose the ownership (none, shallow or deep) for the m4 conversion rule, which you should probably put directly into the .hg file because the ownership depends on the function rather than the type. For instance: <_:programlisting-1/>
zh_CN: 包装<classname>GList*</classname>和<classname>GSList*</classname>返回值：你需要在此阅读C函数文档，确定调用方是否需要负责释放列表和列表中的项目。然后根据这些信息，选择m4转换规则的所有权（无(none)、浅(shallow)、深(deep)），你可能应该将其直接放在.hg文件中，因为所有权取决于函数本身而不是其类型。例如：<_:programlisting-1/>

en: Selecting which C++ types should be used is also important when wrapping C API. Though it's usually obvious what C++ types should be used in the C++ method, here are some hints: <_:itemizedlist-1/>
zh_CN: 封装C API时，选择对应的C++类型也很重要。尽管多数时候应该在C++方法中使用什么C++类型是很明显的，但我们还是想给你一些提示：<_:itemizedlist-1/>

en: This macro is like <function>_WRAP_METHOD()</function>, but it generates only the documentation for a C++ method that wraps a C function. Use this when you must hand-code the method, but you want to use the documentation that would be generated if the method was generated.
zh_CN: 这个宏类似于<function>_WRAP_METHOD()</function>，但是它只生成封装C函数的C++方法的文档。当你需要手动编写该方法又不想手动编写文档时，请使用这个宏。

en: For instance, from <filename>recentinfo.hg</filename>:
zh_CN: 示例来自于<filename>container.hg</filename>：

en: Excludes documentation of the last GError** parameter of the C function. The optional "&lt;exceptions&gt;" is a comma-separated list of exceptions that can be thrown. It determines which @throws Doxygen commands are added to the documentation. Default value is <classname>Glib::Error</classname>. If you want a comma in the description of an exception, precede it by a backslash. Example: <code>errthrow "Glib::OptionError Hello\, world, Glib::ConvertError"</code>
zh_CN: 不要在文档中包含C函数的最后一个GError**参数的文档。可选的 "&lt;exceptions&gt;"是一个以逗号分隔的可抛出异常列表。它决定了哪些@throws Doxygen命令将被加入文档。默认抛出的是<classname>Glib::Error</classname>异常。如果你需要在异常描述中使用逗号，请使用反斜杠对其进行转义。例如：<code>errthrow "Glib::OptionError Hello\, world, Glib::ConvertError"</code>

en: Don't include a @return Doxygen command in the documentation. Useful if the wrapped C function returns a value, but the corresponding C++ method returns <type>void</type>.
zh_CN: 不要再文档中包含@return Doxygen命令。如果被封装的C函数有返回而封装它的C++方法返回<type>void</type>，这将很有用。

en: <command>gmmproc</command> will warn you on stdout about functions, signals, properties and child properties that you have forgotten to wrap, helping to ensure that you are wrapping the complete API. But if you don't want to wrap some functions, signals, properties or child properties, or if you chose to hand-code some methods then you can use the _IGNORE(), _IGNORE_SIGNAL() or _IGNORE_PROPERTY() macro to make <command>gmmproc</command> stop complaining.
zh_CN: <command>gmmproc</command>会在stdout上警告你忘了封装相关的函数、信号、属性、子属性，这有助于确保API被完整的封装。但有时候你会不想对某些函数、信号、属性、子属性封装，或者你想要手动编写一些函数，那么你可以使用_IGNORE()、_IGNORE_SIGNAL()、_IGNORE_PROPERTY()宏使<command>gmmproc</command>停止发出部分警告。

en: <function>_IGNORE(C function name 1, C function name 2, etc)
    _IGNORE_SIGNAL(C signal name 1, C signal name 2, etc)
    _IGNORE_PROPERTY(C property name 1, C property name 2, etc)</function>
zh_CN: <function>_IGNORE(C属性名1, C属性名2, ...)
    _IGNORE_SIGNAL(C属性名1, C属性名2, ...)
    _IGNORE_PROPERTY(C属性名1, C属性名2, ...)</function>

en: For instance, from <filename>flowbox.hg</filename>:
zh_CN: 示例来自<filename>flowbox.hg</filename>：

en: This macro generates the C++ libsigc++-style signal to wrap a C GObject signal. It actually generates a public accessor method, such as <function>signal_clicked()</function>, which returns a proxy object. <command>gmmproc</command> uses the .defs file to discover the C parameter types and the .m4 convert files to discover appropriate type conversions.
zh_CN: 这个宏生成用来封装C GObject信号的C++ libsigc++风格的信号。实际上它会生成一个公有访问器方法，例如<function>signal_clicked()</function>，它返回一个代理对象。<command>gmmproc</command>使用.defs文件寻找C参数类型并使用.m4转换文件查找如何将其转换为适当的类型。

en: <function>_WRAP_SIGNAL( C++ signal handler signature, C signal name)</function>
zh_CN: <function>_WRAP_SIGNAL( C++信号处理函数签名, C信号名)</function>

en: Signals usually have function pointers in the GTK struct, with a corresponding enum value and a <function>g_signal_new()</function> in the .c file.
zh_CN: 信号通常在GTK结构体中具有函数指针，在.c文件中有对应的枚举值和<function>g_signal_new()</function>函数。

en: Do not generate an <function>on_something()</function> virtual method to allow easy overriding of the default signal handler. Use this when adding a signal with a default signal handler would break the ABI by increasing the size of the class's virtual function table, and when adding a signal without a public C default handler.
zh_CN: 不要生成<function>on_something()</function>虚成员函数以允许简单的覆写默认信号处理函数。可以在添加一个具有默认信号处理函数的信号会使虚函数表尺寸变大以至于破坏ABI的时候，或是在需要添加一个非公共C默认处理函数的时候，使用此可选参数。

en: Generate a declaration of the <function>on_something()</function> virtual method in the <filename>.h</filename> file, but do not generate a definition in the <filename>.cc</filename> file. Use this when you must generate the definition by hand.
zh_CN: 在<filename>.h</filename>文件中生成<function>on_something()</function>虚成员函数的声明，但不在<filename>.cc</filename>文件中生成该函数的定义。请在你需要手动编写函数定义的时候使用此可选参数。

en: Do not generate a C callback function for the signal. Use this when you must generate the callback function by hand.
zh_CN: 不要为信号生成C回调函数。请在你需要手动编写回调函数的时候使用此可选参数。

en: Do an extra <function>reference()</function> on the return value of the <function>on_something()</function> virtual method, in case the C function does not provide a reference.
zh_CN: 当C函数没有提供引用的时候，在<function>on_something()</function>虚成员函数的返回值上额外调用一次<function>reference()</function>。

en: Allows to use custom exception handler instead of default one. Exception might be rethrown by user-defined handler, and it will be caught by default handler.
zh_CN: 允许使用自定义异常处理函数而不是使用默认异常处理函数。如果异常被用户自定义的处理函数程序抛出，则该异常将被默认异常处理函数捕获。

en: Adds a <type>const Glib::ustring&amp;</type> parameter to the <methodname>signal_something()</methodname> method. Use it, if the signal accepts a detailed signal name, i.e. if the underlying C code registers the signal with the <literal>G_SIGNAL_DETAILED</literal> flag.
zh_CN: 向<methodname>signal_something()</methodname>成员函数添加一个<type>const Glib::ustring&amp;</type>参数。如果信号接受详细信号名，也就是说底层C代码使用了<literal>G_SIGNAL_DETAILED</literal>标志注册这个信号，则使用该参数作为详细信号名。

en: Used in conjunction with the <literal>detail_name</literal> option to generate two <methodname>signal_something()</methodname> methods, one without a parameter and one with a parameter without a default value. With only the <literal>detail_name</literal> option one method is generated, with a parameter with default value. Use the <literal>two_signal_methods</literal> option, if it's necessary in order to preserve ABI.
zh_CN: 需与<literal>detail_name</literal>选项一起使用。生成两个<methodname>signal_something()</methodname>成员函数，其中一个不带任何参数，而另一个接受一个参数但该参数没有默认值。如果只使用<literal>detail_name</literal>选项，则只生成一个成员函数，此成员函数将接受一个参数且此参数有默认值。请再需要保持ABI不变的情况下使用此选项。

en: This macro generates the C++ method to wrap a C GObject property. You must specify the property name and the wanted C++ type for the property. <command>gmmproc</command> uses the .defs file to discover the C type and the .m4 convert files to discover appropriate type conversions.
zh_CN: 这个宏生成用于包装C GObject属性的C++方法。你需要为该属性指定属性名以及其值所需的C++类型。<command>gmmproc</command>使用.defs文件寻找C参数类型并使用.m4转换文件查找如何将其转换为适当的类型。

en: <function>_WRAP_PROPERTY(C property name, C++ type)</function>
zh_CN: <function>_WRAP_PROPERTY(C属性名, C++类型)</function>

en: This macro generates the C++ method to wrap a virtual C function.
zh_CN: 这个宏生成用于封装C虚函数的C++成员函数。

en: <function>_WRAP_VFUNC( C++ method signature, C function name)</function>
zh_CN: <function>_WRAP_VFUNC( C++成员函数签名, C函数名)</function>

en: For instance, from <filename>widget.hg</filename>:
zh_CN: 示例来自于<filename>widget.hg</filename>：

en: The C function (e.g. <function>get_request_mode</function>) is described more fully in the <filename>*_vfuncs.defs</filename> file, and the <filename>convert*.m4</filename> files contain the necessary conversion from the C++ parameter type to the C parameter type. Conversions can also be written in the .hg file. Virtual functions often require special conversions that are best kept local to the .hg file where they are used.
zh_CN: 在<filename>*_vfuncs.defs</filename>文件中有对C函数更全面的描述，<filename>convert*.m4</filename>文件中包含了从C++参数类型到C参数类型的必要转换。转换也可以写入.hg文件。虚函数通常需要额外的转换，这些转换最好保存在使用这些虚函数的.hg文件文件中。

en: Do an extra <function>reference()</function> on the return value of the <function>something_vfunc()</function> function, in case the virtual C function does not provide a reference.
zh_CN: 当C虚函数没有提供引用的时候，在<function>something_vfunc()</function>函数的返回值上额外调用一次<function>reference()</function>。

en: Do an extra <function>reference()</function> on the return value of an overridden <function>something_vfunc()</function> function in the C callback function, in case the calling C function expects it to provide a reference.
zh_CN: 当被调用的C函数期望其提供一个引用的时候，在C回调函数当中，对被覆写的<function>something_vfunc()</function>函数的返回值额外调用一次<function>reference()</function>。

en: Keep a copy of the return value in the C callback function, in case the calling C function does not expect to get its own reference.
zh_CN: 当被调用的C函数不想要得到属于它的引用的时候，在C回调函数中保留一份返回值的副本。

en: Use the last GError** parameter of the C virtual function (if there is one) to throw an exception.
zh_CN: 如果C虚函数的参数中的最后有一个GError**参数，则使用此参数抛出异常。

en: Do not generate a definition of the vfunc in the <filename>.cc</filename> file. Use this when you must generate the vfunc by hand.
zh_CN: 不在<filename>.cc</filename>文件中生成虚函数的定义。请在你需要手写虚函数的时候使用此可选参数。

en: Do not generate a C callback function for the vfunc. Use this when you must generate the callback function by hand.
zh_CN: 不为虚函数生成C回调函数。请在你需要手写回调函数时使用此可选参数。

en: Defines a non-default return value.
zh_CN: 定义非默认的返回值。

en: Defines a non-default return value, used only if the C++ <function>something_vfunc()</function> function throws an exception which is propagated to the C callback function. If return_value is specified, but err_return_value is not, then return_value is used also when an exception is propagated.
zh_CN: 定义一个只在C++ <function>something_vfunc()</function>函数抛出异常，且传播到了C回调函数中的时候才使用的非默认返回值。如果指定了return_value但没有指定err_return_value，则将err_return_value的值视作return_value的值。

en: A rule to which there may be exceptions: If the virtual C function returns a pointer to an object derived from <classname>GObject</classname>, i.e. a reference-counted object, then the virtual C++ function shall return a <classname>Glib::RefPtr&lt;&gt;</classname> object. One of the extra arguments <parameter>refreturn</parameter> or <parameter>refreturn_ctype</parameter> is required.
zh_CN: 一个可能有例外的规则：如果一个C虚函数返回了指向派生自<classname>GObject</classname>的对象的指针，也即一个引用计数对象的指针，那么C++虚函数应该返回<classname>Glib::RefPtr&lt;&gt;</classname>对象。且需要<parameter>refreturn</parameter>或<parameter>refreturn_ctype</parameter>额外参数。

en: Other macros
zh_CN: 其他宏

en: This macro generates initialization code for the interface.
zh_CN: 这个宏为接口生成初始化代码

en: <function>_IMPLEMENTS_INTERFACE(C++ interface name)</function>
zh_CN: <function>_IMPLEMENTS_INTERFACE(C++接口名)</function>

en: For instance, from <filename>grid.hg</filename>:
zh_CN: 示例来自于<filename>grid.hg</filename>：

en: There is one optional extra argument: <_:variablelist-1/>
zh_CN: 有一个可选的额外参数：<_:variablelist-1/>

en: This macro generates a C++ enum to wrap a C enum. You must specify the desired C++ name and the name of the underlying C enum.
zh_CN: 这个宏生成一个C++枚举以包装C枚举。你必须指定所需的C++名称和底层C枚举的名称。

en: For instance, from <filename>enums.hg</filename>:
zh_CN: 示例来自于<filename>enums.hg</filename>：

en: Use this option, if the enum is not a <classname>GType</classname>. This is the case when there is no <function>*_get_type()</function> function for the C enum, but be careful that you don't just need to include an extra header for that function. You should also file a bug against the C API, because all enums should be registered as GTypes.
zh_CN: 如果枚举不是一个<classname>GType</classname>，则需使用此选项。在这个情况下C枚举没有<function>*_get_type()</function>函数，你不需要为该函数额外包含头文件。但你应该此为对C API提交一个bug，因为所有的枚举都应该被注册为GTypes。

en: If you specify <literal>NO_GTYPE</literal>, don't use that enum as the type in _WRAP_PROPERTY. It would cause a runtime error, when the generated <methodname>property_*()</methodname> method is called.
zh_CN: 如果你指定了<literal>NO_GTYPE</literal>，不要再_WRAP_PROPERTY中使用此枚举类型。这会导致生成的<methodname>property_*()</methodname>成员函数被调用时出现运行时错误。

en: For example, from <filename>icontheme.hg</filename>:
zh_CN: 示例来自于<filename>icontheme.hg</filename>：

en: Specifies the name of the <function>*_get_type()</function> function for the C enum. Use this parameter if <command>gmmproc</command> can't deduce the correct function name from the name of the C enum type.
zh_CN: 指定C枚举的<function>*_get_type()</function>函数名。如果<command>gmmproc</command>无法从C枚举类型的名称推断出正确的函数名，请使用此额外参数。

en: For example, from <filename>dbusproxy.hg</filename> in glibmm:
zh_CN: 示例来自于glibmm的<filename>dbusproxy.hg</filename>：

en: "Convertible to int." Generates a plain enum (not an enum class) within a class. Such an enum is scoped like an enum class, but unlike an enum class, it can be implicitly converted to <type>int</type>.
zh_CN: 在一个类中生成普通枚举而不是生成枚举类。这将允许该枚举类型的值可以直接转换为<type>int</type>类型的值，且这样的枚举还拥有与枚举类类似的作用域。

en: For example, from <filename>dialog.hg</filename>:
zh_CN: 示例来自于<filename>dialog.hg</filename>：

en: Substitutes (part of) the name of one or more enum constants. You can add any number of substitutions.
zh_CN: 替换一个或多个枚举常量名称的全部或一部分。你可以添加任意数量的替换。

en: For example, from <filename>iochannel.hg</filename> in glibmm:
zh_CN: 示例来自于glibmm中的<filename>iochannel.hg</filename>：

en: This macro just generates a Doxygen documentationn block for the enum. This is useful for enums that can't be wrapped with <function>_WRAP_ENUM()</function> because they are complexly defined (maybe using C macros) but including the generated enum documentation is still desired. It is used with the same syntax as <function>_WRAP_ENUM()</function> and also processes the same options (though NO_GTYPE, gtype_func &lt;function_name&gt; and CONV_TO_INT are ignored because they make no difference when just generating the enum's documentation).
zh_CN: 这个宏只是为枚举生成一个Doxygen文档块。这对于因为过于复杂（这通常是因为使用了C宏）而无法使用<function>_WRAP_ENUM()</function>包装，且依然需要包含为枚举生成的文档的枚举类型很有用。它与<function>_WRAP_ENUM()</function>使用同一语法，也处理一样的参数（尽管有些额外参数因为没有作用会被忽略）

en: This macro generates a C++ exception class, derived from <classname>Glib::Error</classname>, with a <type>Code</type> enum and a <methodname>code()</methodname> method. You must specify the desired C++ name, the name of the corresponding C enum, and the prefix for the C enum values.
zh_CN: 这个宏会生成一个C++异常类，生成的类派生自<classname>Glib::Error</classname>，并具有一个<type>Code</type>枚举成员变量和一个<methodname>code()</methodname>成员函数。你必须指定所需的C++名称、以及与其对应的C枚举名、C枚举值前缀。

en: This exception can then be thrown by methods which are generated from _WRAP_METHOD() with the errthrow option.
zh_CN: 然后可以由带有errthrow选项的_WRAP_METHOD()生成的成员函数抛出此异常。

en: For instance, from <filename>pixbuf.hg</filename>:
zh_CN: 示例来自于<filename>pixbuf.hg</filename>：

en: _WRAP_GERROR() accepts the same optional arguments as _WRAP_ENUM() (though CONV_TO_INT is ignored because all exception class enums are plain enums within a class).
zh_CN: _WRAP_GERROR()接受与_WRAP_ENUM()一样的可选参数（尽管CONV_TO_INT参数因为没有作用而被忽略）。

en: Use these macros if you're wrapping a simple struct or boxed type that provides direct access to its data members, to create getters and setters for the data members.
zh_CN: 如果要包装可以被直接访问其数据成员的简单结构体或装箱类型，请使用这些宏。这些宏会为其数据成员创建访问器成员函数（getter和setter）。

en: <function>_MEMBER_GET(C++ name, C name, C++ type, C type)</function>
zh_CN: <function>_MEMBER_GET(C++名, C名, C++类型, C类型)</function>

en: <function>_MEMBER_SET(C++ name, C name, C++ type, C type)</function>
zh_CN: <function>_MEMBER_SET(C++名, C名, C++类型, C类型)</function>

en: For example, in <filename>rectangle.hg</filename>:
zh_CN: 示例来自于<filename>rectangle.hg</filename>：

en: Use these macros to automatically provide getters and setters for a data member that is a pointer type. For the getter function, it will create two methods, one const and one non-const.
zh_CN: 使用这些宏可以自动为指针类型的数据成员提供访问器（getter和setter）。对于getter函数，将创建两个版本，一个const版本一个非const版本。

en: <function>_MEMBER_GET_PTR(C++ name, C name, C++ type, C type)</function>
zh_CN: <function>_MEMBER_GET_PTR(C++名, C名, C++类型, C类型)</function>

en: <function>_MEMBER_SET_PTR(C++ name, C name, C++ type, C type)</function>
zh_CN: <function>_MEMBER_GET_PTR(C++名, C名, C++类型, C类型)</function>

en: For example, for <classname>Pango::Analysis</classname> in <filename>item.hg</filename>:
zh_CN: 示例来自于<filename>item.hg</filename>文件中的<classname>Pango::Analysis</classname>：

en: Use these macros to provide getters and setters for a data member that is a <classname>GObject</classname> type that must be referenced before being returned.
zh_CN: 使用这些宏可以为返回之前必须被引用的<classname>GObject</classname>类型数据成员提供访问器（getters和setters）。

en: <function>_MEMBER_GET_GOBJECT(C++ name, C name, C++ type, C type)</function>
zh_CN: <function>_MEMBER_GET_GOBJECT(C++名, C名, C++类型, C类型)</function>

en: <function>_MEMBER_SET_GOBJECT(C++ name, C name, C++ type, C type)</function>
zh_CN: <function>_MEMBER_SET_GOBJECT(C++名, C名, C++类型, C类型)</function>

en: For example, in Pangomm, <filename>layoutline.hg</filename>:
zh_CN: 示例来自于Pangomm中的<filename>layoutline.hg</filename>：

en: gmmproc Parameter Processing
zh_CN: gmmproc参数处理

en: <command>gmmproc</command> allows processing the parameters in a method signature for the macros that process method signatures (like <function>_WRAP_METHOD()</function>, <function>_WRAP_CTOR()</function> and <function>_WRAP_CREATE()</function>) in a variety of ways:
zh_CN: <command>gmmproc</command>允许以各种方式为处理成员函数签名的宏（如<function>_WRAP_METHOD()</function>、<function>_WRAP_CTOR()</function>、<function>_WRAP_CREATE()</function>）处理成员函数签名中的参数：

en: Parameter Reordering
zh_CN: 对参数重新排序

en: For all the macros that process method signatures, it is possible to specify a different order for the C++ parameters than the existing order in the C function, virtual function or signal. For example, say that the following C function were being wrapped as a C++ method for the <classname>Gtk::Widget</classname> class: <_:programlisting-1/> However, changing the order of the C++ method's two parameters is necessary. Something like the following would wrap the function as a C++ method with a different order for the two parameters: <_:programlisting-2/> The <literal>{c_param_name}</literal> following the method parameter names tells <command>gmmproc</command> to map the C++ parameter to the specified C parameter within the <literal>{}</literal>. Since the C++ parameter names correspond to the C ones, the above could be re-written as: <_:programlisting-3/>
zh_CN: 对于所有处理成员函数签名的宏，可以为C++参数指定一个与C函数、虚函数、信号中现有顺序不同的顺序。例如，假设如下所示的C函数将被封装为<classname>Gtk::Widget</classname>类的C++成员函数：<_:programlisting-1/>但是必须改变C++成员函数中两个参数的顺序。如下所示的代码会将函数封装为C++成员函数但两个参数的顺序会有所不同：<_:programlisting-2/>成员函数参数后的<literal>{c_param_name}</literal>告知<command>gmmproc</command>将C++参数映射到<literal>{}</literal>内的C参数。由于C++参数名与C参数名相对应，所以上述代码可以被重写为：<_:programlisting-3/>

en: Please note that when reordering parameters for a <function>_WRAP_SIGNAL()</function> method signature, the C parameter names would always be <literal>p0</literal>, <literal>p1</literal>, etc. because the <filename>generate_extra_defs</filename> utility uses those parameter names no matter what the C API's parameter names may be. It's how the utility is written presently.
zh_CN: 请注意，当为使用<function>_WRAP_SIGNAL()</function>的成员函数签名重排参数时，C参数名总是<literal>p0</literal>、<literal>p1</literal>等。因为这些参数名由<filename>generate_extra_defs</filename>实用工具使用，而该实用工具不在乎C API中的参数名是什么。

en: Optional Parameter Processing
zh_CN: 可选参数处理

en: For all macros processing method signatures except <function>_WRAP_SIGNAL()</function> and <function>_WRAP_VFUNC()</function> it is also possible to make the parameters optional so that extra C++ methods are generated without the specified optional parameter. For example, say that the following <function>*_new()</function> function were being wrapped as a constructor in the <classname>Gtk::ToolButton</classname> class: <_:programlisting-1/> Also, say that the C API allowed NULL for the function's <parameter>label</parameter> parameter so that that parameter is optional. It would be possible to have <command>gmmproc</command> generate the original constructor (with all the parameters) along with an additional constructor without that optional parameter by appending a <literal>{?}</literal> to the parameter name like so: <_:programlisting-2/> In this case, two constructors would be generated: One with the optional parameter and one without it.
zh_CN: 对于除了<function>_WRAP_SIGNAL()</function>和<function>_WRAP_VFUNC()</function>以外的所有处理成员函数签名的宏，都可以讲参数设为可选的，这样就可以在没有指定可选参数的情况下额外生成C++成员函数。例如，假设以下所示的<function>*_new()</function>将被封装为<classname>Gtk::ToolButton</classname>类的构造函数：<_:programlisting-1/> 另外，假设C API允许函数的<parameter>label</parameter>参数为NULL，这样该参数就是可选的。通过在参数名后附加一个<literal>{?}</literal>可以使<command>gmmproc</command>生成具有所有参数的原始构造函数和一个带有可选参数的构造函数。在如下所示的情况下：<_:programlisting-2/> 将生成两个构造函数：一个带可选参数，另一个不带可选参数。

en: Output Parameter Processing
zh_CN: 输出参数处理

en: With <function>_WRAP_METHOD()</function> it is also possible for the return of the wrapped C function (if it has one) to be placed in an output parameter of the C++ method instead of having the C++ method also return a value like the C function does. To do that, simply include the output parameter in the C++ method parameter list appending a <literal>{OUT}</literal> to the output parameter name. For example, if <function>gtk_widget_get_request_mode()</function> is declared as the following: <_:programlisting-1/> And having the C++ method set an output parameter is desired instead of returning a <type>SizeRequestMode</type>, something like the following could be used: <_:programlisting-2/> The <literal>{OUT}</literal> appended to the name of the <parameter>mode</parameter> output parameter tells <command>gmmproc</command> to place the return of the C function in that output parameter. In this case, however, a necessary initialization macro like the following would also have to be specified: <_:programlisting-3/> Which could also be written as: <_:programlisting-4/>
zh_CN: 使用<function>_WRAP_METHOD()</function>也可以将封装好的C函数的返回值放到C++成员函数的输出参数中，而不是让C++成员函数和C函数一样返回一个值。要做到这个，只需要在C++成员函数参数列表中的输出参数名后附加<literal>{OUT}</literal>即可。例如，如果<function>gtk_widget_get_request_mode()</function>的声明如下所示：<_:programlisting-1/> 想要让C++成员函数使用输出参数而不是返回一个<type>SizeRequestMode</type>。可以用如下所示的方法：<_:programlisting-2/>附加在名为<parameter>mode</parameter>的输出参数之后的<literal>{OUT}</literal>，告知<command>gmmproc</command>将C函数的返回值放在输出参数中。但是在这种情况下还必须指定必要的初始化宏。如下所示：<_:programlisting-3/>也可以写成：<_:programlisting-4/>

en: <function>_WRAP_METHOD()</function> also supports setting C++ output parameters from C output parameters if the C function being wrapped has any. Suppose, for example, that we want to wrap the following C function that returns a value in its C output parameter <parameter>rect</parameter>: <_:programlisting-1/> To have <command>gmmproc</command> place the value returned in the C++ <parameter>rect</parameter> output parameter, something like the following <function>_WRAP_METHOD()</function> macro could be used: <_:programlisting-2/> The <literal>{&gt;&gt;}</literal> following the <parameter>rect</parameter> parameter name indicates that the C++ output parameter should be set from the value returned in the C parameter from the C function. <command>gmmproc</command> will generate a declaration of a temporary variable in which to store the value of the C output parameter and a statement that sets the C++ output parameter from the temporary variable. In this case it may be necessary to have an <function>_INITIALIZATION()</function> describing how to set a <classname>Gdk::Rectangle&amp;</classname> from a <classname>GdkRectangle*</classname> such as the following: <_:programlisting-3/>
zh_CN: 如果被封装的C函数有输出参数，<function>_WRAP_METHOD()</function>也支持将C输出参数设置为C++输出参数。例如，假设我们想封装以下C函数，该函数在C输出参数<parameter>rect</parameter>中返回一个值：<_:programlisting-1/>要让<command>gmmproc</command>将返回值放于C++ <parameter>rect</parameter>输出参数中，可以使用如下所示的<function>_WRAP_METHOD()</function>宏：<_:programlisting-2/><parameter>rect</parameter>参数名后面的<literal>{&gt;&gt;}</literal>表示C++输出参数应该用C函数的C参数返回的值来设置。<command>gmmproc</command>将生成一个用于储存C输出参数的值的临时变量的声明，以及一条使用临时变量设置C++输出参数的语句。在这种情况下，可能需要使用<function>_INITIALIZATION()</function>描述如何从一个<classname>GdkRectangle*</classname>设置一个<classname>Gdk::Rectangle&amp;</classname>。如下所示：<_:programlisting-3/>

en: String Parameter Processing
zh_CN: 处理字符串参数

en: A string-valued input parameter in a C++ method is usually a <type>const Glib::ustring&amp;</type> or a <type>const std::string&amp;</type>. In C code it's a <type>const gchar*</type>. When an empty string is converted to <type>const gchar*</type>, it can be converted either to <literal>nullptr</literal> or to a pointer to an empty string (with <methodname>c_str()</methodname>). Some parameters in some C functions accept a <literal>nullptr</literal>, and interpret it in a special way. Other parameters must not be <literal>nullptr</literal>.
zh_CN: 在C++成员函数中的字符串值的输入参数通常是<type>const Glib::ustring&amp;</type>或者是<type>const std::string&amp;</type>。而在C代码中，它是<type>const gchar*</type>。在将空字符串转换为<type>const gchar*</type>的时候，可以将其转换为<literal>nullptr</literal>或者是一个指向空字符串的指针（用<methodname>c_str()</methodname>）。一些C函数的一些参数接受<literal>nullptr</literal>，并以特殊方式解释它。其他参数不能为<literal>nullptr</literal>。

en: for mandatory parameters (with or without default values): empty string to empty string,
zh_CN: 对于带有或不带有默认值的强制性参数：空字符串到空字符串

en: for optional parameters (with appended <literal>{?}</literal>): empty string to <literal>nullptr</literal>.
zh_CN: 对于附加了<literal>{?}</literal>的可选参数：空字符串到<literal>nullptr</literal>。

en: The default conversion in <function>_WRAP_METHOD()</function> and similar macros is <_:itemizedlist-1/> If the default conversion is not the best conversion, append <literal>{NULL}</literal> to a mandatory parameter or <literal>{?!NULL}</literal> to an optional parameter (<literal>!NULL</literal> = not <literal>NULL</literal>). If you append both a C parameter name and <literal>NULL</literal>, separate them with a space: <literal>{c_param_name NULL}</literal>.
zh_CN: <function>_WRAP_METHOD()</function>和类似的宏的默认转换是：<_:itemizedlist-1/>如果默认转换不够好，可以将<literal>{NULL}</literal>附加到强制性参数之后，或是将<literal>{?!NULL}</literal>附加到可选参数之后（<literal>!NULL</literal>意为非<literal>NULL</literal>）。如果想同时添加C参数名和<literal>NULL</literal>，则用空格对它们进行分隔：<literal>{c_param_name NULL}</literal>。

en: Basic Types
zh_CN: 基本类型

en: Some of the basic types that are used in C APIs have better alternatives in C++. For example, there's no need for a <type>gboolean</type> type since C++ has <type>bool</type>. The following list shows some commonly-used types in C APIs and what you might convert them to in a C++ wrapper library.
zh_CN: C API中使用的一些基本类型在C++中有更好的替代类型。例如，C++中有<type>bool</type>类型，所以不需要<type>gboolean</type>类型。以下列表显示了C API中的一些常用类型，以及你可以在C++封装库中将它们转换为哪些类型。

en: Basic Type equivalents
zh_CN: 基本类型的等效项

en: C type
zh_CN: C 类型

en: C++ type
zh_CN: C++类型

en: <classname>Glib::ustring</classname> (or <classname>std::string</classname> for filenames)
zh_CN: <classname>Glib::ustring</classname>(或<classname>std::string</classname>)

en: Hand-coded source files
zh_CN: 手工编码源文件

en: You might want to include additional source files that will not be generated by <command>gmmproc</command> from <filename>.hg</filename> and <filename>.ccg</filename> files. You can simply place these in your <filename>libsomething/libsomethingmm</filename> directory and mention them in the <filename>meson.build</filename> in the <varname>extra_h_files</varname> and <varname>extra_cc_files</varname> variables.
zh_CN: 你可能想包括<command>gmmproc</command>不会从<filename>.hg</filename>和<filename>.ccg</filename>文件中生成的额外源文件。你可以将它们放到你的<filename>libsomething/libsomethingmm</filename>文件夹中，并在<filename>meson.build</filename>的<varname>extra_h_files</varname>和<varname>extra_cc_files</varname>变量提到它们。

en: Initialization
zh_CN: 初始化

en: Your library must be initialized before it can be used, to register the new types that it makes available. Also, the C library that you are wrapping might have its own initialization function that you should call. You can do this in an <function>init()</function> function that you can place in hand-coded <filename>init.h</filename> and <filename>init.cc</filename> files. This function should initialize your dependencies (such as the C function, and <application>gtkmm</application>) and call your generated <function>wrap_init()</function> function. For instance:
zh_CN: 你必须初始化你的库，以便注册库提供给的新类型，这样你才能使用它。另外你所封装的C库可能有自己需要调用的初始化函数。你可以将其放在手动编码的<filename>init.h</filename>和<filename>init.cc</filename>文件中的<function>init()</function>函数中完成此操作。这个函数应该初始化你的依赖项和调用你生成的<function>wrap_init()</function>函数。例如：

en: The implementation of the <function>wrap_init()</function> method in <filename>wrap_init.cc</filename> is generated by <filename>generate_wrap_init.pl</filename>, but the declaration in <filename>wrap_init.h</filename> is hand-coded, so you will need to adjust <filename>wrap_init.h</filename> so that the <function>wrap_init()</function> function appears in the correct C++ namespace.
zh_CN: <filename>wrap_init.cc</filename>文件中的<function>wrap_init()</function>方法是由<filename>generate_wrap_init.pl</filename>生成的，但是它的声明所在的<filename>wrap_init.h</filename>文件需要手动编码。因此你需要调整<filename>wrap_init.h</filename>文件以使<function>wrap_init()</function>函数出现在正确的C++命名空间中。

en: Problems in the C API.
zh_CN: C API中的问题

en: You are likely to encounter some problems in the library that you are wrapping, particularly if it is a new project. Here are some common problems, with solutions.
zh_CN: 你可能会在封装库的过程中遇到一些问题。特别是它是一个新项目的时候。以下是一些常见问题以及解决方案。

en: Unable to predeclare structs
zh_CN: 无法提前声明的结构体

en: By convention, structs are declared in glib/GTK-style headers like so:
zh_CN: 按照约定，glib/GTK风格的头文件中结构体声明应如下所示：

en: The extra typedef allows the struct to be used in a header without including its full definition, simply by predeclaring it, by repeating that typedef. This means that you don't have to include the C library's header in your C++ header, thus keeping it out of your public API. <command>gmmproc</command> assumes that this technique was used, so you will see compiler errors if that is not the case.
zh_CN: 额外的typedef允许在头文件中使用该结构体而不需要包含其完整定义，只需要通过重复这个typedef预先声明它即可。这意味着你不需要在你的C++头文件中包含C库的头文件。，从而将其排除在你的公共API之外。<command>gmmproc</command>假定使用了这个技术，因此如果没使用这种技术就会遇到编译错误。

en: This compiler error might look like this: <_:programlisting-1/> or this: <_:programlisting-2/>
zh_CN: 编译错误看起来可能如下所示：<_:programlisting-1/>或如下所示：<_:programlisting-2/>

en: This is easy to correct in the C library, so do send a patch to the relevant maintainer.
zh_CN: 这很容易在C库中修复，你可以向相关库的维护者发送补丁。

en: Lack of properties
zh_CN: 缺少属性

en: By convention, glib/GTK-style objects have <function>*_new()</function> functions, such as <function>example_widget_new()</function> that do nothing more than call <function>g_object_new()</function> and return the result. The input parameters are supplied to <function>g_object_new()</function> along with the names of the properties for which they are values. For instance,
zh_CN: 按照约定，glib/GTK风格对象应具有<function>*_new()</function>函数，例如<function>example_widget_new()</function>仅调用<function>g_object_new()</function>并返回其结果。输入参数为<function>g_object_new()</function>函数提供属性名和属性值。例如：

en: This allows language bindings to implement their own equivalents (such as C++ constructors), without using the <function>*_new()</function> function. This is often necessary so that they can actually instantiate a derived GType, to add their own hooks for signal handlers and vfuncs.
zh_CN: 这允许语言绑定实现自己的等效项（例如C++构造函数），而不需要使用<function>*_new()</function>函数。这通常是必须的，这是为了让它们可以实例化派生的GType，这样就可以为信号处理函数和虚函数添加自己的钩子。

en: At the least, the <function>_new()</function> function should not use any private API (functions that are only in a .c file). Even when there are no functions, we can sometimes reimplement 2 or 3 lines of code in a <function>_new()</function> function as long as those lines of code use API that is available to us.
zh_CN: <function>_new()</function>函数不应该使用任何只在.c文件中的私有API。即使没有对应的函数，有时我们也可以在<function>_new()</function>函数中重新实现2到3行代码，只要这些行使用的API是可用的。

en: Another workaround is to add a <function>*_construct()</function> function that the C++ constructor can call after instantiating its own type. For instance,
zh_CN: 另一个解决方法是添加一个C++构造函数可以在实例化自身类型后调用的<function>*_construct()</function>函数。例如：

en: Adding properties, and ensuring that they interact properly with each other, is relatively difficult to correct in the C library, but it is possible, so do file a bug and try to send a patch to the relevant maintainer.
zh_CN: 在C库中，添加属性并确保它们之间正确的进行交互相对来说比较困难。但还是能做到的。若你发现了一个bug请联系相关的维护人员并向其提供相关信息以便尽快修复该bug。

en: Documentation
zh_CN: 文档

en: In general, gtkmm-style projects use Doxygen, which reads specially formatted C++ comments and generates HTML documentation. You may write these doxygen comments directly in the header files.
zh_CN: 通常，gtkmm风格项目使用Doxygen生成文档，它会读取特殊格式的C++注释并生成HTML文档。你可以直接将这些doxygen可读的注释写到头文件中。

en: Reusing C documentation
zh_CN: 重用C文档

en: You might wish to reuse documentation that exists for the C library that you are wrapping. GTK-style C libraries typically use gtk-doc and therefore have source code comments formatted for gtk-doc and some extra documentation in .sgml and .xml files. The docextract_to_xml.py script, from glibmm's <filename>tools/defs_gen</filename> directory, can read these files and generate an .xml file that <command>gmmproc</command> can use to generate doxygen comments. <command>gmmproc</command> will even try to transform the documentation to make it more appropriate for a C++ API.
zh_CN: 你可能想重用所封装C库的现有文档。GTK风格的C库通常直接使用gtk-doc，因此在.sgml和.xml文件中有一些gtk-doc格式的源代码注释和一些额外的文档。在glibmm的<filename>tools/defs_gen</filename>目录中的docextract_to_xml.py脚本，可以读取这些文件并生成一个.xml文件，<command>gmmproc</command>可以使用这个文件生成doxygen注释。<command>gmmproc</command>甚至会尝试转换文档以使其更适合C++ API。

en: Because this automatic transformation is not always appropriate, you might want to provide hand-written text for a particular method. You can do this by copying the XML node for the function from your <filename>something_docs.xml</filename> file to the <filename>something_docs_override.xml</filename> file and changing the contents. Alternatively you can write your own documentation in the <filename>.hg</filename> file.
zh_CN: 由于此自动转换并不总是合适的，所以你可能希望对特定的方法提供手写的文本。为此可以将函数的XML节点从<filename>something_docs.xml</filename>文件复制到<filename>something_docs_override.xml</filename>文件并更改其内容。你也可以在<filename>.hg</filename>文件中编写自己的文档。

en: Documentation build structure
zh_CN: 文档构建结构

en: If you copied the skeleton source tree in <application>mm-common</application> and substituted the placeholder text, then you will already have suitable <filename>meson.build</filename> and <filename>Doxyfile.in</filename> files in the <filename>doc/reference/</filename> directory. You probably need to modify the <varname>tag_file_modules</varname> variable in <filename>meson.build</filename>, though. With the <application>mm-common</application> build setup, the list of Doxygen input files is not defined in the Doxygen configuration file, but passed along from <command>meson/ninja</command> to the standard input of <command>doxygen</command>.
zh_CN: 如果你已经从<application>mm-common</application>中复制skeleton源代码树并替换占位文本，那么在<filename>doc/reference/</filename>目录中已经拥有了合适的<filename>meson.build</filename>和<filename>Doxyfile.in</filename>文件。你可能需要修改<filename>meson.build</filename>文件中的<varname>tag_file_modules</varname>变量，虽然在<application>mm-common</application>构建设置中，Doxygen输入文件不是通过Doxygen配置文件定义的，而是由<command>meson/ninja</command>传递文件内容到<command>doxygen</command>的标准输入。
