LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: Smalltalk

gtkmm 的翻译计划

[复制链接]
发表于 2004-3-11 19:23:56 | 显示全部楼层
支持,我给加精啦。
发表于 2004-3-11 21:10:23 | 显示全部楼层
support!
发表于 2004-3-11 21:24:13 | 显示全部楼层
我英语很菜的,不能帮你翻译了。只能帮助宣传宣传了。
实在不好意思了。
 楼主| 发表于 2004-3-11 22:05:16 | 显示全部楼层
多谢各位弟兄的支持 :-)

还好在这里贴了一份
今天不小心把电脑上的备份全删了

其实小弟也菜得很
大家不嫌弃
小弟已经很感激了

现在的确比较忙
但我会尽力把这个工作做好的
关键是积累嘛
呵呵 :-)

现在图片啊,链接啊什么的都没做
等集中精力全部翻译完了
再做成 HTML 格式的

还想知道大家对此有些什么建议
 楼主| 发表于 2004-3-13 16:23:28 | 显示全部楼层
第三章剩下的部分:

窗口组件

gtkmm 应用程序由一系列窗口组成, 这些窗口包含了像按钮, 文本框这样的一些组件. 在其它一些系统上, 窗口组件被称作"控件". 对于你的应用程序中的每个组件, 对应地, 在你的代码里有相应的 C++ 对象. 所以当你想控制组件行为的时候, 只要调用这个组件对象的相应方法即可.

组件被排列在褚如 frame, notebook 这样的窗口容器中. 在架构上, 属于组件的组件这样一个层次. 有一些像 Gtk::VBox 这样的容器组件是不可见的 - 它们只被用来放置其它组件. 下面这个例子用来把两个 Gtk::Button 控件放到一个 Gtk::VBox 容器中.

m_box.pack_start(m_Button1);
m_box.pack_start(m_Button2);

接下来我们演示怎样再把这个包含两个按钮的 Gtk::VBox 加入一个 Gtk::Frame 中. 它含一个可以的边框和标题.

这本书中的大部分章节处理特定的组件. 关于把组件添加到容器组件中, 要得到更多的信息, 请看容器组件这一章.

尽管你可以用 C++ 代码来控制窗口和组件的外观和布局, 但你会发现, 用 Glade 来设计你的界面, 或在运行时使用 libglademm 动态加载界面是一件更轻松的事. 请参考 Glade 和 libglademm 这一章.

信号

和其它 GUI 工具集一样, gtkmm 也是事件驱动的. 当一个事件发生时, 比如说一个按钮被按下, 被按下的这个组件将发出一个合适的信号. 每种组件有一组不同的信号集可以发送. 为了使这个按钮按下的动作产生合适的效果, 我们可以建立一个信号号柄(signal handler)来捕捉这个信号.

gtkmm 使用 libsigc++ 来实现信号操作. 下面这个例子演示怎样把 Gtk::Button 的单击(clicked)信号连接到 on_button_clicked 这个信号处理句柄上.

m_button1.signal_clicked().connect( sigc::mem_fun(*this, &HelloWorld:n_button_clicked) );

要得到更多关于信号的信息, 请参考附录.

要想知道实现你自己的信号处理方式, 而不仅仅是连接到现成的 gtkmm 信号. 请参考附录.

Glib::ustring

你一定很奇怪 gtkmm 没有把 std::string 纳入自己的接口中. 实际上, Glib::ustring 和它非常相似, 甚至不用看下面的部分, 你就可以把它当成 std::string 来用. 但如果你是想使用编程语言而不是英语的话, 最好还是看一下吧.

std::string 使用 8 位字符编码, 但是对于像阿拉伯语, 汉语和日语这样的语言来说, 8位编码是不够的. 尽管这些语言的编码已经被 Unicode Constortium 组织详细说明了, 但是 C 和 C++ 还没有提供标准的 Unicode 支持. GTK+ 和 GNOME 采用 UTF-8 编码来实现 Unicode, 这也是 Glib::ustring 所包装的东西. 它提供和 std::string 几乎相同的接口, 以及和 std::string 的自动类型转换功能.

UTF-8 编码的优点之一是, 除非必要, 你可以不使用它, 所以你不必经常把自己的代码变来变去. std::string 还将继续使用 7 位的 ASCII 编码. 但是一旦你想本地化你的程序, 比如说, 汉化, 那你就会开始遇到各种奇怪的问题, 可能还会崩溃. 然后你可能只得用 Glib::usting 取而代之.

