Arrow02 липня 2018 р. 08:04
Рефакторинг кода
Добрый день!
Подскажите, пожалуйста, как можно в ниже приведенном случае уменьшить количество практически одинакового повторяющегося кода.
Смотрел в сторону шаблонов проектирования или возможно это можно сделать по другому, а может просто я намудрил. Не могу определиться какое решение в этом случае будет правильным.
Есть несколько форм, которые отображаются в главном окне методом setCentralWidget() в зависимости от выбранного пользователем пункта меню (элементы управления на всех разные).
Изначально на главной форме отображается главное представление ( setCentralWidget() ) с разными данными ( таблица ), при нажатии кнопки создать отображается новая форма в зависимости от данных отображаемых в таблице.
Код функции:
void MainWindow::createView(TableForm::Type type, int rowIndex, int id) { switch (type) { case TableForm::users: userForm = new CreateUserForm(this); setCentralWidget(userForm); delete mainForm; this->prewView = userForm; if (rowIndex > -1) { userForm->setRowIndex(rowIndex); } connect(userForm, &CreateUserForm::sygnalBack, this, [this, type]() { setMainView(type); }); connect(userForm, &CreateUserForm::sygnalSubmit, this, [this, type]() { setMainView(type); }); break; case TableForm::logo: logoForm = new CreateLogoForm(this); setCentralWidget(logoForm); delete mainForm; this->prewView = logoForm; if (rowIndex > -1) { userForm->setRowIndex(rowIndex); } connect(logoForm, &CreateLogoForm::sygnalBack, this, [this, type]() { setMainView(type); }); connect(logoForm, &CreateLogoForm::sygnalSubmit, this, [this, type]() { setMainView(type); }); break; case /* ****** Дальше похожий код ****** */ default: break; } }
***********
enum Type {
none = 0,
users,
logo,
/* и т.д. */
};
***************
// Форма основного представления
connect(mainForm, &TableForm::createData, this, &MainWindow::createView);
// Главная форма
connect(ui->createButton, &QToolButton::clicked, this, [this] {
emit createData(this->viewType); // Create new data
});
// Объявления в разных формах
void createData(Type type, int row=-1, int id=-1);
void createView(TableForm::Type type, int rowIndex, int id);
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.Вам це подобається? Поділіться в соціальних мережах!
sf
- sdfsdfkp fgskpgokspdog
- 14 жовтня 2024 р. 15:09
C++ - Тест 004. Указатели, Массивы и Циклы
- Результат:90бали,
- Рейтинг балів8
МВ
- Максим Васильев
- 02 жовтня 2024 р. 04:14
Qt - Тест 001. Сигналы и слоты
- Результат:68бали,
- Рейтинг балів-1
ЛС
- Лев Семенов
- 30 вересня 2024 р. 11:04
C++ - Тест 001. Первая программа и типы данных
- Результат:53бали,
- Рейтинг балів-4
Останні коментарі
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
Игорь Максимов05 жовтня 2024 р. 07:51
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Анатолий Кононенко05 лютого 2024 р. 01:50
Тепер обговоріть на форумі
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
ИМ
Реализация навигации по разделам Спасибо Евгений!
Игорь Максимов03 жовтня 2024 р. 04:05
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
Кирилл Гусарев27 вересня 2024 р. 09:09
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
В принципе, повторяющийся код можно переписать на лямбду, потребуется использовать стандарт C++14
На каждой форме расположены поля ввода и др. элементы связанные с данными в таблицах базы данных. Связь через QDataWidgetMapper. Подходит ли такое под абстрактную фабрику?
Мне это особо ничего не говорит, если честно.
Все формы имеют базовый класс QWidget, это можно сделать через абстрактную фабрику, но не уверен с QDataWidgetMapper, там уже нужно детали кода смотреть, как минимум сократите код с помощью лямбды, а там смотрите, нужно ли вам ещё что-то делать, возможно, что вам и этого хватит.
Ну как минимум эту часть кода можно зашаблонить
Почитайте о лямбда функциях . В плане того, какая у них структура. Идею вы поняли правильно, но саму лямду вы не реализовали.
Позже напишу пример, сейчас немного некогда.
auto initForm = [this](auto form) {
^~~~
Перепишите так
Я забыл, что нужно ещё указывать тип возвращаемого значения в данном случае.
auto initForm = [this](auto form) -> void {
^~~~
form->setRowIndex(rowIndex); // Edit existing data (current selected row index)
^
auto initForm = [this](auto form) -> void {
^
Так, захватить rowIndex написано в ошибке и что-то с указателем, не уверен, но попробуйте так
И ещё, стандарт в CMake устанавливается так
connect(form, &CreateUserForm::sygnalBack, this, [this, type]() { setMainView(type); });
initForm(groupForm);
^
C:/msys64/mingw64/include/QtCore/qobject.h:314:13: note: candidate function [with Func1 = void (CreateUserForm::*)(), Func2 = (lambda at mainwindow.cpp:157:58)] not viable: no known conversion from 'CreateGroupForm *' to 'const typename QtPrivate::FunctionPointer<void (CreateUserForm::*)()>::Object *' (aka 'const CreateUserForm *') for 1st argument
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
^
В принципе, если у вас везде один и тот же класс в этих формах используется, то тогда так
Классов несколько, ошибки однотипные, поэтому скопировал одну.
У вас эти куски кода отличаются?
Да, для каждой формы свой
И что там разного? Название класса или набор сигналов?
Если название класса, то вам следовало бы сделать для всех форм базовый класс, в котором присутствовали бы одинаковые сигналы, если набор сигналов, то это шаблонизировать не получится, имена же сигналов разные.
Имена сигналов одинаковые, разные только названия классов.
class A ....
Хорошо, что у меня было время сегодня. Вот материал вам на изучение о наследовании форм от кастомного класса.
Огромное спасибо! Наследование обычное, а вот про добавление информации о родителей в ui файл потомка я не знал.
Смысла не вижу в этом классе Base.
Сигналы-то зачем виртуальные? Причем чисто виртуальные без реализации. Да и насчёт submitChanges и setRowIndex я что-то сомневаюсь. Нужно ли их было делать чисто виртуальными, да и переопределяете ли вы правильно эти методы в наследниках.
Вот это не нужно
Сигналы нет смысла переопределять, это объявления методов без реализации. Значит их нужно только объявить в базовом классе.
Спасибо большое! вы абсолютно правы, если определить только в базовом классе и не переопределять, то все работает.
Насчёт размеров колонок не знаю, но вот эту часть можно написать так
Но я бы ещё посоветовал бы наследоваться от QSqlRelationalTableModel и сделать всю необходимую инициализацию в конструкторе. Можно сделать для каждой таблицы свой наследованный класс и работать как с формами. А размеры заголовков и т.д. настроить в конструкторе наследованного класса.
Спасибо. Только таблиц 20 шт, возможно это будет слишком для каждой свой класс.
Не обязательно для всех, если есть общий код, который можно выделить, то один класс может подойти для всех таблиц или большиства их них, для остальной части можно написать другой класс или также использовать QSqlRelationalTableModel