正确退出 gtkmm 应用程序

Exit a gtkmm application properly

本文关键字:应用程序 gtkmm 退出      更新时间:2023-10-16

我正在使用 Glade 创建一个 GUI,并且能够正确地将信号连接到它。我正在尝试有一个按钮可以简单地退出应用程序。

文档不太清楚如何做到这一点。在某些论坛上,您应该执行以下操作:

Gtk::Main::quit(); 

这确实退出了我的应用程序,但存在分段错误。显然,我应该直接从我的应用程序中调用 quit((,如下所示:

p_application->quit(); 

但这会在编译时返回我生成的错误:

error: invalid use of member ‘GUI::p_application’ in static member function
Glib::RefPtr<Gtk::Application> p_application;
^
error: from this location
p_application->quit();
^

我使用以下命令创建了应用程序:

p_application = Gtk::Application::create(argc, argv, "org.app.app");

我应该如何进行?

看起来您正在尝试从GUI的静态成员函数访问GUI类的p_application成员。

不能从静态函数访问成员,因为没有实例。将函数更改为非静态函数,或者获取实例并访问该实例上的成员。

警告:我能找到的所有在线文档都是针对 gtkmm-4 的。如果您坚持使用 Ubuntu 版 gtkmm-3.0,请从存储库下载您自己的文档(见下文(。我包含了指向 gtkmm-4 文档的链接,希望它们对您有所帮助;使用风险自负。

这是 gtkmm-3.0 的工作解决方案。编译方式:

g++ helloworld.cc -o main `pkg-config --cflags --libs gtkmm-3.0`

法典:

// In file helloworld.cc
// sigc::mem_fun is the important part:
// it lets you turn a member function into a static one (or something).
// I don't really get it.
// I got most of the code here from https://www.gtk.org/docs/language-bindings/cpp
#include <iostream>
#include <sigc++/sigc++.h>            // Unnecessary, because the gtkmm modules also include mem_fun.
#include <glibmm/refptr.h>            // The wrapper object that Application::create returns.
#include <gtkmm/application.h>        // C++ wrapper for C's gtk_main.
#include <gtkmm/button.h>
#include <gtkmm/window.h>
class HelloWorld : public Gtk::Window
{
public:
HelloWorld(Glib::RefPtr<Gtk::Application>);
protected:
void on_button_clicked();
Gtk::Button m_button;
Glib::RefPtr<Gtk::Application> app;
};

// Constructor for window class. app should be a pointer to the Application instance you made in main.
HelloWorld::HelloWorld(Glib::RefPtr<Gtk::Application> app)
: m_button("Quit this program")     // Sets button label. I have no idea what this syntax is. C++ be whack, yo
{
this->app = app;
// mem_fun does most of the magic. How does it work? idk lol
m_button.signal_clicked().connect(sigc::mem_fun(*this,
&HelloWorld::on_button_clicked));
add(m_button);
m_button.show();
}
void HelloWorld::on_button_clicked()
{
std::cout << "Exiting the program now." << std::endl;
this->app->quit();
std::cout << "Note: Program doesn't actually end until this function finishes." << std::endl;
}
int main (int argc, char *argv[])
{
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
HelloWorld helloworld(app);
return app->run(helloworld);
}

我的想法:我真的不明白吗?

Gtk::Button.signal_clicked()(引用(返回一个Glib::SignalProxy<void()>。SignalProxy (參考( 有模板 <R(T...(>,我认为它描述了可以连接的函数类型——在这种情况下,带有返回类型void()参数的空列表。SignalProxy.connect()返回我将忽略的内容,并接受SlotType&SlotType&&(我不知道有什么区别(,其中SlotTypesigc::slot<R(T...)>,或者在这种情况下sigc::slot<void()>

sigc::slot<R(T...)>(参考(似乎非常基本。它看起来只是一个保存函数的包装器(大概,所以 SignalProxy 可以存储它,以便稍后单击按钮时调用(。到目前为止,这一切都是有道理的。

关于sigc::mem_fun(参考文献(的注释说它返回了一个sigc::mem_functor,这听起来很合理,但mem_functor似乎没有满足SignalProxy.connect()想要的东西:sigc::slotsigc::mem_functor不会相互继承。莫名其妙。我想这里有某种无证类型的胁迫?或?另一个线索是mem_fun显然返回了一个类型decltype(auto)的对象?我试着阅读文档,然后他们开始谈论左值和不带括号的 id 表达式,那时我的眼睛瞪大了。查看旧文档,过去有大约 70 个重载版本的 mem_fun 来做现在一个版本可以做的事情,所以我想decltype正在做它的工作。但关键是,这就是我放弃的地方。

decltype(auto)mem_functorsC++深奥的魔力。mem_funSignalProxy.connect()需要的事情,这就是我所知道的。

引用:

GTKMM-4.0 文档

格利布姆文档

SIGC++ 文档

c<<gtkmm中的gdk文档引用了诸如"GdkEventKey"之类的内容以及标头中的枚举。我找不到这方面的 c++ 参考,或者像"gdkmm"这样的东西。我想也许 gtkmm 只是直接将 C 结构用于事件?

安装文档:我在 Ubuntu 上,20.04.3 LTS。您可以从存储库安装 gtk 3.0 的 html 文档。做sudo apt install libgtkmm-3.0-doc libglibmm-2.4-doc libsigc++-2.0-doc.要找出索引文件的用途,例如 gtkmm,请执行dpkg -L libgtkmm-3.0-doc | grep index。SIGC++有多个索引文件,其中两个是陷阱。我无法弄清楚 GDK 的文档在哪里,可能是因为存储库中没有任何文档。改用在线内容。