2014-12-28 3 views
0

Я пытаюсь использовать wxWidgets для создания окна открытия/сохранения FileDialog в кросс-платформенном виде. Поэтому я рассмотрел примеры в the documentation. Я также хочу создавать автономные окна без родителя, потому что я не использую какой-либо другой экземпляр wxApp/wxWindow в другом месте моей программы.Автономное окно FileDialog с wxWidgets

Кроме того, мне нужно иметь свою собственную функцию main, поэтому я не хочу использовать макрос, такой как IMPLEMENT_APP. Я пытался следовать указаниям here, и придумал следующую минимальную программу:

#include <wx/wx.h> 
#include <string> 
#include <iostream> 

std::string openFile() { 
    wxFileDialog openFileDialog(NULL, _("Open XYZ file"), "", "", 
     "XYZ files (*.xyz)|*.xyz", wxFD_OPEN|wxFD_FILE_MUST_EXIST); 

    if (openFileDialog.Show() == wxID_CANCEL) 
     return ""; // the user changed idea... 

    // proceed loading the file chosen by the user; 
    return "something"; 
} 

int main(int argc, char *argv[]) { 
    std::cout << wxEntryStart(argc, argv) << std::endl; 
    std::string s = openFile(); 
    wxEntryCleanup(); 
} 

А вот CMakeLists.txt я компилировать код:

CMake_Minimum_Required(VERSION 2.8.11) 
Project(test) 

Find_Package(wxWidgets REQUIRED) 
Include(${wxWidgets_USE_FILE}) 

Add_Executable(test main.cpp) 
Target_Link_Libraries(test ${wxWidgets_LIBRARIES}) 

Тем не менее, когда я запустите эту программу, я получаю Ошибка сегментации, несмотря на то, что wxEntryStart возвращает true, и я понятия не имею, откуда эта проблема. Любой отзыв?

+0

Начните с создания отладочной версии и запустите в отладчике, чтобы увидеть * где * произошел сбой. –

+0

Он больше не разбивается, если я предшествую вызову 'wxEntryStart' линией, содержащей' wxApp :: SetInstance (новый wxApp()); '. Однако, когда я запускаю программу, окно не запрашивается, а строка 'openFileDialog.Show()' немедленно возвращается ('openFile' возвращает' 'что-то"). – skuld

ответ

0

Я бы не был так смел с удалением кода инициализации wx. Он может работать сегодня, но в следующей версии, кто знает ...

Это то, что я использую:

class MyApp : public wxApp { }; 
wxIMPLEMENT_APP_NO_MAIN(MyApp); 

int main() 
{ 
    wxDISABLE_DEBUG_SUPPORT(); 
    int dummy = 0; 
    if(!wxEntryStart(dummy, static_cast<wxChar**>(nullptr))) 
     return 1; 
    auto onx1 = on_exit([]{ wxEntryCleanup(); }); //using RAII for cleanup 

    //Other initialization, create main window, show it. 

    wxGetApp().OnRun(); //This starts the event loop. 
    //In your case, it looks like ShowModal's event loop is enough, 
    //so you don't need this. 
} 

Я думаю, что эти макросы, некрасиво, как они, обеспечивают гораздо лучшую изоляцию от будущих изменений в коде инициализации библиотеки.

+0

Нужно ли нам wxDECLARE_APP, если мы используем wxIMPLEMENT_APP_NO_MAIN в том же файле? Можем ли мы использовать wxIMPLEMENT_APP_NO_MAIN (wxApp) и не объявлять наш собственный класс дочерних приложений? – skuld

+0

@ skuld Вы правы, 'wxDECLARE_APP' только объявляет' wxGetApp() ', который также определен в другом макросе. Я думаю, он также должен работать с wxApp, но я предпочитаю держать вещи как можно ближе к «официальному» способу делать все возможное. Как только я принял пару уродливых макросов в файле, еще одно пустое определение класса не имеет большого значения. – bogdan

+0

Я удалю 'wxDECLARE_APP()' из образца кода, в интересах будущих читателей. – bogdan

0

Хорошо, после некоторого вождения здесь приведен пример кода, который работает для меня. Комментарии приветствуются на том, что было бы лучшим опытом. То, что я сделал, это сохранить ShowModal() вместо Show() в функции openFile. Я также создал экземпляр singleton wxApp. Окончательный код здесь:

#include <wx/wx.h> 
#include <string> 
#include <iostream> 

std::string openFile() { 
    wxFileDialog openFileDialog(NULL, _("Open XYZ file"), "", "", 
     "XYZ files (*.xyz)|*.xyz", wxFD_OPEN|wxFD_FILE_MUST_EXIST); 

    if (openFileDialog.ShowModal() == wxID_CANCEL) 
     return ""; // the user changed idea... 

    // proceed loading the file chosen by the user; 
    return "something"; 
} 

int main(int argc, char *argv[]) { 
    wxApp::SetInstance(new wxApp()); 
    wxEntryStart(argc, argv); 
    std::string s = openFile(); 
    wxEntryCleanup(); 
} 

Не уверен, что это полностью герметичен, так как valgrind кажется, жалуется немного после выхода. Любой совет о том, могу ли я также поместить wxEntryStart() в функцию openFile(), приветствуется (я уверен, что это единственное место, где используется wxWidgets lib, и я хочу, чтобы API был как можно более простым).

+1

Не зная, что функция wxWidgets, вероятно, нуждается в запуске цикла сообщений, потому что 'ShowModal' содержит собственный цикл сообщений для собственного окна. –

Смежные вопросы