当派生 class 不调用超级 class 的构造函数时,绘制信号不会在 GTKMM 中触发
Draw signal doesn't get fired in GTKMM, when derived class doesn't call a superclass's constructor
DrawingArea.hpp
#ifndef __DRAWINGAREA
#define __DRAWINGAREA
#include <gtkmm.h>
class DrawingArea : public Gtk::DrawingArea
{
public:
bool on_my_draw(const Cairo::RefPtr<Cairo::Context>& cr);
DrawingArea(GtkDrawingArea* &cobject, const Glib::RefPtr<Gtk::Builder>& builder);
};
#endif // __DRAWINGAREA
DrawingArea.cpp
#include "DrawingArea.hpp"
#include <iostream>
DrawingArea::DrawingArea(GtkDrawingArea* &cobject, const Glib::RefPtr<Gtk::Builder>& builder)
{
this->signal_draw().connect(sigc::mem_fun(this, &DrawingArea::on_my_draw));
}
bool DrawingArea::on_my_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
std::cout << "i am here" << std::endl;
}
将其编译到应用程序中后,我测试了 DrawingArea
构造函数确实被触发(我使用 get_widget_derived
将其连接到 Glade,但这在这里不重要) .
我希望在启动应用程序时看到 "I am here"
,或者当它需要重绘 DrawingArea
时看到 "I am here"
,但由于某种原因没有发生。
尽管该区域已经显示,但我尝试在它所属的 window 上启动 show_all_children
,但这没有帮助。
现在尝试添加
到 .hpp:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
然后到 .cpp:
bool DrawingArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
std::cout << "i am here!!!" << std::endl;
}
这没有帮助。
也曾尝试将 false
作为第二个参数传递给 connect()
,但这没有帮助。
覆盖默认处理程序更简单 - on_draw(),如这个简单示例所示:
https://developer.gnome.org/gtkmm-tutorial/stable/sec-cairo-drawing-lines.html.en#cairo-example-lines
这些信号 return bool 通常必须连接 "before" 才能调用额外的信号处理程序:
https://developer.gnome.org/gtkmm-tutorial/stable/sec-xeventsignals.html.en#signal-handler-sequence
这个问题很有趣,与人们预期的完全不同,所以我会 post 我得到的答案。
问题是我需要正确初始化对象。具体来说,我没有调用超类的构造函数。我需要做的:
DrawingArea::DrawingArea(GtkDrawingArea* cobject, const Glib::RefPtr<Gtk::Builder>& builder)
: Gtk::DrawingArea(cobject) // <--- this is a very important bit
{
//...
}
否则不仅信号连接丢失(这是可以理解的,因为处理所需函数调用的整个对象部分都消失了),甚至被覆盖的 on_draw
也停止工作(这是我仍然不明白的地方)。
DrawingArea.hpp
#ifndef __DRAWINGAREA
#define __DRAWINGAREA
#include <gtkmm.h>
class DrawingArea : public Gtk::DrawingArea
{
public:
bool on_my_draw(const Cairo::RefPtr<Cairo::Context>& cr);
DrawingArea(GtkDrawingArea* &cobject, const Glib::RefPtr<Gtk::Builder>& builder);
};
#endif // __DRAWINGAREA
DrawingArea.cpp
#include "DrawingArea.hpp"
#include <iostream>
DrawingArea::DrawingArea(GtkDrawingArea* &cobject, const Glib::RefPtr<Gtk::Builder>& builder)
{
this->signal_draw().connect(sigc::mem_fun(this, &DrawingArea::on_my_draw));
}
bool DrawingArea::on_my_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
std::cout << "i am here" << std::endl;
}
将其编译到应用程序中后,我测试了 DrawingArea
构造函数确实被触发(我使用 get_widget_derived
将其连接到 Glade,但这在这里不重要) .
我希望在启动应用程序时看到 "I am here"
,或者当它需要重绘 DrawingArea
时看到 "I am here"
,但由于某种原因没有发生。
尽管该区域已经显示,但我尝试在它所属的 window 上启动 show_all_children
,但这没有帮助。
现在尝试添加
到 .hpp:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
然后到 .cpp:
bool DrawingArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
std::cout << "i am here!!!" << std::endl;
}
这没有帮助。
也曾尝试将 false
作为第二个参数传递给 connect()
,但这没有帮助。
覆盖默认处理程序更简单 - on_draw(),如这个简单示例所示: https://developer.gnome.org/gtkmm-tutorial/stable/sec-cairo-drawing-lines.html.en#cairo-example-lines
这些信号 return bool 通常必须连接 "before" 才能调用额外的信号处理程序: https://developer.gnome.org/gtkmm-tutorial/stable/sec-xeventsignals.html.en#signal-handler-sequence
这个问题很有趣,与人们预期的完全不同,所以我会 post 我得到的答案。
问题是我需要正确初始化对象。具体来说,我没有调用超类的构造函数。我需要做的:
DrawingArea::DrawingArea(GtkDrawingArea* cobject, const Glib::RefPtr<Gtk::Builder>& builder)
: Gtk::DrawingArea(cobject) // <--- this is a very important bit
{
//...
}
否则不仅信号连接丢失(这是可以理解的,因为处理所需函数调用的整个对象部分都消失了),甚至被覆盖的 on_draw
也停止工作(这是我仍然不明白的地方)。