
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.97.9.171] |
![]() |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
![]() |
|
|
Здравствуйте!
Использую для изучения проект Majestio из темы Работа с QTCreator начинающего. Немного изменил проект, использую FormLayout (чтобы при изменении размеров формы не разъезжались поля для ввода). Добавил также кнопку, чтобы потом проверять логин и пароль (пока с сигналами и слотами не разобрался). Возник следующий вопрос: как только я добавляю третий HLayout - форма почему-то не появляется, а как только убираю - появляется (в проекте строки с 3 лайоутом закоментированы). Это связано со свойствами FormLayout? Проект прикрепил. У меня пока вопросы очень простые, можно будет их задавать в одной теме, чтобы не засорять ветку форума? Прикреплённый файл ![]() |
Сообщ.
#2
,
|
|
|
Да, для такой формы, для красивого выравнивания - можно использовать лайяуты QGridLayout или QFormLayout. Так как на форме у нас вырисовываются две колонки контролов, то QFormLayout - лучший выбор, ибо QGridLayout тут будет избыточен. Честно говоря мне бы не хотелось комментировать твой код, я лучше покажу как правильно делается. Код немного подчистил и добавил реализацию размещений на базе QFormLayout, а заодно и подключил слот для примера:
dialog.h ![]() ![]() #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 ![]() ![]() #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. В нем проверяется заполнение всех полей ввода. И если все заполнены, тогда кнопке авторизации устанавливается состояние "разрешена". |
Сообщ.
#3
,
|
|
|
Спасибо большое за код! Конечно, лучше показывать, как надо, чтобы я мог учиться. Разбирать мой код бессмысленно, пока ничего толкового я изобразить не могу.
|
Сообщ.
#4
,
|
|
|
Здравствуйте!
Хочу попытаться реализовать на QT без дизайнера программу на C#, внешний вид который прикрепил. Иинтерфейс сделан убого, много недостатков, но основные элементы (группу чекбоксов, спинера и др.) хотелось бы иметь в программе на QT). Для начала я хотел бы реализовать первую вкладку на QTabWidget. Правильно ли я понял следующее: 1. На основной форме нужно создать Layout формы. Предполагаю использовать QVBox, поскольку основным элементом интерфейса будет являться QTabWidget. Расширение функциональности программы будет идти путем добавления вкладок. 2. В какой-то из Layout (предполагаю использовать Grid) включить все элементы этой вкладки. 3. Создать QTabWidget с нужными параметрами (размеры и др.). 4. Затем методом addTab(ссылка на Layout с элементами, "Имя ярлыка вкладки") добавить вкладку. 5. Затем добавить в Layout формы созданный QTabWidget. Помогите, пожалуйста, советом и критикой. Прикреплённая картинка
|
Сообщ.
#5
,
|
|
|
Ну в принципе более менее верно. Будет код - покажи.
|
Сообщ.
#6
,
|
|
|
Спасибо за ответ. Как только сделаю - обязательно покажу.
|
Сообщ.
#7
,
|
|
|
Решил сначала попробовать сделать QGroupBox:
![]() ![]() 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); } ![]() ![]() QCheckBox *arr_checkbox = new QCheckBox[16]; for(int i=0; i < 16; i++) { arr_checkbox[i] = QCheckBox(QString::number(i+1)); } ![]() ![]() "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)); |
Сообщ.
#8
,
|
|
|
Ну вот смотри, я набросал тебе макет твоей программы.
Прикреплённая картинка
dialog.h ![]() ![]() #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 ![]() ![]() #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. И обрати внимание, что все контролы, которые как-то будут взаимодействовать с пользователем или между собою - нужно объявлять полями класса. Иначе в других методах класса к ним доступа не будет, хотя они будут отображаться и висеть в памяти. Локальные объявки допустимы только для лайяутов. И то, если ты не собираешься в динамике добавлять или удалять контролы. Кстати. Посмотри важное преимущество "ручной" сборки формы. Я однотипные элементы, для удобства, могу собирать в контейнеры (вектора, мапы) и удобно к ним обращаться. В случае же использования дизайнера - каждое поле будет отдельной переменной. Во первых, это загромождает сам класс. А во вторых - если понадобится динамическая перекомпоновка, то используя дизайнер форм, про нее можно смело забыть. |
Сообщ.
#9
,
|
|
|
Спасибо огромное! Я только сейчас стал понимать, почему не следует использовать дизайнер. Все больше нравится QT. Буду дальше разбираться.
|
Сообщ.
#10
,
|
|
|
При создании интерфейса функция SetupWidgetsForm очень сильно разрастается. А можно ли в QT сделать следующее:
- создать в каком-то методе (классе) один элемент интерфейса, например комбобокс; - создать в другом методе (классе) другой элементы интерфейса, например набор спиннеров; - создать набор кнопок для сохранения, загрузки, очистки настроек и т.д. А затем прикрепить их к нужным лайаутам и разместить на форме? Или это мои фантазии и так делать QT не умеет (или это не нужно)? Как сложный интерфейс делают специалисты по QT без использования дизайнера? |
Сообщ.
#11
,
|
|
|
tumanovalex, "сетап" можно конечно разнести на n-методов. Но я бы не советовал такое делать. Лучше будет делать в одном методе - НО код комментировать. Т.е. просто комментариями визуально разделять "шаги". Это конечно дело вкуса. Если такое не нравится - безусловно можно сделать набор методов, а-ля setupCombo, setupSpin, setupButtons и вызывать их последовательно в конструкторе. Но в этом лично я какого-то профита не вижу.
|
Сообщ.
#12
,
|
|
|
Спасибо за ответ. Понятно.
|
Сообщ.
#13
,
|
|
|
tumanovalex, я обычно разделяю "сетап" контроллов и потом сетап коннектов. Как это делать - дело "вкусовщины"!. Можно просто тупо в конструкторе, можно разносить в методы, это дело - предпочтений. Мой подход "Не плодить сущностей без необходимости". По ссылке выше - "математическая часть" =)
|
Сообщ.
#14
,
|
|
|
Понятно. Интерфейс закончу на следующей неделе. Очень понравилось делать интерфейс без редактора. Большое спасибо за совет делать его без дизайнера!
|
Сообщ.
#15
,
|
|
|
В первом приближении сделал интерфейс вкладки "Настройки программы". Также попробовал получить параметры из этой вкладки. Не смог понять, как получить состояние всех чекбоксов в групбоксе "Каналы". Также хотел посоветоваться по поводу сохранения, загрузки и сбросу настроек. В старой программе на C# я сохранял и загружал файлы в виде сsv файлов, чтобы их можно было редактировать в текстовом редакторе. Очень нужны критика, замечания и предложения по интерфейсу программы, поскольку это мой первый опыт проекта на QT. Проект прикрепил.
Прикреплённый файл ![]() |