使用g++ main.cc -Wall $(pkg-config gtkmm-3.0 --cflags --libs)
当前功能:
显示带有简单
的窗口SpinButton
我想做什么:
将对
spinbutton
的引用传递给信号处理程序on_spinbutton_change
,以便我可以getAdjustment
并设置格式(如here)
问题:
如何传递对
spinbutton
的引用以及其他可选数据(如简单的整数)?
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(不编译,尝试传递引用):
#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);
}
答案 0 :(得分:1)
我必须承认几年前我从gtkmm切换到Qt。出于好奇,我在cygwin(我在Windows 10上)中安装了gtkmm 3,以准备示例(并了解我对gtkmm的看法有多生锈)。
考虑到OP的尝试,我使用了多个不同的签名,可以用来实现相同的结果。
static gboolean Window::on_spinbtn_output_p(Gtk::SpinButton *pGtkSpinBtn);
相应的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);
相应的connect()
:
_gtkSpinBtn2.signal_output().connect(
sigc::bind(
sigc::ptr_fun(&Window::on_spinbtn_output_r),
sigc::ref(_gtkSpinBtn2)));
gboolean Window::on_spinbtn3_output()
(非静态)
相应的connect()
:
_gtkSpinBtn3.signal_output().connect(
sigc::mem_fun(this, &Window::on_spinbtn3_output));
完整的示例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);
}
经过编译和测试:
$ 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
请记住,OP实际上想修改GtkSpinButton
文本的格式,这是另一个想法。
gtkmm绑定的一个显着扩展(与GTK +相比)是所有GTK +小部件类信号均作为虚拟方法提供的事实。 (我在Qt中非常想念此功能,在Qt中您有 个虚拟方法或信号,但是(IMHO)从来没有两个信号。)实际上,这意味着,在gtkmm中,您总是有选择
当然,除此之外,还可以派生一个小部件类,该小部件类将自己的方法连接到从基类继承的信号。 (在gtkmm 2.4中,在极少数情况下,GTK +信号缺少虚拟方法时,我必须这样做。)
因此,我修改了上面的示例,添加了派生的SpinButton
并更改了信号回调以格式化旋转按钮文本。
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);
}
经过编译和测试:
$ g++ testGtkSpinBtnSig.cc -Wall $(pkg-config gtkmm-3.0 --cflags --libs) -o testGtkSpinBtnSig