Arrow
Arrow2. Juli 2018 08:04

Рефакторинг кода

Qt

Добрый день!

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

Есть несколько форм, которые отображаются в главном окне методом 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
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

33
Evgenii Legotckoi
  • 2. Juli 2018 08:20
  • (bearbeitet)

В принципе, повторяющийся код можно переписать на лямбду, потребуется использовать стандарт C++14



void MainWindow::createView(TableForm::Type type, int rowIndex, int id)
{
    auto initForm = [this](auto form) {
        setCentralWidget(form);
        delete mainForm;
        this->prewView = form;

        if (rowIndex > -1) {
            form->setRowIndex(rowIndex);
        }

        connect(form, &CreateUserForm::sygnalBack, this, [this, type]() { setMainView(type); });
        connect(form, &CreateUserForm::sygnalSubmit, this, [this, type]() { setMainView(type); });
    };
	
    switch (type) {
    case TableForm::users:
        userForm = new CreateUserForm(this);
	initForm(userForm);
        break;
    case TableForm::logo:
        logoForm = new CreateLogoForm(this);
	initForm(logoForm);
        break;
     case

/*  ******  Дальше похожий код  ******  */

    default:
        break;
    }
}
Также я рекомендовал бы использовать абстрактную фабрику для создания форм, если можете выделить базовый класс для всех форм (как минимум должен быть QWidget), хотя конечно если вам необходимо использовать именованые поля для каждой своей формы, то возможно, что абстрактная фабрика будет лишней.
    Arrow
    • 2. Juli 2018 08:26
    • (bearbeitet)
    • Die Antwort wurde als Lösung markiert.

    На каждой форме расположены поля ввода и др. элементы связанные с данными в таблицах базы данных. Связь через QDataWidgetMapper. Подходит ли такое под абстрактную фабрику?

      Evgenii Legotckoi
      • 2. Juli 2018 08:28

      Мне это особо ничего не говорит, если честно.

      Но через лямбду вы можете шаблонизировать повторяющиеся куски кода, что позволит как минимум значительно уменьшить количество строчек кода.
        Evgenii Legotckoi
        • 2. Juli 2018 08:30

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

          Arrow
          • 2. Juli 2018 08:32
          • (bearbeitet)
          А можно как-то через лямбду это выразить?

          Или это врядли получится?

          void TableForm::loadDataFromDB()
          {
              // Load data
          
              QStringList headers;
          
              switch (this->viewType) {
                  case TableForm::groups:
                      mainModel = new QSqlRelationalTableModel(this);
                      this->table = "groups";
                      mainModel->setTable(this->table);
          
                      mainModel->setSort(0, Qt::AscendingOrder);
                      mainModel->select();
                      ui->mainTableView->setModel(mainModel);
                      ui->mainTableView->setColumnHidden(0, true); // Hide
          
                      headers << trUtf8("id") << trUtf8("Group name") << trUtf8("Group description");
          
                      // Columns size
                      for (int i = 0; i < ui->mainTableView->horizontalHeader()->count(); i++) {
                          ui->mainTableView->horizontalHeader()->setSectionResizeMode(i, QHeaderView::Stretch);
                          mainModel->setHeaderData(i, Qt::Horizontal, headers.at(i));
                      }
                      break;
          
                   case TableForm::document_family:
                      mainModel = new QSqlRelationalTableModel(this);
                      this->table = "document_family";
                      mainModel->setTable(this->table);
          
                      mainModel->setSort(0, Qt::AscendingOrder);
                      mainModel->select();
                      ui->mainTableView->setModel(mainModel);
          
                      ui->mainTableView->setColumnHidden(0, true);    // Hide column
          
                      // Columns size
                      for (int i = 0; i < ui->mainTableView->horizontalHeader()->count(); i++) {
                          ui->mainTableView->horizontalHeader()->setSectionResizeMode(i, QHeaderView::Stretch);
                      }
                      break;
          
          case TableForm::security_questions:
          mainModel = new QSqlRelationalTableModel(this); this->table = "data_sources"; mainModel->setTable(this->table); mainModel->setSort(0, Qt::AscendingOrder); mainModel->select(); ui->mainTableView->setModel(mainModel); // Select mainModel->setRelation(4, QSqlRelation("function_type", "id", "func_type")); mainModel->setRelation(5, QSqlRelation("direction_type", "id", "direct_type")); ui->mainTableView->setItemDelegate(new QSqlRelationalDelegate(ui->mainTableView)); mainModel->select(); // Columns size for (int i = 0; i < ui->mainTableView->horizontalHeader()->count(); i++) { ui->mainTableView->horizontalHeader()->setSectionResizeMode(i, QHeaderView::Stretch); if (i < 1 || i == 3 || i > 5) ui->mainTableView->setColumnHidden(i, true); // Hide columns } break; default: break; } ui->mainTableView->setSelectionBehavior(QAbstractItemView::SelectRows); ui->mainTableView->setSelectionMode(QAbstractItemView::SingleSelection); ui->mainTableView->setEditTriggers(QAbstractItemView::NoEditTriggers); }
            Arrow
            • 2. Juli 2018 08:39
            Все формы имеют базовый класс QWidget, это можно сделать через абстрактную фабрику, но не уверен с QDataWidgetMapper, там уже нужно детали кода смотреть, как минимум сократите код с помощью лямбды, а там смотрите, нужно ли вам ещё что-то делать, возможно, что вам и этого хватит.

            Спасибо! Попробую покопать в эту сторону, а то форм таких многовато.
              Evgenii Legotckoi
              • 2. Juli 2018 08:40
              • (bearbeitet)

              Ну как минимум эту часть кода можно зашаблонить

              this->table = "groups";
              mainModel->setTable(this->table);
              
              mainModel->setSort(0, Qt::AscendingOrder);
              mainModel->select();
              ui->mainTableView->setModel(mainModel);
                Arrow
                • 2. Juli 2018 09:00
                • (bearbeitet)
                Если я правильно понял, то это должно выглядеть так ( ? ) :

                void TableForm::loadDataFromDB()
                {
                	QStringList headers;
                	
                	this->table = "groups"; // Не совсем понимаю как зашаблонить
                	///this->table = "....";
                	//this->table = ".....";
                	
                	mainModel = new QSqlRelationalTableModel(this);
                	mainModel->setTable(this->table);
                	mainModel->setSort(0, Qt::AscendingOrder);
                        mainModel->select();
                        ui->mainTableView->setModel(mainModel);
                        ui->mainTableView->setColumnHidden(0, true); // Hide
                
                	// Columns size
                        for (int i = 0; i < ui->mainTableView->horizontalHeader()->count(); i++) {
                           ui->mainTableView->horizontalHeader()->setSectionResizeMode(i, QHeaderView::Stretch);
                           mainModel->setHeaderData(i, Qt::Horizontal, headers.at(i));
                        }
                
                	switch (this->viewType) {
                        case TableForm::groups:
                		headers << trUtf8("id") << trUtf8("Group name") << trUtf8("Group description");
                	   break;
                	case TableForm::document_family:
                		headers << ..........;
                	   break;
                	case TableForm::security_questions:
                	        mainModel->setRelation(4, QSqlRelation("function_type", "id", "func_type"));
                                mainModel->setRelation(5, QSqlRelation("direction_type", "id", "direct_type"));
                                ui->mainTableView->setItemDelegate(new QSqlRelationalDelegate(ui->mainTableView));
                                mainModel->select();
                			
                		// Columns size
                               for (int i = 0; i < ui->mainTableView->horizontalHeader()->count(); i++) {
                                 if (i < 1 || i == 3 || i > 5)
                                    ui->mainTableView->setColumnHidden(i, true);    // Hide columns
                               }
                          break;
                			
                	/* ***** */
                			
                	default:
                           break;
                    }
                    	
                    ui->mainTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
                    ui->mainTableView->setSelectionMode(QAbstractItemView::SingleSelection);
                    ui->mainTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
                }

                А как это зашаблонить:
                this->table = "groups";

                Создать их список и потом в зависимости от
                this->viewType

                а выбирать:

                QStringList view;
                
                /***************/
                
                this->table = view.at(/*viewType*/) /* Примерно так */
                  Evgenii Legotckoi
                  • 2. Juli 2018 09:08
                  • (bearbeitet)

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

                    Arrow
                    • 2. Juli 2018 09:19
                    • (bearbeitet)
                    Спасибо! Статью обязательно прочту.

                    Компилятор clang выдал:

                    error: 'auto' not allowed in lambda parameter
                    auto initForm = [this](auto form) {
                                                           ^~~~
                    В CMakeList.txt

                    set (CMAKE_CXX_FLAGS                "-Wall -std=c++14")
                      Evgenii Legotckoi
                      • 2. Juli 2018 09:22

                      Перепишите так

                      auto initForm = [this](auto form)  -> void 
                      {
                          // Some code
                      }

                      Я забыл, что нужно ещё указывать тип возвращаемого значения в данном случае.
                        Arrow
                        • 2. Juli 2018 09:36
                        • (bearbeitet)
                        Ничего не изменилось:

                        error: 'auto' not allowed in lambda parameter
                        auto initForm = [this](auto form)  -> void {
                                                              ^~~~
                        error: variable 'rowIndex' cannot be implicitly captured in a lambda with no capture-default specified
                        form->setRowIndex(rowIndex);    // Edit existing data (current selected row index)
                                                             ^
                        note: candidate function not viable: no known conversion from 'CreateUserForm *' to 'int' for 1st argument
                        auto initForm = [this](auto form)  -> void {
                                                    ^
                          Evgenii Legotckoi
                          • 2. Juli 2018 09:40

                          Так, захватить rowIndex написано в ошибке и что-то с указателем, не уверен, но попробуйте так

                          auto initForm = [this, &rowIndex](auto* form) {
                                  setCentralWidget(form);
                                  delete mainForm;
                                  this->prewView = form;
                          
                                  if (rowIndex > -1) {
                                      form->setRowIndex(rowIndex);
                                  }
                          
                                  connect(form, &CreateUserForm::sygnalBack, this, [this, type]() { setMainView(type); });
                                  connect(form, &CreateUserForm::sygnalSubmit, this, [this, type]() { setMainView(type); });
                              };
                            Evgenii Legotckoi
                            • 2. Juli 2018 09:43

                            И ещё, стандарт в CMake устанавливается так

                            set(CMAKE_CXX_STANDARD 14)
                              Arrow
                              • 2. Juli 2018 09:53
                              • (bearbeitet)
                              Ругался на type добавил получилось такое:

                              auto initForm = [this, &rowIndex, &type](auto form) { ... }

                              Пишет:

                              error: no matching member function for call to 'connect'
                              connect(form, &CreateUserForm::sygnalBack, this, [this, type]() { setMainView(type); });
                              ^~~~~~~

                              note: in instantiation of function template specialization 'MainWindow::createView(TableForm::Type, int, int)::(anonymous class)::operator()<CreateGroupForm *>' requested here
                              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,
                              ^


                              Спасибо добавил:
                              set(CMAKE_CXX_STANDARD 14)
                                Evgenii Legotckoi
                                • 2. Juli 2018 09:59

                                В принципе, если у вас везде один и тот же класс в этих формах используется, то тогда так


                                auto initForm = [this, &rowIndex, &type](CreateUserForm* form) { ... }
                                  Arrow
                                  • 2. Juli 2018 10:15

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

                                    Evgenii Legotckoi
                                    • 2. Juli 2018 10:38

                                    У вас эти куски кода отличаются?

                                            connect(logoForm, &CreateLogoForm::sygnalBack, this, [this, type]() { setMainView(type); });
                                            connect(logoForm, &CreateLogoForm::sygnalSubmit, this, [this, type]() { setMainView(type); });
                                      Arrow
                                      • 2. Juli 2018 10:51

                                      Да, для каждой формы свой

                                        Evgenii Legotckoi
                                        • 2. Juli 2018 10:54
                                        • (bearbeitet)

                                        И что там разного? Название класса или набор сигналов?
                                        Если название класса, то вам следовало бы сделать для всех форм базовый класс, в котором присутствовали бы одинаковые сигналы, если набор сигналов, то это шаблонизировать не получится, имена же сигналов разные.

                                          Arrow
                                          • 2. Juli 2018 11:04

                                          Имена сигналов одинаковые, разные только названия классов.


                                          Можно пример общего класса, а то я не совсем представляю как это сделать с классами Форм в Qt.

                                          class A ....

                                          class B: public A ...







                                            Evgenii Legotckoi
                                            • 2. Juli 2018 14:25

                                            Хорошо, что у меня было время сегодня. Вот материал вам на изучение о наследовании форм от кастомного класса.

                                              Arrow
                                              • 2. Juli 2018 15:02

                                              Огромное спасибо!  Наследование обычное, а вот про добавление информации о родителей в ui файл потомка я не знал.


                                              И такой вопрос,  а если написать это наследование от базового класса и дописать ещё один класс типа:

                                              class Base {
                                              public :
                                              Base (BaseForm *form) : frm(form) {}
                                              ~Base() {delete from; }

                                              private :
                                              BaseForm *frm;
                                              };

                                              И затем использовать:
                                              Base *base = new Base(new FirstForm);
                                              Base *base = new Base(new SecondForm);

                                              Чтобы уйти от лямбды, которая не компилируется. Или это слишком?




















                                                Evgenii Legotckoi
                                                • 3. Juli 2018 03:46
                                                • (bearbeitet)

                                                Смысла не вижу в этом классе Base.

                                                Вы же можете присваивать указатель на потомка указателю базового класса. Этого должно быть достаточно.
                                                BaseForm* form = new FirstForm();
                                                form = new SecondForm();

                                                  Arrow
                                                  • 3. Juli 2018 03:54
                                                  • (bearbeitet)
                                                  Написал базовый класс BaseForm.

                                                  Переписал код так:


                                                      auto initForm = [this, &rowIndex, &type, &id](auto form) {
                                                          setCentralWidget(form);
                                                          delete mainForm;
                                                          this->prewView = form;  // Save current view
                                                  
                                                          if (rowIndex > -1) {
                                                              docFamilyForm->setRowIndex(rowIndex, id);   // Edit existing data (current selected row index)
                                                          }
                                                          else {
                                                              docFamilyForm->setRowIndex(rowIndex, -1);
                                                          }
                                                  
                                                          connect(form, &BaseForm::sygnalBack, this, [this, type]() { setMainView(type); });
                                                          connect(form, &BaseForm::sygnalSubmit, this, [this, type]() { setMainView(type); });
                                                      };
                                                  
                                                      switch (type) {
                                                      case TableForm::groups:
                                                          groupForm = new CreateGroupForm(this);
                                                          initForm(groupForm);
                                                          break;
                                                      case TableForm::users:
                                                          userForm = new CreateUserForm(this);
                                                          initForm(userForm);
                                                          break;
                                                  ..........................
                                                      default:
                                                          break;
                                                      }
                                                  }

                                                  Все скомпилировалось только при попытке открытия одной из форм программа вылетает.

                                                  Код формы (заголовочный файл):

                                                  #include <QWidget>
                                                  
                                                  class BaseForm : public QWidget
                                                  {
                                                  Q_OBJECT
                                                  
                                                  public:
                                                      explicit BaseForm(QWidget *parent = nullptr);
                                                  
                                                      virtual void setRowIndex(int rowIndex, int) = 0;
                                                  
                                                      virtual void submitChanges() = 0;
                                                  
                                                  signals:
                                                      virtual void sygnalBack()= 0;
                                                      virtual void sygnalSubmit()= 0;
                                                  };


                                                  Файл реализации:

                                                  #include "BaseForm.h"

                                                  BaseForm::BaseForm(QWidget *parent) : QWidget(parent)
                                                  {

                                                  }
                                                    Evgenii Legotckoi
                                                    • 3. Juli 2018 04:03

                                                    Сигналы-то зачем виртуальные? Причем чисто виртуальные без реализации. Да и насчёт submitChanges и setRowIndex я что-то сомневаюсь. Нужно ли их было делать чисто виртуальными, да и переопределяете ли вы правильно эти методы в наследниках.

                                                      Arrow
                                                      • 3. Juli 2018 04:13
                                                      Ошибка в этом была :

                                                      if (rowIndex > -1) {
                                                                  docFamilyForm->setRowIndex(rowIndex, id);   // Edit existing data (current selected row index)
                                                              }
                                                              else {
                                                                  docFamilyForm->setRowIndex(rowIndex, -1);
                                                              }

                                                      Должно быть так:


                                                      if (rowIndex > -1) {
                                                                  form->setRowIndex(rowIndex, id);   // Edit existing data (current selected row index)
                                                              }
                                                              else {
                                                                  form->setRowIndex(rowIndex, -1);
                                                              }

                                                      Ошибка копипаста :(


                                                      Теперь все работает (setRowIndex - отрабатывает хорошо), кроме сигналов. Возможно я с ними погорячился или не так описал.

                                                      Код переопределения:


                                                      void setRowIndex(int rowIndex, int id) override;
                                                      
                                                      void submitChanges() override;
                                                      
                                                      signals:
                                                          void sygnalBack() override;
                                                          void sygnalSubmit() override;

                                                        Evgenii Legotckoi
                                                        • 3. Juli 2018 04:18

                                                        Вот это не нужно

                                                        signals:
                                                            void sygnalBack() override;
                                                            void sygnalSubmit() override;

                                                        Сигналы нет смысла переопределять, это объявления методов без реализации. Значит их нужно только объявить в базовом классе.
                                                          Arrow
                                                          • 3. Juli 2018 04:31

                                                          Спасибо большое! вы абсолютно правы, если определить только в базовом классе и не переопределять, то все работает.

                                                            Arrow
                                                            • 3. Juli 2018 04:48
                                                            Можете помочь с этим участком кода. Как его в лямбду переписать.

                                                            void TableForm::loadDataFromDB()
                                                            {
                                                            	QStringList headers;
                                                            	
                                                            	this->table = "groups"; // Не совсем понимаю как зашаблонить
                                                            	///this->table = "....";
                                                            	//this->table = ".....";
                                                            	
                                                            	mainModel = new QSqlRelationalTableModel(this);
                                                            	mainModel->setTable(this->table);
                                                            	mainModel->setSort(0, Qt::AscendingOrder);
                                                                    mainModel->select();
                                                                    ui->mainTableView->setModel(mainModel);
                                                                    ui->mainTableView->setColumnHidden(0, true); // Hide
                                                            
                                                            	// Columns size
                                                                    for (int i = 0; i < ui->mainTableView->horizontalHeader()->count(); i++) {
                                                                       ui->mainTableView->horizontalHeader()->setSectionResizeMode(i, QHeaderView::Stretch);
                                                                       mainModel->setHeaderData(i, Qt::Horizontal, headers.at(i));
                                                                    }
                                                            
                                                            	switch (this->viewType) {
                                                                    case TableForm::groups:
                                                            		headers << trUtf8("id") << trUtf8("Group name") << trUtf8("Group description");
                                                            	   break;
                                                            	case TableForm::document_family:
                                                            		headers << ..........;
                                                            	   break;
                                                            	case TableForm::security_questions:
                                                            	        mainModel->setRelation(4, QSqlRelation("function_type", "id", "func_type"));
                                                                            mainModel->setRelation(5, QSqlRelation("direction_type", "id", "direct_type"));
                                                                            ui->mainTableView->setItemDelegate(new QSqlRelationalDelegate(ui->mainTableView));
                                                                            mainModel->select();
                                                            			
                                                            		// Columns size
                                                                           for (int i = 0; i < ui->mainTableView->horizontalHeader()->count(); i++) {
                                                                             if (i < 1 || i == 3 || i > 5)
                                                                                ui->mainTableView->setColumnHidden(i, true);    // Hide columns
                                                                           }
                                                                      break;
                                                            			
                                                            	/* ***** */
                                                            			
                                                            	default:
                                                                       break;
                                                                }
                                                                	
                                                                ui->mainTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
                                                                ui->mainTableView->setSelectionMode(QAbstractItemView::SingleSelection);
                                                                ui->mainTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
                                                            }
                                                              Evgenii Legotckoi
                                                              • 3. Juli 2018 05:02
                                                              • (bearbeitet)

                                                              Насчёт размеров колонок не знаю, но вот эту часть можно написать так

                                                              auto initTable = [this](const QString& tableName)
                                                              {
                                                                  this->table = tableName;
                                                                  mainModel = new QSqlRelationalTableModel(this);
                                                                  mainModel->setTable(this->table);
                                                                  mainModel->setSort(0, Qt::AscendingOrder);
                                                                  mainModel->select();
                                                                  ui->mainTableView->setModel(mainModel);
                                                                  ui->mainTableView->setColumnHidden(0, true);
                                                              }

                                                              Но я бы ещё посоветовал бы наследоваться от QSqlRelationalTableModel и сделать всю необходимую инициализацию в конструкторе. Можно сделать для каждой таблицы свой наследованный класс и работать как с формами. А размеры заголовков и т.д. настроить в конструкторе наследованного класса.
                                                              Появится несколько дополнительных файлов в проекте, но само по себе решение будет более грамотным.



                                                                Arrow
                                                                • 3. Juli 2018 05:20
                                                                • (bearbeitet)

                                                                Спасибо. Только таблиц 20 шт, возможно это будет слишком для каждой свой класс.

                                                                  Evgenii Legotckoi
                                                                  • 3. Juli 2018 05:22
                                                                  • (bearbeitet)

                                                                  Не обязательно для всех, если есть общий код, который можно выделить, то один класс может подойти для всех таблиц или большиства их них, для остальной части можно написать другой класс или также использовать QSqlRelationalTableModel

                                                                    Kommentare

                                                                    Nur autorisierte Benutzer können Kommentare posten.
                                                                    Bitte Anmelden oder Registrieren
                                                                    Letzte Kommentare
                                                                    A
                                                                    ALO1ZE19. Oktober 2024 18:19
                                                                    Fb3-Dateileser auf Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                                                                    ИМ
                                                                    Игорь Максимов5. Oktober 2024 17:51
                                                                    Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                                                                    d
                                                                    dblas55. Juli 2024 21:02
                                                                    QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                                                    k
                                                                    kmssr9. Februar 2024 05:43
                                                                    Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                                                                    Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                                                                    Jetzt im Forum diskutieren
                                                                    J
                                                                    JacobFib17. Oktober 2024 13:27
                                                                    добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
                                                                    JW
                                                                    Jhon Wick2. Oktober 2024 01:52
                                                                    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…
                                                                    КГ
                                                                    Кирилл Гусарев27. September 2024 19:09
                                                                    Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
                                                                    F
                                                                    Fynjy22. Juli 2024 14:15
                                                                    при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

                                                                    Folgen Sie uns in sozialen Netzwerken