要注意的是 UTF-8 和其它一些 8 位的编码如 ISO-8859-1 并不兼容. 比如, 德语中的元音变音并不在 ASCII 码的编码范围内, 你还需要 UTF-8 编码中额外一位. 如果你的代码中包含 8 位的字符串, 你需要把它们转变成 UTF-8 编码 (比如, 巴伐利亚的问候语 "Grü? Gott" 可能会显示成 "Gr\xC3\xBC\xC3\x9F Gott").

你应该尽量避免 C 类型的指针算法, 以及像 strlen() 这样的函数. 在 UTF-8 编码中, 每个字符可能占 1 到 6 个字节, 所以你并不能假定下一个字节一定是另一个字符. 所有的这些细节 Glib::ustring 都已经帮你考虑到了, 所以你可以从字符的层面上考虑使用 Glib::ustring::substr() 这样的函数, 而不用再去考虑字节这样的细节了.

不像 Windows 的 UCS-2 Unicode 解决方案, 这并不需要编译器提供特别的选项来处理这样字符串, 也不会导致含 Unicode 的可执行文件或库与含 ASCII 的不兼容.
   
参考

要得到更多关于 UTF-8 字符的信息, 请参考国际化这一节.

中间型别

gtkmm 的部分 API 使用了中间型别, 比如使用 Glib::StringArrayHandle, 而不是像 std::vector 或 std::list 这样的 C++ 标准容器. 你不用声明这些型别 -- 你也可以使用自己喜欢的 C++ 标准容器. gtkmm 会为你做好自动型别转换的工作. 下面是一些常用的中间型别:

    Glib::StringArrayHandle 或 Glib::ArrayHandle<Glib::ustring>: 使用 std::vector<Glib::ustring>, std::list<Glib::ustring>, const char*[], 等等.

    Glib:istHandle<Gtk::Widget*>: 使用 std::vector<Gtk::Widget*>, std::list<Gtk::Widget*>, 等等.

    Glib::SListHandle<Gtk::Widget*>: 使用 std::vector<Gtk::Widget*>, std::list<Gtk::Widget*>, 等等.

用 gtkmm 写 Hello World

到目前为止, 我们已经可以自己的所学来写一个真正的程序了. 根据计算机科学的传统, 你们现在以 gtkmm 的方式来介绍 Hello World:

源代码:

文件: helloworld.h
[php]
#ifndef GTKMM_EXAMPLE_HELLOWORLD_H
#define GTKMM_EXAMPLE_HELLOWORLD_H

#include <gtkmm/button.h>
#include <gtkmm/window.h>

class HelloWorld : public Gtk::Window
{

public:
  HelloWorld();
  virtual ~HelloWorld();

protected:
  // 消息句柄:
  virtual void on_button_clicked();

  // 成员组件:
  Gtk::Button m_button;
};

#endif // GTKMM_EXAMPLE_HELLOWORLD_H
[/php]

File: helloworld.cc
[php]
#include "helloworld.h"
#include <iostream>

HelloWorld::HelloWorld()
: m_button("Hello World")   // 创建一个含 "Hello World" 标签的按钮.
{
  // 为窗口设置边框宽度.
  set_border_width(10);

  // 当按钮收到 "clicked" 消息时, 会调用 hello() 方法.
  // hello() 方法将在下面定义.
  m_button.signal_clicked().connect(sigc::mem_fun(*this, &HelloWorld:n_button_clicked));

  // 这个语句将按钮包装进窗口(一个容器)
  add(m_button);

  // 最后一步是显示刚刚创建的组件...
  m_button.show();
}

HelloWorld::~HelloWorld()
{
}

void HelloWorld:n_button_clicked()
{
  std::cout << "Hello World" << std::endl;
}
[/php]

文件: main.cc
[php]
#include <gtkmm/main.h>
#include "helloworld.h"

int main (int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  HelloWorld helloworld;
  Gtk::Main::run(helloworld); //显示窗口, 关闭时返回.

  return 0;
}
[/php]
尝试着编译并运行这个程序. 你会看到这样的结果:

图片 3.1. Hello World

[图片]

真让人激动, 嗯? 让我们回过头来看一下代码. 先看 HelloWorld 类:
[php]
class HelloWorld : public Gtk::Window
{

public:
  HelloWorld();
  virtual ~HelloWorld();

protected:
  // 消息句柄:
  virtual void on_button_clicked();

  // 成员组件:
  Gtk::Button m_button;
}
[/php]
这个类实现了 "Hello World" 窗口. 它由 Gtk::Window 派生, 并且仅有一个 Gtk::Button 成员. 我们已经使用构造函数为该窗口完成了所有的初始化工作, 包括挂接消息. 下面是除去注释的代码:
[php]
HelloWorld::HelloWorld()
:
  m_button ("Hello World")
{
  set_border_width(10);
  m_button.signal_clicked().connect(sigc::mem_fun(*this, &HelloWorld:n_button_clicked));
  add(m_button);.
  m_button.show();
}
[/php]
注意, 我们使用初始化列表的方式给 m_button 对象添加了一个 "Hello World" 的标签.

