显示没有父窗口的Gtk :: FileChooserDialog
问题描述:
我正在用OpenGL GUI编写应用程序。在Windows上,我使用GetOpenFilename
来允许用户选择文件。显示没有父窗口的Gtk :: FileChooserDialog
我试图使用Gtk::FileChooserDialog
(跟在this tutorial之后)在Linux for Gtk上实现类似的功能。我试图让函数签名用于Windows和Linux一样的,所以我修改的例子是这样的:
std::string browseFile(std::string filetypes)
{
Gtk::Main kit(false);
Gtk::FileChooserDialog dialog("Please choose a file",
Gtk::FILE_CHOOSER_ACTION_OPEN);
// dialog.set_transient_for(kit.instance());
//Add response buttons the the dialog:
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
//Add filters, so that only certain file types can be selected:
Glib::RefPtr<Gtk::FileFilter> filter_any = Gtk::FileFilter::create();
filter_any->set_name("Any files");
filter_any->add_pattern("*");
dialog.add_filter(filter_any);
//Show the dialog and wait for a user response:
int result = dialog.run();
//Handle the response:
switch(result)
{
case(Gtk::RESPONSE_OK):
{
std::cout << "Open clicked." << std::endl;
//Notice that this is a std::string, not a Glib::ustring.
std::string filename = dialog.get_filename();
std::cout << "File selected: " << filename << std::endl;
return filename;
}
case(Gtk::RESPONSE_CANCEL): { std::cout << "Cancel clicked." << std::endl; break; }
default: { std::cout << "Unexpected button clicked." << std::endl; break; }
}
return std::string("");
}
的主要区别是,我消除了set_transient_for
位,因为我的主窗口ISN”由Gtk管理(它由freeglut创建)。
问题:选择文件后,对话框会冻结。我的应用程序继续运行,我可以处理选定的文件,它只是冻结的对话框。
如何在选择文件后终止对话框?我试过dialog.hide()
,但它似乎没有任何效果。我还试图将Gtk特定的代码包含到此函数中,使int main()
免于使用特定于平台的代码。
答
我决定为此创建重载的类。代码如下:
class FileChooser : public Gtk::FileChooserDialog {
public:
static std::string getFileName() {
FileChooser dialog("Select file", Gtk::FILE_CHOOSER_ACTION_OPEN);
kit.run(dialog);
std::string ret = dialog.chosenFile;
return ret;
}
protected:
static Gtk::Main kit;
std::string chosenFile;
FileChooser(const Glib::ustring& title, Gtk::FileChooserAction action = Gtk::FILE_CHOOSER_ACTION_OPEN) :
Gtk::FileChooserDialog(title, action) {
chosenFile = std::string("");
add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
signal_response().connect(sigc::mem_fun(*this,
&FileChooser::on_my_response));
}
void on_my_response(int response_id) {
chosenFile = get_filename();
hide();
}
};
Gtk::Main FileChooser::kit(false);
您可以使用它像这样:
std::cout << "File: " << FileChooser::getFileName() << "\n";
只是胡乱猜测,因为我不知道是否和如何能freeglut的平台上GTK干扰,但也许这是某种线程问题?如果您使用单独的线程,是否尝试过在单个线程中创建统一的消息循环? – Ivarpoiss 2012-07-17 20:01:36
@Ivarpoiss,我不认为这是可能的;使用freeglut进行事件处理是通过为特定消息类型(键盘,鼠标等)注册回调来完成的 - 您无法直接访问消息循环。 – 2012-07-17 23:10:43
根据文档,这两个API都提供了一个函数来运行一个事件处理循环的迭代。事件处理和回调将像以前一样工作。其他选项是放弃freeglut并完成所有使用GTK管理的窗口。 – Ivarpoiss 2012-07-18 10:10:53