На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела *nix / gcc / Eclipse / Qt / wxWidgets / GTK+
  • При создании темы ОБЯЗАТЕЛЬНО указывайте версию тулкита / библиотеки / компилятора.
  • Перед тем как задать вопрос, сформулируйте его правильно, чтобы вас могли понять.
  • Нарушение Правил может повлечь наказание со стороны модераторов.


Полезные ссылки:
user posted image Boost по-русски
user posted image Qt по-русски
Модераторы: Majestio
Страницы: (3) [1] 2 3  все  ( Перейти к последнему сообщению )  
> Работа с QTCreator без дизайнера
    Здравствуйте!
    Использую для изучения проект Majestio из темы Работа с QTCreator начинающего. Немного изменил проект, использую FormLayout (чтобы при изменении размеров формы не разъезжались поля для ввода). Добавил также кнопку, чтобы потом проверять логин и пароль (пока с сигналами и слотами не разобрался). Возник следующий вопрос: как только я добавляю третий HLayout - форма почему-то не появляется, а как только убираю - появляется (в проекте строки с 3 лайоутом закоментированы). Это связано со свойствами FormLayout? Проект прикрепил. У меня пока вопросы очень простые, можно будет их задавать в одной теме, чтобы не засорять ветку форума?
    Прикреплённый файлПрикреплённый файлqtTestLayout.zip (2,02 Кбайт, скачиваний: 37)
    Сообщение отредактировано: tumanovalex -
      Да, для такой формы, для красивого выравнивания - можно использовать лайяуты QGridLayout или QFormLayout. Так как на форме у нас вырисовываются две колонки контролов, то QFormLayout - лучший выбор, ибо QGridLayout тут будет избыточен. Честно говоря мне бы не хотелось комментировать твой код, я лучше покажу как правильно делается. Код немного подчистил и добавил реализацию размещений на базе QFormLayout, а заодно и подключил слот для примера:

      dialog.h

      ExpandedWrap disabled
        #ifndef DIALOG_H
        #define DIALOG_H
         
        #include <QtWidgets>
         
        class Dialog : public QDialog {
         
            Q_OBJECT
         
            QLineEdit* nameInput;
            QLineEdit* surnameInput;
            QLineEdit* passwordInput;
            QPushButton* authButton;
         
          public:
            Dialog(QWidget* parent = nullptr);
            ~Dialog();
            void SetupWidgetsForm();
         
          public slots:
            void checkLabels(const QString &text);
         
        };
        #endif // DIALOG_H

      dialog.cpp

      ExpandedWrap disabled
        #include "dialog.h"
         
        Dialog::Dialog(QWidget* parent)
          : QDialog(parent) {
          SetupWidgetsForm();
          connect(nameInput, &QLineEdit::textChanged, this, &Dialog::checkLabels);
          connect(surnameInput, &QLineEdit::textChanged, this, &Dialog::checkLabels);
          connect(passwordInput, &QLineEdit::textChanged, this, &Dialog::checkLabels);
        }
         
        Dialog::~Dialog() {
        }
         
        void Dialog::SetupWidgetsForm() {
          // Создание QFormLayout
          QFormLayout* layout = new QFormLayout();
          // Поля ввода
          nameInput = new QLineEdit();
          surnameInput = new QLineEdit();
          passwordInput = new QLineEdit();
          passwordInput->setEchoMode(QLineEdit::Password);
          // Добавление полей на форму, вернее в макет сперва
          layout->addRow("Имя:", nameInput);
          layout->addRow("Фамилия:", surnameInput);
          layout->addRow("Пароль:", passwordInput);
          // Установка выравнивания меток по правому краю
          layout->setLabelAlignment(Qt::AlignRight);
          // Кнопка Авторизации
          authButton = new QPushButton(" Авторизация ");
          authButton->setEnabled(false);
          // Создание горизонтального макета для кнопки для выравнивания по правому краю
          QHBoxLayout* buttonLayout = new QHBoxLayout();
          buttonLayout->addStretch(); // Добавляем растяжение слева
          buttonLayout->addWidget(authButton); // Добавляем кнопку
          // Добавление горизонтального макета с кнопкой в основной макет
          layout->addRow(buttonLayout);
          setLayout(layout);
          setWindowTitle("Форма входа");
          // Устанавливаем минимальные размеры формы, значение "нуль" означает
          // "высоту формы взять по минимуму", но чтобы все элементы поместились
          // Хотя можно было бы вызвать и просто setMinimumWidth(480);
          setMinimumSize(480,0);
        }
         
        void Dialog::checkLabels([[maybe_unused]] const QString& text) {
          bool checkEmpty = nameInput->text().isEmpty() ||
                            surnameInput->text().isEmpty() ||
                            passwordInput->text().isEmpty();
          authButton->setEnabled(!checkEmpty);
        }


      Изначально кнопка [Авторизация] имеет состояние "не разрешена". В процессе ввода данных в поля ввода вызывается слот Dialog::checkLabels. В нем проверяется заполнение всех полей ввода. И если все заполнены, тогда кнопке авторизации устанавливается состояние "разрешена".
        Спасибо большое за код! Конечно, лучше показывать, как надо, чтобы я мог учиться. Разбирать мой код бессмысленно, пока ничего толкового я изобразить не могу.
          Здравствуйте!
          Хочу попытаться реализовать на QT без дизайнера программу на C#, внешний вид который прикрепил. Иинтерфейс сделан убого, много недостатков, но основные элементы (группу чекбоксов, спинера и др.) хотелось бы иметь в программе на QT).
          Для начала я хотел бы реализовать первую вкладку на QTabWidget. Правильно ли я понял следующее:
          1. На основной форме нужно создать Layout формы. Предполагаю использовать QVBox, поскольку основным элементом интерфейса будет являться QTabWidget. Расширение функциональности программы будет идти путем добавления вкладок.
          2. В какой-то из Layout (предполагаю использовать Grid) включить все элементы этой вкладки.
          3. Создать QTabWidget с нужными параметрами (размеры и др.).
          4. Затем методом addTab(ссылка на Layout с элементами, "Имя ярлыка вкладки") добавить вкладку.
          5. Затем добавить в Layout формы созданный QTabWidget.
          Помогите, пожалуйста, советом и критикой.
          Прикреплённая картинка
          Прикреплённая картинка
            Ну в принципе более менее верно. Будет код - покажи.
              Спасибо за ответ. Как только сделаю - обязательно покажу.
                Решил сначала попробовать сделать QGroupBox:
                ExpandedWrap disabled
                  void Dialog::SetupWidgetsForm()
                  {
                    QHBoxLayout *main_layout = new QHBoxLayout();
                    QGroupBox *grb_chennels = new QGroupBox("Каналы");
                    QVBoxLayout *grb_chennels_layout = new QVBoxLayout();
                    for(int i=0; i < 8; i++)
                    {
                      grb_chennels_layout -> addWidget(new QCheckBox(QString::number(i+1)));
                    }
                    grb_chennels -> setLayout(grb_chennels_layout);
                    main_layout -> addWidget(grb_chennels);
                    setLayout(main_layout);
                    setMinimumSize(480,0);
                  }
                Выводятся чекбоксы в 1 ряд. А как сделать программно массив чекбоксов, чтобы их потом разместить в Grid в 2 ряда? Я попробовал сделать так:
                ExpandedWrap disabled
                    QCheckBox *arr_checkbox = new QCheckBox[16];
                    for(int i=0; i < 16; i++)
                    {
                      arr_checkbox[i] = QCheckBox(QString::number(i+1));
                    }
                получил ошибку
                ExpandedWrap disabled
                  "N:\MyProgramming\qtTestLayout\dialog.cpp:22: error: use of deleted function 'QCheckBox& QCheckBox::operator=(const QCheckBox&)'
                  ..\..\dialog.cpp: In member function 'void Dialog::SetupWidgetsForm()':
                  ..\..\dialog.cpp:22:53: error: use of deleted function 'QCheckBox& QCheckBox::operator=(const QCheckBox&)'
                     22 |     arr_checkbox[i] = QCheckBox(QString::number(i+1));
                Подскажите, пожалуйста, как сделать массив контролов правильно.
                  Ну вот смотри, я набросал тебе макет твоей программы.

                  Прикреплённая картинка
                  Прикреплённая картинка


                  dialog.h

                  ExpandedWrap disabled
                    #ifndef DIALOG_H
                    #define DIALOG_H
                     
                    #include <QtWidgets>
                     
                    class Dialog : public QDialog {
                     
                        Q_OBJECT
                     
                      QTabWidget *TabWidget;
                      QVector<QWidget*> Tabs;
                      QVector<QCheckBox*> Checks;
                     
                      public:
                        Dialog(QWidget* parent = nullptr);
                        ~Dialog();
                        void SetupWidgetsForm();
                     
                     
                    };
                    #endif // DIALOG_H

                  dialog.cpp

                  ExpandedWrap disabled
                    #include "dialog.h"
                     
                    Dialog::Dialog(QWidget* parent)
                      : QDialog(parent) {
                      SetupWidgetsForm();
                    }
                     
                    Dialog::~Dialog() {
                    }
                     
                    void Dialog::SetupWidgetsForm() {
                      setWindowTitle("Такая программка");
                      // Создание макета самой формы и сразу его установка
                      QVBoxLayout* layout = new QVBoxLayout;
                      setLayout(layout);
                      setMinimumSize(640,480);
                      // Инициализирование табов и помещение в макет
                      TabWidget = new QTabWidget;
                      for (auto i=0; i<3; i++) Tabs.push_back(new QWidget);
                      TabWidget->addTab(Tabs[0],"Настройка программы");
                      TabWidget->addTab(Tabs[1],"Графики");
                      TabWidget->addTab(Tabs[2],"Вывод результатов");
                      layout->addWidget(TabWidget);
                      // Заполнение таба "Настройка программы"
                      QVBoxLayout *outerLayout = new QVBoxLayout;
                      Tabs[0]->setLayout(outerLayout);
                      QHBoxLayout *upperLayout = new QHBoxLayout;
                      outerLayout->addLayout(upperLayout);
                      QGroupBox *channels = new QGroupBox("Каналы");
                      upperLayout->addWidget(channels);
                      for (auto i = 0; i < 16; ++i) Checks.push_back(new QCheckBox(QString::number(i+1)));
                      QGridLayout *checkLayout = new QGridLayout;
                      channels->setLayout(checkLayout);
                      for (auto i = 0; i < 16; ++i) checkLayout->addWidget(Checks[i], i % 8, i / 8);
                      QPushButton *filler1 = new QPushButton("Потом");
                      QPushButton *filler2 = new QPushButton("Потом");
                      filler1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
                      filler2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
                      upperLayout->addWidget(filler1);
                      upperLayout->addWidget(filler2);
                      QPushButton *filler3 = new QPushButton("Потом будет заполняться");
                      filler3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
                      outerLayout->addWidget(filler3);
                    }

                  Ну и сразу замечания. Места в макете, которые планируется дальше заполнять, я временно занял кнопками, растянутыми на всю доступную площадь. Когда до этих областей доберешься - вместо вставки кнопки вставляй нужный тебе лайяут, и в него уже добавляй контролы. Что касается чекбоксов - я их поместил в два ряда в QGridLayout. И обрати внимание, что все контролы, которые как-то будут взаимодействовать с пользователем или между собою - нужно объявлять полями класса. Иначе в других методах класса к ним доступа не будет, хотя они будут отображаться и висеть в памяти. Локальные объявки допустимы только для лайяутов. И то, если ты не собираешься в динамике добавлять или удалять контролы.

                  Кстати. Посмотри важное преимущество "ручной" сборки формы. Я однотипные элементы, для удобства, могу собирать в контейнеры (вектора, мапы) и удобно к ним обращаться. В случае же использования дизайнера - каждое поле будет отдельной переменной. Во первых, это загромождает сам класс. А во вторых - если понадобится динамическая перекомпоновка, то используя дизайнер форм, про нее можно смело забыть.
                    Спасибо огромное! Я только сейчас стал понимать, почему не следует использовать дизайнер. Все больше нравится QT. Буду дальше разбираться.
                      При создании интерфейса функция SetupWidgetsForm очень сильно разрастается. А можно ли в QT сделать следующее:
                      - создать в каком-то методе (классе) один элемент интерфейса, например комбобокс;
                      - создать в другом методе (классе) другой элементы интерфейса, например набор спиннеров;
                      - создать набор кнопок для сохранения, загрузки, очистки настроек и т.д.
                      А затем прикрепить их к нужным лайаутам и разместить на форме?
                      Или это мои фантазии и так делать QT не умеет (или это не нужно)? Как сложный интерфейс делают специалисты по QT без использования дизайнера?
                        tumanovalex, "сетап" можно конечно разнести на n-методов. Но я бы не советовал такое делать. Лучше будет делать в одном методе - НО код комментировать. Т.е. просто комментариями визуально разделять "шаги". Это конечно дело вкуса. Если такое не нравится - безусловно можно сделать набор методов, а-ля setupCombo, setupSpin, setupButtons и вызывать их последовательно в конструкторе. Но в этом лично я какого-то профита не вижу.
                          Спасибо за ответ. Понятно.
                            tumanovalex, я обычно разделяю "сетап" контроллов и потом сетап коннектов. Как это делать - дело "вкусовщины"!. Можно просто тупо в конструкторе, можно разносить в методы, это дело - предпочтений. Мой подход "Не плодить сущностей без необходимости". По ссылке выше - "математическая часть" =)
                              Понятно. Интерфейс закончу на следующей неделе. Очень понравилось делать интерфейс без редактора. Большое спасибо за совет делать его без дизайнера!
                                В первом приближении сделал интерфейс вкладки "Настройки программы". Также попробовал получить параметры из этой вкладки. Не смог понять, как получить состояние всех чекбоксов в групбоксе "Каналы". Также хотел посоветоваться по поводу сохранения, загрузки и сбросу настроек. В старой программе на C# я сохранял и загружал файлы в виде сsv файлов, чтобы их можно было редактировать в текстовом редакторе. Очень нужны критика, замечания и предложения по интерфейсу программы, поскольку это мой первый опыт проекта на QT. Проект прикрепил.
                                Прикреплённый файлПрикреплённый файлqtTestLayout.zip (2,93 Кбайт, скачиваний: 29)
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) [1] 2 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0452 ]   [ 23 queries used ]   [ Generated: 24.03.25, 20:27 GMT ]