接下来调用 Windows 类的 set_border_width() 方法, 设置窗口的边框和它所包含的组件之间的空白距离.

再把 m_button 的 clicked 消息挂接到消息号柄上. 结果会向 stdout(标准输入) 打印出友好的问候语.

下一步, 我们使用 Window 类的 add() 方法把 m_button 加到 Window 类中. (add() 方法由 Gtk::container 类继承而来,  我们将在容器这一章中具体介绍.) add() 方法仅仅将组件添加到窗口中, 它并不负责显示这些组件. 所以 gtkmm 组件在创建以后都是不可见的 - 要显示它们, 你必须调用 show() 方法, 通常我们会在下个一语句就调用它.

现在让我们来看看没有注释过的 main() 函数:
[php]
int main(int argc, char** argv)
{
  Gtk::Main kit(argc, argv);

  HelloWorld helloworld;
  Gtk::Main::run(helloworld);

  return 0;
}
[/php]
我们首先初始化一个叫 kit 的对象, 它是 Gtk::Main 类型的. 每一个程序都有这样一个东西. 我们将命令行参数传递给它. 它提取自己需要的参数, 将剩下的部分留给我们, 就像前面已经描述过的那样.

接着我们创建了 HelloWorld 类的实例, 它的构造函数没有参数, 但它也是不可见的.  当我们调用 Gtk::Main::run(), 并给它提供一个 helloworld 窗口作为参数时, 它将窗口显示出来并进入消息循环. 在消息循环中, gtkmm 是空闲的, 它等待用户的操作动作并作出相应的反应. 当用户关闭窗口时, run() 函数将返回, main() 函数的最后一行将被执行. 程序也就结束了.
 楼主| 发表于 2004-3-14 19:55:07 | 显示全部楼层
现在又多了一个成员
wbusy 兄加入了 :-)
他是个强人
比我懂的要多
 楼主| 发表于 2004-3-14 19:56:06 | 显示全部楼层
wbusy 翻译的第四章:

第四章        按钮

gtkmm 提供以下四种基本按钮控件:
按钮(Push-Buttons)
        Gtk ::Button. 这是标准按钮,通常用文字标签或者图片来标识它。按一下就会触发一个事件。参看Button。
开关按钮(标记按钮)(Toggle Buttons)
        Gtk ::ToggleButton. 和一般按下后自动弹起的按钮不一样,开关按钮需要你再按一次才会弹起。当你要用到开关(或者类似的功能)时,它会很有用。参看ToggleButton。
复选框(CheckBoxes)
        Gtk ::CheckButton. 它们用起来和ToggleButtons很相像,只不过它们用一个小方块来显示自己的状态。在需要设置是/否的大多数情况下都可以使用它们。
单选按钮(Radio Buttons)
        Gtk ::RadioButton. 它是根据老式汽车内的收音机的选台器来命名的,选台器是一组选择按钮并且它们是互斥的。按下其中任何一个都会使这一组中的其他按钮都弹起.它们的布局和CheckBoxes(一个旁边有标签的小窗口)很相似,但是通常看起来不一样。参看RadioButton。
请注意,由于GTK+的主题/风格(的特点),这些控件外观可能会改变。复选框和单选按钮可能会很不相同。

Button

构造函数
可以通过两种方式来创建按钮,你可以在Gtk ::Button构造函数中指定标签字符串,或者以后调用set_lable()来指定标签。

如果你想(为按钮)定义加速键,那么可以在标签字符串中的某个字符前面加上一个下划线,并且(在构造函数中)指定可选的参数mnemonic为true。例如:
Gtk ::Button*        pButton = new Gtk ::Button("_Something", true);

无论何时当你想使用备用项(Stock Items)时,一定要确保和其他程序的兼容性(良好),并且可以通过使用图标来改善你的程序的外观。例如:
Gtk ::Button* pButton = new Gtk ::Button(Gtk ::Stock ::OK);
这样在所有的语言中使用标准的文字,加速键以及图标。

Gtk ::Button也时一个容器,因此你可以在其中放任何的窗口对象(widget),例如Gtk ::Image。

示例
这个示例创建了一个有图片和文字标签的按钮。

源代码:
文件: buttons.h
[php]
#ifndef GTKMM_EXAMPLE_BUTTONS_H
#define GTKMM_EXAMPLE_BUTTONS_H

#include <gtkmm/window.h>
#include <gtkmm/button.h>

