2012-07-14 127 views
2

我正在用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

回答

1

我決定爲此創建重載的類。代碼如下:

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