[英]Passing by reference to signal handler
Compile with g++ main.cc -Wall $(pkg-config gtkmm-3.0 --cflags --libs)
用
g++ main.cc -Wall $(pkg-config gtkmm-3.0 --cflags --libs)
What it currently does:它目前的作用:
Displays a window with a simple
SpinButton
显示一个带有简单
SpinButton
的窗口
What I want to do:我想做的事:
Pass in a reference of
spinbutton
to the signal handleron_spinbutton_change
so that I cangetAdjustment
and set the formatting (like here )将
spinbutton
的引用传递给信号处理程序on_spinbutton_change
以便我可以getAdjustment
并设置格式(如此处)
Question:题:
How do I pass in a reference of
spinbutton
and optionally additional data (like a simple integer)?如何传入
spinbutton
的引用和可选的附加数据(如简单的整数)?
main.cc (compiles fine, does not pass reference): main.cc(编译正常,不传递引用):
#include <iostream>
#include <gtkmm/application.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/window.h>
class HelloWorld : public Gtk::Window {
public:
HelloWorld();
virtual ~HelloWorld();
protected:
static gboolean on_spinbutton_change();
Gtk::SpinButton spinbutton;
};
HelloWorld::HelloWorld() {
spinbutton.signal_output().connect(sigc::ptr_fun(&HelloWorld::on_spinbutton_change));
add(spinbutton);
spinbutton.show();
}
HelloWorld::~HelloWorld() {}
gboolean HelloWorld::on_spinbutton_change() {
std::cout << "Hello World" << std::endl;
return true;
}
int main (int argc, char *argv[]) {
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
HelloWorld helloworld;
return app->run(helloworld);
}
main.cc (does not compile, attempt to pass reference): main.cc(不编译,尝试传递引用):
#include <iostream>
#include <gtkmm/application.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/window.h>
class HelloWorld : public Gtk::Window {
public:
HelloWorld();
virtual ~HelloWorld();
protected:
static gboolean on_spinbutton_change(Gtk::SpinButton *spin);
Gtk::SpinButton spinbutton;
};
HelloWorld::HelloWorld() {
spinbutton.signal_output().connect(sigc::bind<Gtk::SpinButton*>(sigc::ptr_fun(&HelloWorld::on_spinbutton_change), spinbutton));
add(spinbutton);
spinbutton.show();
}
HelloWorld::~HelloWorld() {}
gboolean HelloWorld::on_spinbutton_change(Gtk::SpinButton *spin) {
std::cout << "Hello World" << std::endl;
return true;
}
int main (int argc, char *argv[]) {
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
HelloWorld helloworld;
return app->run(helloworld);
}
I must admit that I switched from gtkmm to Qt some years ago.我必须承认,几年前我从 gtkmm 切换到 Qt。 Out of curiosity, I installed gtkmm 3 in my cygwin (I'm on Windows 10) to prepare a sample (and find out how rusty I've become concerning gtkmm).
出于好奇,我在我的cygwin (我在 Windows 10 上)中安装了 gtkmm 3 来准备一个样本(并了解我对 gtkmm 的生疏程度)。
Considering the attempts of OP, I used multiple different signatures which can be used to achieve the same result.考虑到 OP 的尝试,我使用了多个不同的签名,可以用来实现相同的结果。
static gboolean Window::on_spinbtn_output_p(Gtk::SpinButton *pGtkSpinBtn);
the corresponding connect()
:相应的
connect()
:
_gtkSpinBtn1.signal_output().connect( sigc::bind( sigc::ptr_fun(&Window::on_spinbtn_output_p), &_gtkSpinBtn1));
static gboolean Window::on_spinbtn_output_r(Gtk::SpinButton >kSpinBtn);
the corresponding connect()
:相应的
connect()
:
_gtkSpinBtn2.signal_output().connect( sigc::bind( sigc::ptr_fun(&Window::on_spinbtn_output_r), sigc::ref(_gtkSpinBtn2)));
gboolean Window::on_spinbtn3_output()
(non-static) gboolean Window::on_spinbtn3_output()
(非静态)
the corresponding connect()
:相应的
connect()
:
_gtkSpinBtn3.signal_output().connect( sigc::mem_fun(this, &Window::on_spinbtn3_output));
The complete sample testGtkSpinBtnSig.cc
:完整的示例
testGtkSpinBtnSig.cc
:
#include <iostream>
#include <gtkmm/application.h>
#include <gtkmm/box.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/window.h>
class Window: public Gtk::Window {
private:
Gtk::VBox _gtkVBox;
Gtk::SpinButton _gtkSpinBtn1;
Gtk::SpinButton _gtkSpinBtn2;
Gtk::SpinButton _gtkSpinBtn3;
public:
Window();
virtual ~Window() = default;
Window(const Window&) = delete;
Window& operator=(const Window&) = delete;
protected:
static gboolean on_spinbtn_output_p(Gtk::SpinButton *pGtkSpinBtn);
static gboolean on_spinbtn_output_r(Gtk::SpinButton >kSpinBtn);
gboolean on_spinbtn3_output();
};
Window::Window(): Gtk::Window()
{
_gtkSpinBtn1.set_range(0.0, 10.0); _gtkSpinBtn1.set_value(1.0);
_gtkVBox.pack_start(_gtkSpinBtn1);
_gtkSpinBtn2.set_range(0.0, 10.0); _gtkSpinBtn2.set_value(2.0);
_gtkVBox.pack_start(_gtkSpinBtn2);
_gtkSpinBtn3.set_range(0.0, 10.0); _gtkSpinBtn3.set_value(3.0);
_gtkVBox.pack_start(_gtkSpinBtn3);
add(_gtkVBox);
_gtkVBox.show_all();
// install signal handlers
_gtkSpinBtn1.signal_output().connect(
sigc::bind(
sigc::ptr_fun(&Window::on_spinbtn_output_p),
&_gtkSpinBtn1));
_gtkSpinBtn2.signal_output().connect(
sigc::bind(
sigc::ptr_fun(&Window::on_spinbtn_output_r),
sigc::ref(_gtkSpinBtn2)));
_gtkSpinBtn3.signal_output().connect(
sigc::mem_fun(this, &Window::on_spinbtn3_output));
}
gboolean Window::on_spinbtn_output_p(Gtk::SpinButton *pGtkSpinBtn)
{
std::cout << "Window::on_spinbtn_output_p(): pGtkSpinBtn->get_value(): "
<< pGtkSpinBtn->get_value() << '\n';
return true;
}
gboolean Window::on_spinbtn_output_r(Gtk::SpinButton >kSpinBtn)
{
std::cout << "Window::on_spinbtn_output_r(): gtkSpinBtn.get_value(): "
<< gtkSpinBtn.get_value() << '\n';
return true;
}
gboolean Window::on_spinbtn3_output()
{
std::cout << "Window::on_spinbtn_output(): _gtkSpinBtn3.get_value(): "
<< _gtkSpinBtn3.get_value() << '\n';
return true;
}
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "Test SpinButton Signals");
Window gtkWin;
return app->run(gtkWin);
}
Compiled and tested:编译和测试:
$ g++ testGtkSpinBtnSig.cc -Wall $(pkg-config gtkmm-3.0 --cflags --libs) -o testGtkSpinBtnSig
$ ./testGtkSpinBtnSig
Window::on_spinbtn_output_p(): pGtkSpinBtn->get_value(): 1
Window::on_spinbtn_output_r(): gtkSpinBtn.get_value(): 2
Window::on_spinbtn_output(): _gtkSpinBtn3.get_value(): 3
Remembering, that OP actually wants to modify the formatting of the GtkSpinButton
text another idea came into mind.记住,OP 实际上想要修改
GtkSpinButton
文本的格式,这是另一个想法。
A notable extension of the gtkmm binding (in comparison to GTK+) is the fact that all the GTK+ widget class signals are provided as virtual methods. gtkmm 绑定的一个显着扩展(与 GTK+ 相比)是所有 GTK+ 小部件类信号都作为虚拟方法提供。 (I miss this feature very much in Qt where you have either virtual methods or signals but (IMHO) never both of them.) Practically, this means, in gtkmm you always have the option
(我非常想念这个功能在Qt的,你要么虚方法或信号,但(恕我直言)不会同时。)实际上,这意味着,在你的gtkmm随时选择
Beside of this, it is, of course, also possible to derive a widget class which connects a method of its own to a signal inherited from the base class.除此之外,当然,也可以派生一个小部件类,该类将自己的方法连接到从基类继承的信号。 (In gtkmm 2.4, I had to do this in the rare cases where the virtual methods were missing for GTK+ signals.)
(在 gtkmm 2.4 中,我不得不在极少数情况下这样做,即 GTK+ 信号缺少虚拟方法。)
So, I modified the above sample adding a derived SpinButton
and changing the signal callbacks to format the spin button text.因此,我修改了上面的示例,添加了一个派生的
SpinButton
并更改了信号回调以设置SpinButton
文本的格式。
testGtkSpinBtnSig.cc
: testGtkSpinBtnSig.cc
:
#include <sstream>
#include <iomanip>
#include <gtkmm/application.h>
#include <gtkmm/box.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/window.h>
std::string format(double value)
{
std::ostringstream out;
out << std::fixed << std::setw(4) << std::setprecision(1) << std::setfill('0')
<< value;
return out.str();
}
class SpinButton: public Gtk::SpinButton {
public:
SpinButton (double climb_rate = 0.0, guint digits = 0):
Gtk::SpinButton(climb_rate, digits)
{ }
virtual ~SpinButton() = default;
SpinButton(const SpinButton&) = delete;
SpinButton& operator=(const SpinButton&) = delete;
protected:
virtual bool on_output() override;
};
bool SpinButton::on_output()
{
const double value = get_value();
set_text(format(value));
return true;
}
class Window: public Gtk::Window {
private:
Gtk::VBox _gtkVBox;
Gtk::SpinButton _gtkSpinBtn1;
Gtk::SpinButton _gtkSpinBtn2;
Gtk::SpinButton _gtkSpinBtn3;
SpinButton _gtkSpinBtn4; // derived SpinButton
public:
Window();
virtual ~Window() = default;
Window(const Window&) = delete;
Window& operator=(const Window&) = delete;
protected:
static gboolean on_spinbtn_output_p(Gtk::SpinButton *pGtkSpinBtn);
static gboolean on_spinbtn_output_r(Gtk::SpinButton >kSpinBtn);
gboolean on_spinbtn3_output();
};
Window::Window(): Gtk::Window()
{
_gtkSpinBtn1.set_range(0.0, 10.0); _gtkSpinBtn1.set_value(1.0);
_gtkVBox.pack_start(_gtkSpinBtn1);
_gtkSpinBtn2.set_range(0.0, 10.0); _gtkSpinBtn2.set_value(2.0);
_gtkVBox.pack_start(_gtkSpinBtn2);
_gtkSpinBtn3.set_range(0.0, 10.0); _gtkSpinBtn3.set_value(3.0);
_gtkVBox.pack_start(_gtkSpinBtn3);
_gtkSpinBtn4.set_range(0.0, 10.0); _gtkSpinBtn4.set_value(4.0);
_gtkVBox.pack_start(_gtkSpinBtn4);
add(_gtkVBox);
_gtkVBox.show_all();
// install signal handlers
_gtkSpinBtn1.signal_output().connect(
sigc::bind(
sigc::ptr_fun(&Window::on_spinbtn_output_p),
&_gtkSpinBtn1));
_gtkSpinBtn2.signal_output().connect(
sigc::bind(
sigc::ptr_fun(&Window::on_spinbtn_output_r),
sigc::ref(_gtkSpinBtn2)));
_gtkSpinBtn3.signal_output().connect(
sigc::mem_fun(this, &Window::on_spinbtn3_output));
}
gboolean Window::on_spinbtn_output_p(Gtk::SpinButton *pGtkSpinBtn)
{
pGtkSpinBtn->set_text(format(pGtkSpinBtn->get_value()));
return true;
}
gboolean Window::on_spinbtn_output_r(Gtk::SpinButton >kSpinBtn)
{
gtkSpinBtn.set_text(format(gtkSpinBtn.get_value()));
return true;
}
gboolean Window::on_spinbtn3_output()
{
_gtkSpinBtn3.set_text(format(_gtkSpinBtn3.get_value()));
return true;
}
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "Test SpinButton Signals");
Window gtkWin;
return app->run(gtkWin);
}
Compiled and tested:编译和测试:
$ g++ testGtkSpinBtnSig.cc -Wall $(pkg-config gtkmm-3.0 --cflags --libs) -o testGtkSpinBtnSig
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.