绘制图片

有一个方法可以将Gdk::Pixbuf绘制到Cairo::ContextGdk::Pixbuf缓冲区是对像素集合的有效封装,它提供了从文件读取以及各种操纵像素的方式。

最常见的Gdk::Pixbuf创建方法是用Gdk::Pixbuf::create_from_file()Gdk::Pixbuf::create_from_resource(),它们可以将图像文件(例如png文件)读取到pixbuf中用于渲染。

通过使用Gdk::Cairo::set_source_pixbuf()Gdk::Pixbuf设置为开罗上下文的源模式使其可以被渲染。然后使用Cairo::Context::paint()(画整个图像),或者使用Cairo::Context::rectangle()Cairo::Context::fill()(用图像填充整个矩形)。set_source_pixbuf()不是Cairo::Context的成员函数。Cairo::Context是它的第一个参数。

这是一小段将他们结合在一起的代码(请注意,通常你不应该在每次调用绘制信号处理函数的时候都加载一次图片):

void MyArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height)
{
  auto image = Gdk::Pixbuf::create_from_file("myimage.png");
  // Draw the image at 110, 90, except for the outermost 10 pixels.
  Gdk::Cairo::set_source_pixbuf(cr, image, 100, 80);
  cr->rectangle(110, 90, image->get_width()-20, image->get_height()-20);
  cr->fill();
}

16.6.1. 示例

这是一个绘制图像的简单示例程序。该程序从资源文件加载图像。请参阅Gio::Resource和glib-compile-resources小节。使用glib-compile-resources将资源文件编译为C源文件,然后将该源文件与C++代码一起编译链接。例如:

$ glib-compile-resources --target=resources.c --generate-source image.gresource.xml

Figure 16-7绘图区域 - 图像

源代码

File: myarea.h (For use with gtkmm 4)

#ifndef GTKMM_EXAMPLE_MYAREA_H
#define GTKMM_EXAMPLE_MYAREA_H

#include <gtkmm/drawingarea.h>
#include <gdkmm/pixbuf.h>

class MyArea : public Gtk::DrawingArea
{
public:
  MyArea();
  virtual ~MyArea();

protected:
  void on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height);

  Glib::RefPtr<Gdk::Pixbuf> m_image;
};

#endif // GTKMM_EXAMPLE_MYAREA_H

File: main.cc (For use with gtkmm 4)

#include "myarea.h"
#include <gtkmm/application.h>
#include <gtkmm/window.h>

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

protected:
  MyArea m_area;
};

ExampleWindow::ExampleWindow()
{
  set_title("DrawingArea");
  set_default_size(300, 200);
  set_child(m_area);
}

int main(int argc, char** argv)
{
  auto app = Gtk::Application::create("org.gtkmm.example");

  return app->make_window_and_run<ExampleWindow>(argc, argv);
}

File: myarea.cc (For use with gtkmm 4)

#include "myarea.h"
#include <cairomm/context.h>
#include <giomm/resource.h>
#include <gdkmm/general.h> // set_source_pixbuf()
#include <glibmm/fileutils.h>
#include <iostream>

MyArea::MyArea()
{
  try
  {
    // The fractal image has been created by the XaoS program.
    // http://xaos.sourceforge.net
    m_image = Gdk::Pixbuf::create_from_resource("/image/fractal_image.png");
  }
  catch(const Gio::ResourceError& ex)
  {
    std::cerr << "ResourceError: " << ex.what() << std::endl;
  }
  catch(const Gdk::PixbufError& ex)
  {
    std::cerr << "PixbufError: " << ex.what() << std::endl;
  }

  // Show at least a quarter of the image.
  if (m_image)
  {
    set_content_width(m_image->get_width()/2);
    set_content_height(m_image->get_height()/2);
  }

  // Set the draw function.
  set_draw_func(sigc::mem_fun(*this, &MyArea::on_draw));
}

MyArea::~MyArea()
{
}

void MyArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height)
{
  if (!m_image)
    return;

  // Draw the image in the middle of the drawing area, or (if the image is
  // larger than the drawing area) draw the middle part of the image.
  Gdk::Cairo::set_source_pixbuf(cr, m_image,
    (width - m_image->get_width())/2, (height - m_image->get_height())/2);
  cr->paint();
}

File: image.gresource.xml (For use with gtkmm 4)

<?xml version="1.0" encoding="UTF-8"?>
<gresources>
  <gresource prefix="/image">
    <file>fractal_image.png</file>
  </gresource>
</gresources>