【问题标题】:How to use gtk::DrawingArea?如何使用 gtk::DrawingArea?
【发布时间】:2018-03-21 00:23:33
【问题描述】:

我正在尝试使用 GTK、Cairo 和 Glade 在 Rust 中构建一个 GUI。我想用gtk::DrawingArea 画一个运动场,但我不知道如何使用它。我有这个:

extern crate cairo;
extern crate gtk;

use gtk::*;

fn main() {
    gtk::init().unwrap(); //init gtk before using it

    let glade_src = include_str!("Glade_gui.glade"); //build the glade gui
    let builder = gtk::Builder::new_from_string(glade_src);

    //get widgets from the gui
    let draw_area: gtk::DrawingArea = builder.get_object("zeichenbrett").unwrap();
    let window: gtk::Window = builder.get_object("fenster").unwrap();

    let size = (600, 600); //define the size for the image

    let style_context: gtk::StyleContext = draw_area.get_style_context().unwrap(); //get the style context from the drawing area
    let surface: cairo::ImageSurface =
        cairo::ImageSurface::create(cairo::Format::ARgb32, size.0, size.1).unwrap(); //build a new ImageSurface to draw on
    let context: cairo::Context = cairo::Context::new(&surface); //build a new cairo context from that ImageSurface to draw on

    //just a blue area
    context.set_source_rgb(0.0, 0.0, 1.0);
    context.paint();
    context.stroke();

    gtk::functions::render_background(
        &style_context,
        &context,
        0.0,
        0.0,
        size.0 as f64,
        size.1 as f64,
    ); //here I thought that I drew the context                        cairo::Context to the drawingArea but it seems to do nothing.

    window.show_all();
    gtk::main();
}

它编译并运行,但窗口上没有显示任何比赛场地。

我认为我没有正确使用render_background 函数,但我不知道如何正确使用。

这是Glade_gui.glade 文件:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="fenster">
    <property name="can_focus">False</property>
    <property name="title" translatable="yes">Reise nach Jerusalem</property>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="spacing">5</property>
            <property name="homogeneous">True</property>
            <child>
              <object class="GtkButton" id="links">
                <property name="label" translatable="yes">Left</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="rechts">
                <property name="label" translatable="yes">Right</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="quit">
                <property name="label" translatable="yes">Quit</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">2</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkDrawingArea" id="zeichenbrett">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

【问题讨论】:

  • 您需要在draw 信号中为您的DrawingArea 进行绘图。 This answer 应该给你一个很好的起点。

标签: rust gtk


【解决方案1】:

作为说明,我没有使用 Rust 的经验,所以我将主要使用 C 示例。

您正在尝试在启动gtk::main 之前渲染您的 GUI。实现 GTK+ GUI 的正确方法是添加您的小部件,将它们的 draw 信号(以及任何其他必要的信号)连接到您自己的绘图回调函数,然后运行 ​​gtk::main

以文档中的简单 GtkDrawingArea 示例为例,该示例在 here 中找到。在本例中,g_signal_connect 用于将draw 信号连接到draw_callback 回调函数。这样,当小部件由gtk::main 实际创建时,它会在其上绘制您想要的图像。

您的 draw_callback 函数将获取 Cairo 上下文作为参数。您将在该上下文中完成所有绘图,因此无需创建您自己的绘图。这也在文档中通过在draw_callback 的参数中使用指针cr 进行了演示。

您的所有绘图都需要在draw 回调函数中完成。只要需要更新(包括创建 GtkDrawingArea 小部件),它就会被调用,或者您可以通过发出 queue_draw 信号来强制更新。

即使使用不同的语言,C docs 也会有很大的帮助,尤其是当您选择的语言没有全面的文档时。

此外,创建 GTK+ 应用程序的推荐现代方法是使用 GtkApplication。你可能想调查一下。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    • 1970-01-01
    相关资源
    最近更新 更多