class Buttons : public Gtk::Window
{
public:
  Buttons();
  virtual ~Buttons();

protected:
  //消息处理:
  virtual void on_button_clicked();

  //子窗口:
  Gtk::Button m_button;
};

#endif //GTKMM_EXAMPLE_BUTTONS_H
[/php]

文件: buttons.cc
[php]
#include "buttons.h"
#include <iostream>

Buttons::Buttons()
{
  m_button.add_pixlabel("info.xpm", "cool button");
   
  set_title("ixmap'd buttons!");
  set_border_width(10);

  m_button.signal_clicked().connect( SigC::slot(*this, &Buttons:n_button_clicked) );
  
  add(m_button);

  show_all_children();
}

Buttons::~Buttons()
{
}

void Buttons:n_button_clicked()
{
  std::cout << "The Button was clicked." << std::endl;
}

[/php]

文件: main.cc
[php]
#include <gtkmm/main.h>
#include "buttons.h"

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  Buttons buttons;
  Gtk::Main::run(buttons); //显示窗口,当它被关闭时返回
  return 0;
}
[/php]
请注意XPMLabelBox可以用来将XPM(XPixMap)和标签放置在任何容器中。

消息

Gtk ::Button有如下的一些消息,但是大多数情况下你只需要处理clicked消息:

pressed
        当按钮被按下时发送。
released
        当按钮被释放时发送。
clicked
        当按钮被按下并且释放后发送。
enter
        当鼠标指针移动到按钮窗口内时发送
leave
        当鼠标指针离开按钮窗口时发送

----------------------------------------------------------------------------
开关按钮

开关按钮和一般的按钮相似,只不过它们被按下或者点击后仍然时激活的(不会自动弹起),直到你再次点击。

要得到ToggleButton的状态你可以用get_active()方法,如果它返回true则说明按钮被按下了。当然,你也可以通过使用set_active()来设置按钮的状态。请注意,如果你这样做了,并且它的状态的确改变了,那么“clicked”消息将会被发送。这正时你想要的。

你可以用toggled()方法来控制它,而不是强迫它开或者关。这中方法改变按钮的状态并且toggled消息会被发送。

Gtk ::ToggleButton可以作为Gtk ::CheckButton和Gtk ::RadioButton的一个很好的基类。
-------------------------------------------------------------------
复选框

Gtk ::CheckButton继承于Gtk ::ToggleButton。两者实际上只是外观不同而已,你可以象使用Gtk ::ToggleButton一样来检查,设置,标记复选框。

示例


源代码

文件: examplewindow.h
[php]
#ifndef GTKMM_EXAMPLE_BUTTONS_H
#define GTKMM_EXAMPLE_BUTTONS_H

#include <gtkmm/window.h>
#include <gtkmm/checkbutton.h>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow();
  virtual ~ExampleWindow();

protected:
  //消息处理:
  virtual void on_button_clicked();

  //子窗口:
  Gtk::CheckButton m_button;
};

#endif //GTKMM_EXAMPLE_BUTTONS_H
[/php]

文件: examplewindow.cc
[php]
#include "examplewindow.h"
#include <iostream>

ExampleWindow::ExampleWindow()
: m_button("something")
{
  set_title("checkbutton example");
  set_border_width(10);

  m_button.signal_clicked().connect( SigC::slot(*this, &ExampleWindow:n_button_clicked) );
  
  add(m_button);

  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}

void ExampleWindow:n_button_clicked()
{
  std::cout << "The Button was clicked: state=" << (m_button.get_active() ? "true" : "false")  << std::endl;
}

[/php]

文件: main.cc
[php]
#include <gtkmm/main.h>
#include "examplewindow.h"

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  ExampleWindow window;
  Gtk::Main::run(window); //显示窗口,当它被关闭时返回

  return 0;
}
[/php]
----------------------------------------------------------
单选按钮

和复选框一样,单选按钮也时派生于Gtk ::ToggleButton,但是它们是成组工作的,并且在一组中同时只能有一个被选中。



有两种方式创建一组单选按钮。第一种方式是先创建按钮,然后再创建组。(这种方式只用到了前两个构造函数)。在下面的代码中,我们创建了一个新的窗口类RadioButtons,然后在其中放置3个单选按钮:
[php]
  class RadioButtons : public Gtk::Window
  {
  public:
      RadioButtons();

  protected:
      Gtk::RadioButton m_rb1, m_rb2, m_rb3;
  };

  RadioButtons::RadioButtons()
    : m_rb1("button1"),
      m_rb2("button2"),
      m_rb3("button3")
  {
      Gtk::RadioButton::Group group = m_rb1.get_group();
      m_rb2.set_group(group);
      m_rb3.set_group(group);
  }
