显示没有父窗口的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()免于使用特定于平台的代码。

+0

只是胡乱猜测,因为我不知道是否和如何能freeglut的平台上GTK干扰,但也许这是某种线程问题?如果您使用单独的线程,是否尝试过在单个线程中创建统一的消息循环? – Ivarpoiss 2012-07-17 20:01:36

+0

@Ivarpoiss,我不认为这是可能的;使用freeglut进行事件处理是通过为特定消息类型(键盘,鼠标等)注册回调来完成的 - 您无法直接访问消息循环。 – 2012-07-17 23:10:43

+0

根据文档,这两个API都提供了一个函数来运行一个事件处理循环的迭代。事件处理和回调将像以前一样工作。其他选项是放弃freeglut并完成所有使用GTK管理的窗口。 – Ivarpoiss 2012-07-18 10:10:53

我决定为此创建重载的类。代码如下:

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";