将 gtkmm4 FileChooserNative 的 signal_response 连接到函数时出现构建错误
Build error on connection of signal_response of gtkmm4 FileChooserNative to the function
我需要将 FileChooserNative 的 signal_response 连接到该函数,但是当我尝试使用来自 Programming with gtkmm 4 book.
的示例代码时出现错误
当我尝试编译它时(g++、XCLT、macOS Big Sur):
void MyWindow::on_button_browse_clicked(){
auto dialog = Gtk::FileChooserNative::create("Please choose a folder", *this,
Gtk::FileChooser::Action::SELECT_FOLDER, "Choose", "Cancel");
dialog->set_transient_for(*this);
dialog->set_modal(true);
dialog->signal_response().connect(sigc::bind(sigc::mem_fun(*this,
&MyWindow::on_folder_dialog_response), dialog)); // <- error
dialog->show();}
重现问题的最小 .cpp 是 here (pastebin)。
我收到 in instantiation of function template specialization...
错误。完整的构建日志是 here (pastebin).
我的目标是将文件选择对话框的响应发送到 on_folder_dialog_response 函数,然后在终端中显示文件夹路径。
将文件选择对话框的响应连接到函数的正确代码是什么?
你有一个构建错误,因为你提供的额外参数的类型不是 Gtk::FileChooserNative*
,而是 Glib::RefPtr<Gtk::FileChooserNative>
(这是隐藏在 auto
后面的)。所以你应该:
void MyWindow::on_folder_dialog_response(int response_id, Glib::RefPtr<Gtk::FileChooserNative>& dialog)
相反。但是请注意,您的 dialog
实例将在 MyWindow::on_button_browse_clicked
结束时死亡,您将留下空引用。
使用 Gtkmm 3.24(您可能需要针对 Gtkmm 4 进行一些调整),我为您编写了一个小示例:
#include <iostream>
#include <gtkmm.h>
class MainWindow : public Gtk::Window
{
public:
MainWindow();
private:
// Handler for when the user clicks the "Open file chooser dialog..." button
// on the main window. This:
//
// 1. Creates the file chooser.
// 2. Connects the response signal handler, to know about what the user
// will have done with the chooser.
// 3. Shows the file chooser.
//
// So when this is done the user is presented the file chooser.
void OnButtonBrowseClicked()
{
m_fileChooser = Gtk::FileChooserNative::create("Please choose a folder",
*this,
Gtk::FileChooserAction::FILE_CHOOSER_ACTION_SELECT_FOLDER,
"Choose",
"Cancel");
m_fileChooser->signal_response().connect(
[this](int p_responseID)
{
OnBrowseButtonClicked(p_responseID);
}
);
m_fileChooser->show();
} // m_fileChooser will not be destroyed here because it is a member.
// User response handler for the file chooser.
void OnBrowseButtonClicked(int p_responseID)
{
switch(p_responseID)
{
case Gtk::ResponseType::RESPONSE_ACCEPT:
{
std::cout << m_fileChooser->get_file()->get_path() << std::endl;
break;
}
case Gtk::ResponseType::RESPONSE_CANCEL:
{
std::cout << "Cancel clicked : " << p_responseID << std::endl;
break;
}
default:
{
std::cout << "Unexpected button clicked: " << p_responseID << std::endl;
break;
}
}
}
// Keeping a reference on the picker. This allows me to use it whenever I need. I can
// also reset it if I don't need it anymore.
Glib::RefPtr<Gtk::FileChooserNative> m_fileChooser;
Gtk::Button m_browseBtn;
};
MainWindow::MainWindow()
: m_browseBtn{"Open file chooser dialog..."}
{
add(m_browseBtn);
m_browseBtn.signal_clicked().connect(
[this]()
{
OnButtonBrowseClicked();
}
);
}
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
MainWindow window;
window.show_all();
return app->run(window);
}
这基本上是让用户选择一个文件,并将其父目录的路径打印到控制台。
备注:
- 我使用了对文件选择器的引用而不是参数(就像你试过的那样)。这让我无需更改回调的预期原型即可访问它。它还避免了空引用问题。
- 我避免使用老式的
sigc::bind/sigc::mem_fun
,转而使用 lambda 表达式。我发现它不那么晦涩难懂。
我需要将 FileChooserNative 的 signal_response 连接到该函数,但是当我尝试使用来自 Programming with gtkmm 4 book.
的示例代码时出现错误当我尝试编译它时(g++、XCLT、macOS Big Sur):
void MyWindow::on_button_browse_clicked(){
auto dialog = Gtk::FileChooserNative::create("Please choose a folder", *this,
Gtk::FileChooser::Action::SELECT_FOLDER, "Choose", "Cancel");
dialog->set_transient_for(*this);
dialog->set_modal(true);
dialog->signal_response().connect(sigc::bind(sigc::mem_fun(*this,
&MyWindow::on_folder_dialog_response), dialog)); // <- error
dialog->show();}
重现问题的最小 .cpp 是 here (pastebin)。
我收到 in instantiation of function template specialization...
错误。完整的构建日志是 here (pastebin).
我的目标是将文件选择对话框的响应发送到 on_folder_dialog_response 函数,然后在终端中显示文件夹路径。
将文件选择对话框的响应连接到函数的正确代码是什么?
你有一个构建错误,因为你提供的额外参数的类型不是 Gtk::FileChooserNative*
,而是 Glib::RefPtr<Gtk::FileChooserNative>
(这是隐藏在 auto
后面的)。所以你应该:
void MyWindow::on_folder_dialog_response(int response_id, Glib::RefPtr<Gtk::FileChooserNative>& dialog)
相反。但是请注意,您的 dialog
实例将在 MyWindow::on_button_browse_clicked
结束时死亡,您将留下空引用。
使用 Gtkmm 3.24(您可能需要针对 Gtkmm 4 进行一些调整),我为您编写了一个小示例:
#include <iostream>
#include <gtkmm.h>
class MainWindow : public Gtk::Window
{
public:
MainWindow();
private:
// Handler for when the user clicks the "Open file chooser dialog..." button
// on the main window. This:
//
// 1. Creates the file chooser.
// 2. Connects the response signal handler, to know about what the user
// will have done with the chooser.
// 3. Shows the file chooser.
//
// So when this is done the user is presented the file chooser.
void OnButtonBrowseClicked()
{
m_fileChooser = Gtk::FileChooserNative::create("Please choose a folder",
*this,
Gtk::FileChooserAction::FILE_CHOOSER_ACTION_SELECT_FOLDER,
"Choose",
"Cancel");
m_fileChooser->signal_response().connect(
[this](int p_responseID)
{
OnBrowseButtonClicked(p_responseID);
}
);
m_fileChooser->show();
} // m_fileChooser will not be destroyed here because it is a member.
// User response handler for the file chooser.
void OnBrowseButtonClicked(int p_responseID)
{
switch(p_responseID)
{
case Gtk::ResponseType::RESPONSE_ACCEPT:
{
std::cout << m_fileChooser->get_file()->get_path() << std::endl;
break;
}
case Gtk::ResponseType::RESPONSE_CANCEL:
{
std::cout << "Cancel clicked : " << p_responseID << std::endl;
break;
}
default:
{
std::cout << "Unexpected button clicked: " << p_responseID << std::endl;
break;
}
}
}
// Keeping a reference on the picker. This allows me to use it whenever I need. I can
// also reset it if I don't need it anymore.
Glib::RefPtr<Gtk::FileChooserNative> m_fileChooser;
Gtk::Button m_browseBtn;
};
MainWindow::MainWindow()
: m_browseBtn{"Open file chooser dialog..."}
{
add(m_browseBtn);
m_browseBtn.signal_clicked().connect(
[this]()
{
OnButtonBrowseClicked();
}
);
}
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
MainWindow window;
window.show_all();
return app->run(window);
}
这基本上是让用户选择一个文件,并将其父目录的路径打印到控制台。
备注:
- 我使用了对文件选择器的引用而不是参数(就像你试过的那样)。这让我无需更改回调的预期原型即可访问它。它还避免了空引用问题。
- 我避免使用老式的
sigc::bind/sigc::mem_fun
,转而使用 lambda 表达式。我发现它不那么晦涩难懂。