Круговые зависимости графического интерфейса пользователя C ++ GTKMM - PullRequest
0 голосов
/ 30 октября 2018

Я пытался написать приложение графического интерфейса GTKMM на C ++. В моих предыдущих проектах на Java я начинал с создания так называемых «экранных» объектов, каждый из которых содержал бы макеты и объекты на разных экранах. Итак, я попробовал это и в C ++, я получил эти различные объекты Screen из Gtk::Box, чтобы я мог легко добавить их в Gtk::Notebook.

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

Мне удалось разрешить переключение между экранами, указав каждому экрану указатель на Gtk::Notebook, в котором они находятся, но я наткнулся на препятствие, когда не смог понять, как заставить два экрана взаимодействовать друг с другом (например, фильтровать данные на другом экране).

Общая проблема выглядит следующим образом:

Gui.h:

class Gui {
protected:
    //  Child object pointers.
    Gtk::Notebook *m_screens;
    DbConnector *m_db;

    //  Screen object pointers.
    MainScreen *m_mainScreen;
    FilterScreen *m_filterScreen;
public:
    //  Constructors & destructor.
    Gui();
    virtual ~Gui();
};

Gui.cpp:

Gui::Gui() {
    //  Create application.
    auto app = Gtk::Application::create();

    //  Db connector
    m_db = new DbConnector();

    //  Create & configure window.
    Gtk::Window m_window;
    //  Window configs.....

    //  Create notebook & screen objects.
    m_screens = new Gtk::Notebook();
    m_screens->set_show_tabs(false);
    m_mainScreen = new MainScreen(*m_screens);
    m_filterScreen = new FilterScreen(*m_screens);

    //  Add notebook to window.
    m_window.add(*m_screens);

    //Insert pages.
    m_screens->append_page(*m_mainScreen);
    m_screens->append_page(*m_filterScreen);

    //  Show all children & run app.
    m_window.show_all_children();
    app->run(m_window);
}

MainScreen.h:

class MainScreen : public Gtk::Box {
protected:
    //  Parent notebook pointer.
    Gtk::Notebook* parent;

    //  Child widgets.
    Gtk::Button m_toFilterScreenButton = Gtk::Button("To Filter Screen");

    //  Constructors & desctructor.
    MainScreen(Gtk::Notebook& par);
    virtual ~MainScreen();

    //  Methods.
    void addFilter(std::string filterText);
    void toFilterScreen();
};

MainScreen.cpp:

MainScreen::MainScreen(Gtk::Notebook& par) : parent(&par) {
    //  Build screen.
    //  Packing contents.....

    //  Configure widgets.
    //  Things like widget border width.....

    //  Signal handlers.
    m_toFilterScreenButton.signal_clicked().connect(sigc::mem_fun(*this, &MainScreen::toFilterScreen));
}

void MainScreen::addFilter(std::string filterText) {
    //  Add filter
}

void MainScreen::toFilterScreen() {
    notebook->set_current_screen(pagenum_of_filterscreen);
}

Проблема, с которой я столкнулся сейчас, заключается в том, что когда FilterScreen активен, выбран фильтр, и этот фильтр должен быть применен к MainScreen. FilterScreen не может достичь MainScreen через объект Gui, потому что для этого на экранах должно быть Gui.h, что приведет к циклической зависимости. Попытка извлечь MainScreen из Gtk::Notebook возвращает Widget&, который скажет вам, что Gtk::Widget не имеет функции с именем addFilter(std::string filterText);.

Кто-нибудь знает о шаблоне, который я мог бы использовать, который позволил бы этот тип поведения? Пока что я могу думать только об одном-единственном гигантском классе, который устанавливает экраны, используя функции вместо готовых объектов, что было бы далеко от оптимального ...

1 Ответ

0 голосов
/ 01 ноября 2018

С советом, данным Сэмом Варшавчиком в комментариях, я сделал крошечный пример приложения, которое может работать с несколькими экранами и легко переключаться. Для интересующихся: источник можно найти здесь: ExampleApp

...