[/php]
我们通过gtkmm将3个单选按钮放置在同一个组内,先使用(某一个按钮的)get_group()来获得要放置的组(目的地),然后在其他按钮中使用set_group()来加入那个组。

请注意你不能只是这样:
m_rb2.set_group(m_rb1.get_group()); //它不会加入到组

因为set_group()改变了group的值,所以group的值是可变的。

第二中方式是先创建一个组,然后向其中加入按钮。看下面的示例:
[php]
class RadioButtons : public Gtk::Window
  {
  public:
      RadioButtons();
  };

  RadioButtons::RadioButtons()
  {
      Gtk::RadioButton::Group group;
      Gtk::RadioButton *m_rb1 = manage( new Gtk::RadioButton(group,"button1"));
      Gtk::RadioButton *m_rb2 = manage( new Gtk::RadioButton(group,"button2"));
      Gtk::RadioButton *m_rb3 = manage( new Gtk::RadioButton(group,"button3"));
  }
[/php]
我们创建了一个组group,它是Gtk ::RadioButton ::Group类型的变量,然后通过在按钮的构造函数中使用它作为参数,使新创建的按钮成为它的一个成员。

方法

单选按钮在创建后缺省为未选中状态,那就意味着当你创建了一组按钮后,它们都是未选中的,别忘记使用set_active()将其中一个选中。

示例

下面的示例说明如何使用单选按钮:


源代码:
文件:radiobuttons.h
[php]
#ifndef GTKMM_EXAMPLE_RADIOBUTTONS_H
#define GTKMM_EXAMPLE_RADIOBUTTONS_H

#include <gtkmm/window.h>
#include <gtkmm/radiobutton.h>
#include <gtkmm/box.h>
#include <gtkmm/separator.h>

class RadioButtons : public Gtk::Window
{
public:
  RadioButtons();
  virtual ~RadioButtons();

protected:
  //消息处理:
  virtual void on_button_clicked();

  //子窗口:
  Gtk::VBox m_Box_Top, m_Box1, m_Box2;
  Gtk::RadioButton m_RadioButton1, m_RadioButton2, m_RadioButton3;
  Gtk::HSeparator m_Separator;
  Gtk::Button m_Button_Close;
};

#endif //GTKMM_EXAMPLE_RADIOBUTTONS_H
[/php]

文件: main.cc
[php]
#include <gtkmm/main.h>
#include "radiobuttons.h"

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  RadioButtons buttons;
  Gtk::Main::run(buttons); //显示窗口,当它被关闭时返回

  return 0;
}
[/php]

文件: radiobuttons.cc
[php]
#include "radiobuttons.h"


RadioButtons::RadioButtons() :
  m_Box1(false, 10),
  m_Box2(false, 10),
  m_RadioButton1("button1"),
  m_RadioButton2("button2"),
  m_RadioButton3("button3"),
  m_Button_Close("close")
{
  set_title("radio buttons");
  set_border_width(0);

  //把m_RadioButton2和m_RadioButton3放在和m_RadioButton1相同的组里
  Gtk::RadioButton::Group group = m_RadioButton1.get_group();
  m_RadioButton2.set_group(group);
  m_RadioButton3.set_group(group);

  add(m_Box_Top);

  //把Box1放在m_Box_Top里:
  m_Box1.set_border_width(10);
  m_Box_Top.pack_start(m_Box1);

  //把单选按钮放在Box1里:
  m_Box1.pack_start(m_RadioButton1);
  m_Box1.pack_start(m_RadioButton2);
  m_Box1.pack_start(m_RadioButton3);
  m_RadioButton2.set_active();

  //加一个分隔符:
  m_Box_Top.pack_start(m_Separator, Gtk:ACK_SHRINK);

  //把Box2放在m_Box_Top里:
  m_Box2.set_border_width(10);
  m_Box_Top.pack_start(m_Box2, Gtk:ACK_SHRINK);

  //把Close按钮放在Box2里:
  m_Box2.pack_start(m_Button_Close);
  m_Button_Close.set_flags(Gtk::CAN_DEFAULT);
  m_Button_Close.grab_default();

  m_Button_Close.signal_clicked().connect( SigC::slot(*this, &RadioButtons:n_button_clicked) );

  show_all_children();
}

RadioButtons::~RadioButtons()
{
}

void RadioButtons:n_button_clicked()
{
  hide(); //关闭程序.
}
[/php]
发表于 2004-3-16 12:29:49 | 显示全部楼层
兄弟们,丁页啊!!
 楼主| 发表于 2004-3-17 09:47:12 | 显示全部楼层
wbusy 翻译的第五章:

