gtkmm : 用 cairo 绘制文本
Posted
技术标签:
【中文标题】gtkmm : 用 cairo 绘制文本【英文标题】:gtkmm : Drawing text with cairo 【发布时间】:2021-08-15 12:54:31 【问题描述】:我想在一个使用 Gtkmm 的应用程序中用 Cairo 绘制一个简单的文本。我想在单击Gtk::FontButton
时(换句话说,当signal_font_set
信号发出时)直接给出字体样式(可以是Pango::FontDescription
或Pango::Context
等等...)以使用Cairo 绘制文本)。在下面的示例中,我有一个Gtk::HeaderBar
,其中包含一个Gtk::FontButton
,它在单击时将Glib::RefPtr<<Pango::Context>>
发送到绘图类。我想要这样的东西:
MyWindow.cpp:
#include <iostream>
#include "MyWindow.h"
MyWindow::MyWindow()
set_default_size(1000, 1000);
set_position(Gtk::WIN_POS_CENTER);
header.set_show_close_button(true);
header.pack_start(fontButton);;
set_titlebar(header);
fontButton.signal_font_set().connect([&]
drawingArea.select_font(fontButton.get_pango_context());
);
scrolledWindow.add(drawingArea);
add(scrolledWindow);
show_all();
MyDrawing.h:
#ifndef DRAWING_H
#define DRAWING_H
#include <gtkmm.h>
#include <cairo/cairo.h>
class MyDrawing : public Gtk::Layout
public:
MyDrawing();
~MyDrawing() override;
void select_font(Glib::RefPtr<Pango::Context> p_pangoContext);
private:
bool draw_text(const Cairo::RefPtr<::Cairo::Context>& p_context);
Glib::RefPtr<Pango::Context> m_pangoContext;
;
#endif // DRAWING_H
和MyDrawing.cpp:
#include <iostream>
#include <utility>
#include "MyDrawing.h"
#include <cairomm/context.h>
#include <cairomm/surface.h>
MyDrawing::MyDrawing()
this->signal_draw().connect(sigc::mem_fun(*this, &MyDrawing::draw_text));
MyDrawing::~MyDrawing() = default;
bool MyDrawing::draw_text(const Cairo::RefPtr<::Cairo::Context> &p_context)
auto layout = create_pango_layout("hello ");
if(m_pangoContext)
layout->set_font_description(m_pangoContext->get_font_description());
else
Pango::FontDescription fontDescription;
layout->set_font_description(fontDescription);
p_context->save();
p_context->set_font_size(30);
p_context->set_source_rgb(0.1, 0.1, 0.1);
p_context->move_to(40, 40);
layout->show_in_cairo_context(p_context);
p_context->restore();
return true;
void MyDrawing::select_font(Glib::RefPtr<Pango::Context> p_pangoContext)
this->m_pangoContext = std::move(p_pangoContext);
queue_draw();
当我手动设置Pango::FontDescription
时:
Pango::FontDescription fontDescription;
fontDescription.set_weight(Pango::WEIGHT_BOLD);
fontDescription.set_style(Pango::STYLE_ITALIC);
layout->set_font_description(fontDescription);
有效:
【问题讨论】:
如果我正确理解您的问题,您是否希望在MyDrawing::draw_text
中设置字体描述?我认为这不是工作代码?
我编辑了帖子。
更清楚了,谢谢!另外,如果有更多代码(请尝试使其下次可重现),我可以在这里重现该问题。
【参考方案1】:
这是一种可行的方法:您可以从Gtk::FontButton::get_font_name
获取字体名称,而不是使用Pango::Context
,然后从中创建Pango::FontDescription
。这是一个显示这一点的最小示例:
#include <iostream>
#include <gtkmm.h>
class MyDrawing : public Gtk::Layout
public:
MyDrawing();
void set_font(const std::string& p_selectedFont);
private:
bool draw_text(const Cairo::RefPtr<::Cairo::Context>& p_context);
std::string m_selectedFont;
Glib::RefPtr<Pango::Layout> m_pangoLayout;
;
MyDrawing::MyDrawing()
signal_draw().connect(sigc::mem_fun(*this, &MyDrawing::draw_text));
m_pangoLayout = Pango::Layout::create(get_pango_context());
m_pangoLayout->set_text(
"This text's appearance should change\n"
"when font description changes."
);
void MyDrawing::set_font(const std::string& p_selectedFont)
// Record the font selected by the user (as a string... Ugh!):
m_selectedFont = p_selectedFont;
std::cout << "Selected font: " << m_selectedFont << std::endl;
// Request a redraw:
queue_draw();
bool MyDrawing::draw_text(const Cairo::RefPtr<::Cairo::Context>& p_context)
// Create a font description from what was selected by the user earlier,
// and set it:
const Pango::FontDescription descriptionm_selectedFont;
m_pangoLayout->set_font_description(description);
p_context->save();
p_context->set_font_size(30);
p_context->set_source_rgb(0.1, 0.1, 0.1);
p_context->move_to(40, 40);
m_pangoLayout->show_in_cairo_context(p_context);
p_context->restore();
return true;
class MyWindow : public Gtk::ApplicationWindow
public:
MyWindow();
private:
Gtk::HeaderBar m_headerBar;
Gtk::FontButton m_fontButton;
MyDrawing m_drawingArea;
;
MyWindow::MyWindow()
m_headerBar.set_show_close_button(true);
m_headerBar.pack_start(m_fontButton);;
set_titlebar(m_headerBar);
m_fontButton.signal_font_set().connect(
[this]()
m_drawingArea.set_font(m_fontButton.get_font_name());
);
add(m_drawingArea);
show_all();
int main(int argc, char *argv[])
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
MyWindow window;
window.show_all();
return app->run(window);
我不是 Pango 专家,所以我不知道是否有更好的方法使用您的初始策略。此外,表示字体名称的字符串似乎需要遵循一些约定。来自Pango::FontDescription::FontDescription(const Glib::ustring& font_name)
(Gtkmm 3.24) 的文档:
font_name 的格式必须为“[FAMILY-LIST] [STYLE-OPTIONS] [SIZE]”, 其中 FAMILY-LIST 是一个以逗号分隔的家庭列表(可选) 以逗号结尾,STYLE_OPTIONS 是一个空格分隔的列表 每个 WORD 描述风格、变体、重量或 拉伸,而 SIZE 是一个十进制数(大小以磅为单位)。任何一个 选项可能不存在。如果 FAMILY-LIST 不存在,则 生成的字体描述的 family_name 字段将是 初始化为 0。如果缺少 STYLE-OPTIONS,则所有样式选项 将设置为默认值。如果缺少 SIZE,则 生成的字体描述将设置为 0。
因此您可能需要自己进行一些测试,以确保这适用于所有字体。就我而言,我测试过的所有 10-15 种字体似乎都可以正常工作。
【讨论】:
以上是关于gtkmm : 用 cairo 绘制文本的主要内容,如果未能解决你的问题,请参考以下文章
如何在 gtkmm DrawingArea 中绘制 poppler 文档