Разделение логики и пользовательского интерфейса

Я разрабатываю приложение с графическим интерфейсом в Qt.

Это мое первое приложение с графическим интерфейсом, и я не очень опытен, и мне все еще приходится бороться с некоторыми более продвинутыми аспектами C++ и Qt framework.

Приложение довольно простое, с главным окном и несколькими диалогами, в которых пользователь настраивает параметры и нажимает кнопку, а программа выполняет (довольно сложный) расчет, выдавая результат где-то в пользовательском интерфейсе.

Теперь у меня проблема. Я помещаю все свои расчетные данные (которые являются статическими и загружаемыми из ресурсов) и логику в отдельный класс. Я создаю экземпляр этого класса и классов пользовательского интерфейса. Теперь проблема в том, как получить доступ к членам класса данных/логики из класса пользовательского интерфейса? Скажем, в классе Logic есть QStringList, и я хочу, чтобы определенный диалог обращался к этому списку и представлял его пользователю, не создавая его копий в памяти?

Я понимаю, что это, вероятно, очень простой вопрос C ++ (Qt даже не имеет отношения к делу), но, эй, не все умеют программировать. Спасибо за любую подсказку или помощь!


person vedran    schedule 13.08.2011    source источник


Ответы (3)


Есть несколько способов сделать это, поэтому ваш вопрос действителен.

  1. Ваш класс GUI может быть получен из вашего логического класса. Нетипичный подход, но это зависит от того, как разработано ваше приложение. Одним из основных недостатков является то, что графический интерфейс должен оставаться в том же потоке, что и логика, если вы не хотите использовать механизмы блокировки в своем логическом классе. Часто требуется, чтобы два объекта выполнялись в отдельных потоках, чтобы тяжелые вычисления не приводили к зависанию графического интерфейса (см. привязка потока QObject).

  2. Ваш класс GUI может содержать указатель на ваш логический класс и/или наоборот. Это также может быть ссылкой для удобства, если ваш логический класс существует до класса GUI и переживает его. Затем вы можете передать ссылку конструктору класса GUI, и вам никогда не придется проверять, действителен ли указатель.

  3. Ваш класс GUI может получить доступ к элементам данных через геттеры/сеттеры или напрямую, если вы хотите сделать их общедоступными, или просто определить свой класс GUI как класс friend для класса Logic. Даже если вы используете геттеры, они могут возвращать константные ссылки, поэтому копирование не требуется. Классы Qt, такие как QStringList, также имеют свой собственный подсчет ссылок, механизм копирования при записи, который позволяет избежать копирования.

  4. Ваш класс GUI может излучать сигналы, а класс Logic может их получать. См. Механизм сигнала/слота Qt. Это очень удобно для таких событий, как кнопка «Начать вычисление». У сигналов есть два преимущества: (а) они могут проходить через потоки, однако, если получатель не является основным циклом, это становится немного сложнее; (b) объекты не должны видеть друг друга (без передачи указателя), вы можете подключать сигналы к слотам в любом месте вашей программы, где вы видите оба объекта одновременно.

Обычно вы будете использовать смесь 2 и 3: Используйте геттеры для чтения данных из класса Logic, который предоставляется пользователю. Используйте сигналы, чтобы спровоцировать действие или манипулировать данными (пользователь делает выбор, класс Logic должен реагировать).

person ypnos    schedule 13.08.2011
comment
Ваш исчерпывающий ответ был очень, очень полезен! Теперь я гораздо лучше понимаю это разделение. Благодарю вас! - person vedran; 13.08.2011
comment
Спасибо! Есть ли среди них лучшие? - person Shiva; 08.06.2015
comment
Обычно я бы предложил использовать систему сигналов/слотов Qt. Однако причина в том, что я все равно буду использовать Qt для графического интерфейса. - person ypnos; 10.06.2015

Существует модель программирования под названием MVC (Модель — Вид — Управление).

Для простых случаев достаточно только Model - View. Модель представляет данные, а представление представляет пользовательский интерфейс.

Класс модели предоставляет некоторые интерфейсы для установки/получения данных. Класс Model обычно ничего не знает о классе View, но обычно может уведомлять класс View об изменении данных (это можно сделать с помощью сигнала/слота в Qt).

Класс View содержит указатель на класс Model и использует интерфейсы, предоставляемые классом Model, для управления данными.

person Bood    schedule 13.08.2011

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

person Andrew White    schedule 13.08.2011