第五章        范围控件(Range Widgets)

Gtk ::Scale 和Gtk ::Scrollbar都是从Gtk ::Range派生而来,因此它们又很多相似的功能。它们都有一个滑轨和一个(可以在上面滑动的)滑块(在其他GUI环境中有时候叫指轮(thumbwheel))。用鼠标按住并且拖动滑块可以使它在滑轨内移动,如果在滑轨上点击的话则可以使滑块朝着刚才点击的方向移动,(这时)要么它会移动到你点击的地方,或者仅仅只是移动一定的距离,这取决于使用哪个鼠标键。这和滚动条(scrollbar)的行为很相似。

就象在后面的调整部分要谈到的那样,所有的可调整的窗口都和一个Adjustment(调整)对象相关联。你可以通过使用Adjustment对象提供的方法来间接地改变(与它关联的窗口)的最小值、最大值以及当前值,可以使用get_adjustment()方法来得到这个对象。可调整控件的构造函数(会)自动创建一个adjustment对象(和它相关联),(当然),你也可以给它指定一个已知的adjustment对象,并且这个对象可以和其他的可调整控件共享。详细介绍请参看调整部分。

滚动条控件(ScrollBar Widgets)

这是一些标准的滚动条,它们只应该用于控制其他窗口的滚动,例如一个Gtk ::Entry,或者一个Gtk ::Viewport,然而在大多数情况下使用Gtk ::ScrolledWindow会简单一点。

Gtk ::HScrollbar和Gtk ::VScrollbar分别是水平滚动条和垂直滚动条。

可显示数值的调整控件、刻度条(Scale Widgets)

Gtk ::Scale窗口(或者说滑块)可以让用户在一定范围内直观地调节它的值。例如,你可以用它来调节一副预览图片的放大率,或者控制颜色的亮度,或者指定多少分钟后执行屏保。

和滚动条一样,它也有水平的和垂直的两种-Gtk ::HScale和Gtk ::CScale。它们的构造函数(会)自动创建一个Adjustment对象,并且将它的所有值均设置为0.0。这样做显然没有什么意义,所以如果你想很好地使用它的话应该设置一些参数。

一些有用的方法

默认情况下,有刻度的可调节窗口在滑块的旁边用数字显示当前的值。当然,你可以通过使用set_draw_value()来改变它(显示的值)。

默认情况下,它显示的是精确到小数点后一位的值,那是由Gtk ::Adjustment的值域决定的。你可以使用set_digits()方法来改变它(显示精度)。

另外,通过使用set_value_pos()可以使值显示在相对于滑块不同的地方。

(数据)更新规则

调整窗口的更新规则定义了在用户操作期间的什么时候更新Gtk ::Adjustment的值,并且发送value_changed消息。通过使用set_policy()可以指定的更新规则有:
        Gtk ::UPDATE_CNTINUOUS-这是默认的更新规则。value_changed一直在发送,例如,无论何时,即使滑块只是被移动了一点点(,都会有value_changed消息发送)。
        Gtk ::UPDATE_DISCONTINUOUS-value_changed消息只是在滑块停止了移动并且用户释放了鼠标的时候才发送。
        Gtk ::UPDATE_DELAYED-当用户释放鼠标或者滑块停止移动一小段时间后才发送value_changed消息。

示例

这个示例显示了一个窗口,其中使用了3个关联到同一个Adjustment对象的可调整窗口,还有2个控件用来改变上面几节讨论过的一些参数,所以你可以很清楚地看到那些参数和它们行为方式的关系。

源代码

文件:examplewindow.h
[PHP]
#ifndef GTKMM_EXAMPLE_RANGEWIDGETS_H
#define GTKMM_EXAMPLE_RANGEWIDGETS_H

#include <gtkmm.h>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow();
  virtual ~ExampleWindow();

protected:
  //消息处理:
  virtual void on_checkbutton_toggled();
  virtual void on_menu_position(Gtk:ositionType type);
  virtual void on_menu_policy(Gtk::UpdateType type);
  virtual void on_adjustment1_value_changed();
  virtual void on_adjustment2_value_changed();
  virtual void on_button_quit();

  //子窗口:
  Gtk::VBox m_VBox_Top, m_VBox2, m_VBox_HScale;
  Gtk::HBox m_HBox_Scales, m_HBox_Digits, m_HBox_PageSize;

  Gtk::Adjustment m_adjustment, m_adjustment_digits, m_adjustment_pagesize;

  Gtk::VScale m_VScale;
  Gtk::HScale m_HScale, m_Scale_Digits, m_Scale_PageSize;

  Gtk::HSeparator m_Separator;

  Gtk::CheckButton m_CheckButton;

  Gtk::HScrollbar m_Scrollbar;

  Gtk::Menu m_Menu_Position, m_Menu_Policy;

  Gtk::Button m_Button_Quit;
};

