2015-02-24 19 views
1

我想顯示一個消息框,如果正在運行的程序的PID爲有效之前,這是我的呈香代碼:雙的Gtk :: Messadialog退出

Gtk::Main kit (argc, argv); 
Glib::RefPtr<Gtk::Builder> refBuilder = Gtk::Builder::create(); 
try { refBuilder->add_from_file (UI_PATH); } 
catch (const Glib::FileError& ex) { 
    std::cout << "FileError: " << ex.what() << std::endl; 
    return 1; 
} 
catch (const Gtk::BuilderError& ex) { 
    std::cout << "BuilderError: " << ex.what() << std::endl; 
    return 1; 
} 
FormUI * ui = 0; 
refBuilder->get_widget_derived ("window1", ui); 
if (ui) { 
    kit.run (*ui); 
} 
delete ui; 

構造:

signal_delete_event().connect (sigc::mem_fun (*this, &FormUI::on_delete_event)); 

方法:

bool FormUI::on_delete_event (GdkEventAny* event) { 
if (_pid) { 
    bool retState; 
    Gtk::MessageDialog md(*this, Glib::ustring::compose ("<b>%1</b>", _("Warning: youtube-dl in process")), true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true); 
    md.set_title (PACKAGE_STRING); 
    md.set_secondary_text (_("Closing can generate a corrupted file, do you want to continue anyway?")); 
    if (md.run() == Gtk::RESPONSE_YES) { 
     kill (_pid, 0); 
     retState = false; 
    } else { 
     retState = true; 
    } 
    md.hide(); 
    return retState; 
} 
return false; 

}

有了以上所述,如果pid有效,它會按預期顯示消息對話框,但如果我點擊「是」(退出應用程序),它會顯示另一個消息對話框。爲什麼?

+1

如果重命名'on_delete_event()'方法會發生什麼? (如果這樣做,等待答案;它會有解釋,或者你可以嘗試從這個評論的其餘部分推斷它。)並且是''從'Gtk :: Window'派生的'FormUI'?我假設它來自你的'refBuilder-> get_widget_derived()'調用,但我想確定。 – andlabs 2015-02-26 04:23:07

+0

哇,我將刪除處理程序重命名爲cb_on_delete_event,它按預期工作:只有一個messagedialog。是的,FormUI源自Gtk :: Window,它來自構建器。 – Joel 2015-02-26 06:20:19

回答

2

你說FormUI來源於Gtk::WindowGtk::Windowa virtual method on_delete_event(),它自動連接到delete-event信號,不問任何問題。糟糕,你在不知道的情況下實施了虛擬方法!所以,你沒有通過調用

signal_delete_event().connect (sigc::mem_fun (*this, &FormUI::on_delete_event)); 

在不知不覺中連接該信號兩倍,而且由於Gtk::Window::on_delete_event()是虛擬的,兩個連接到您自己的方法。

好吧,爲什麼我們仍然會得到兩個對話框?不返回false意思是關閉窗口?不是真的。

delete-event是一個GDK事件。 GDK事件總是返回一個布爾值:如果值爲falseGDK_EVENT_PROPAGATE),則運行信號連接鏈中的下一個信號處理程序,如果返回值爲trueGDK_EVENT_STOP),則不會運行信號連接鏈中的其他信號。

恰恰如此,如果您不停止delete-event傳播信號連接鏈,窗口就會被銷燬。所以當只有一個處理器連接時,從那個處理器返回false有效地破壞窗口。

但現在你有兩個處理程序連接。第一個將返回false,這將導致第二個運行,並且您將獲得第二個消息對話框。當那個返回false時,你的窗戶被毀壞。

希望能夠解釋這個問題。您可以通過不調用signal_delete_event().connect()或將方法名稱更改爲其他方法來解決此問題。請務必觀看gtkmm文檔,以確保您不會意外地使用自動連接到信號的其他虛擬方法(我不確定爲什麼gtkmm提供了這些虛擬方法;方便嗎?)。並且一定要了解GDK事件如何工作;如果您曾經玩過GDK事件(如處理Gtk::DrawingArea中的輸入),則需要知道這一點。

+0

哦,夥計!感謝您的信息,真的很有幫助...所以我只需要不要在我的課堂中使用相同的虛擬方法名稱。 – Joel 2015-02-26 15:56:02