#endif //GTKMM_EXAMPLE_RANGEWIDGETS_H
[/PHP]

文件: labeledoptionmenu.h
[PHP]
#ifndef GTKMM_EXAMPLE_RANGEWIDGETS_LABELEDOPTIONMENU_H
#define GTKMM_EXAMPLE_RANGEWIDGETS_LABELEDOPTIONMENU_H

#include <gtkmm.h>

class LabeledOptionMenu : public Gtk::HBox
{
public:
  LabeledOptionMenu(const Glib::ustring& menu_title, Gtk::Menu& menu,
    bool homogeneous = false, int spacing = 10);

protected:
    Gtk:abel m_label;
    Gtk::OptionMenu m_OptionMenu;
    Gtk::Menu* m_pMenu;
};
#endif //GTKMM_EXAMPLE_RANGEWIDGETS_LABELEDOPTIONMENU_H
[/PHP]

文件: examplewindow.cc
[PHP]
#include "examplewindow.h"
#include "labeledoptionmenu.h"
#include <iostream>

ExampleWindow::ExampleWindow()
:
  m_VBox2(false, 20),
  m_VBox_HScale(false, 10),
  m_HBox_Scales(false, 10),
  m_HBox_Digits(false, 10),
  m_HBox_PageSize(false, 10),

  // 下面的构造函数各参数对应的含义依次为:当前值,最小值,最大值,步进值
  // 页增量,页大小。请注意,页大小的值只是在和滚动条控件关联时才起作用,
  // 你得到的最大值实质上是(最大值-页大小)
  m_adjustment(0.0, 0.0, 101.0, 0.1, 1.0, 1.0),
  m_adjustment_digits(1.0, 0.0, 5.0),
  m_adjustment_pagesize(1.0, 1.0, 101.0),

  m_VScale(m_adjustment),
  m_HScale(m_adjustment),
  m_Scale_Digits(m_adjustment_digits),
  m_Scale_PageSize(m_adjustment_pagesize),

  // 用来控制是否显示当前值的复选框
  m_CheckButton("Display value on scale widgets", 0),

  // 再用一次相同的Adjustment对象
  m_Scrollbar(m_adjustment),
  // 请注意当滚动条移动时,这是怎样使刻度条在一直更新的。

  m_Button_Quit("Quit")
{
  set_title("range controls");

  //VScale:
  m_VScale.set_update_policy(Gtk::UPDATE_CONTINUOUS);
  m_VScale.set_digits(1);
  m_VScale.set_value_pos(Gtk:OS_TOP);
  m_VScale.set_draw_value();

  //水平刻度条控件:
  m_HScale.set_update_policy(Gtk::UPDATE_CONTINUOUS);
  m_HScale.set_digits(1);
  m_HScale.set_value_pos(Gtk:OS_TOP);
  m_HScale.set_draw_value();
  m_HScale.set_size_request(200, 30);

  add(m_VBox_Top);
  m_VBox_Top.pack_start(m_VBox2);
  m_VBox2.set_border_width(10);
  m_VBox2.pack_start(m_HBox_Scales);

  //把垂直刻度条和水平刻度条并列地放在滚动条的上面。.
  m_HBox_Scales.pack_start(m_VScale);
  m_HBox_Scales.pack_start(m_VBox_HScale);

  m_VBox_HScale.pack_start(m_HScale);

  //滚动条:
  m_Scrollbar.set_update_policy(Gtk::UPDATE_CONTINUOUS);
  m_VBox_HScale.pack_start(m_Scrollbar);

  //复选框:
  m_CheckButton.set_active();
  m_CheckButton.signal_toggled().connect( SigC::slot(*this, &ExampleWindow:n_checkbutton_toggled) );
  m_VBox2.pack_start(m_CheckButton);

  //可选菜单:
  {
      using namespace Gtk::Menu_Helpers;

      MenuList& list_vpos = m_Menu_Position.items();
      list_vpos.push_back(
        MenuElem("Top", SigC::bind( SigC::slot(*this, &ExampleWindow:n_menu_position), Gtk:OS_TOP)) );
      list_vpos.push_back(
        MenuElem("Bottom", SigC::bind( SigC::slot(*this, &ExampleWindow:n_menu_position), Gtk:OS_BOTTOM)) );
      list_vpos.push_back(
        MenuElem("Left", SigC::bind( SigC::slot(*this, &ExampleWindow:n_menu_position), Gtk:OS_LEFT)) );
      list_vpos.push_back(
        MenuElem("Right", SigC::bind( SigC::slot(*this, &ExampleWindow:n_menu_position), Gtk:OS_RIGHT)) );

      m_VBox2.pack_start( *Gtk::manage(new LabeledOptionMenu("Scale Value Position:", m_Menu_Position)) );


      MenuList& list_upd = m_Menu_Policy.items();
      list_upd.push_back(
        MenuElem("Continuous", SigC::bind( SigC::slot(*this, &ExampleWindow:n_menu_policy), Gtk::UPDATE_CONTINUOUS)) );
      list_upd.push_back(
        MenuElem("Discontinuous", SigC::bind( SigC::slot(*this, &ExampleWindow:n_menu_policy), Gtk::UPDATE_DISCONTINUOUS)) );
      list_upd.push_back(
        MenuElem("Delayed", SigC::bind( SigC::slot(*this, &ExampleWindow:n_menu_policy), Gtk::UPDATE_DELAYED)) );

      m_VBox2.pack_start( *Gtk::manage(new LabeledOptionMenu("Scale Update Policy:", m_Menu_Policy)) );
  }

  //精确位数:
  m_HBox_Digits.pack_start(*Gtk::manage(new Gtk:abel("Scale Digits:", 0)),  Gtk:ACK_SHRINK);
  m_Scale_Digits.set_digits(0);
  m_adjustment_digits.signal_value_changed().connect( SigC::slot(*this, &ExampleWindow:n_adjustment1_value_changed) );
  m_HBox_Digits.pack_start(m_Scale_Digits);

  //页大小:
  m_HBox_PageSize.pack_start(*Gtk::manage(new Gtk:abel("Scrollbar Page Size:", 0)), Gtk:ACK_SHRINK);
  m_Scale_PageSize.set_digits(0);
  m_adjustment_pagesize.signal_value_changed().connect( SigC::slot(*this, &ExampleWindow:n_adjustment2_value_changed) );
  m_HBox_PageSize.pack_start(m_Scale_PageSize);

  m_VBox2.pack_start(m_HBox_Digits);
  m_VBox2.pack_start(m_HBox_PageSize);
  m_VBox_Top.pack_start(m_Separator, Gtk:ACK_SHRINK);
  m_VBox_Top.pack_start(m_Button_Quit, Gtk::PACK_SHRINK);

  m_Button_Quit.set_flags(Gtk::CAN_DEFAULT);
  m_Button_Quit.grab_default();
  m_Button_Quit.signal_clicked().connect(SigC::slot(&Gtk::Main::quit));
  m_Button_Quit.set_border_width(10);

  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}

void ExampleWindow::on_checkbutton_toggled()
{
    m_VScale.set_draw_value(m_CheckButton.get_active());
    m_HScale.set_draw_value(m_CheckButton.get_active());
}

void ExampleWindow::on_menu_position(Gtk::PositionType postype)
{
    m_VScale.set_value_pos(postype);
    m_HScale.set_value_pos(postype);
}

void ExampleWindow::on_menu_policy(Gtk::UpdateType type)
{
    m_VScale.set_update_policy(type);
    m_HScale.set_update_policy(type);
}

void ExampleWindow::on_adjustment1_value_changed()
{
    double val = m_adjustment_digits.get_value();
    m_VScale.set_digits((int)val);
    m_HScale.set_digits((int)val);
}

void ExampleWindow::on_adjustment2_value_changed()
{
    double val = m_adjustment_pagesize.get_value();
    m_adjustment.set_page_size((int)val);
    m_adjustment.set_page_increment((int)val);

    // 请注意,你不需要发送changed消息,gtkmm已经替你做了。
}

void ExampleWindow::on_button_quit()
{
  hide();
}
[/PHP]

文件: labeledoptionmenu.cc
[PHP]
#include "labeledoptionmenu.h"

LabeledOptionMenu:abeledOptionMenu(const Glib::ustring& menu_title, Gtk::Menu& menu, bool homogeneous, int spacing) :
    Gtk::HBox(homogeneous, spacing),
    m_label(menu_title),
    m_pMenu(&menu)
{
  pack_start(m_label, Gtk::PACK_SHRINK);

  m_OptionMenu.set_menu(*m_pMenu);
  pack_start(m_OptionMenu);
}
[/PHP]

文件: main.cc
[PHP]
#include <gtkmm/main.h>
#include "examplewindow.h"

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  ExampleWindow window;
  Gtk::Main::run(window); //显示窗口,当它被关闭时返回

  return 0;
}
[/PHP]
 楼主| 发表于 2004-3-17 09:51:09 | 显示全部楼层
多谢 kj501 版主帮忙整理格式

以后一定注意
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表