Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
0 / 0 / 0
Регистрация: 25.04.2025
Сообщений: 2

Привязка к pushButton нескольких виджетов

25.04.2025, 12:16. Показов 1595. Ответов 6
Метки c++, qt (Все метки)

Студворк — интернет-сервис помощи студентам
всем привет, пишу приложение "организатор задач".
решила сделать так, чтобы по нажатию кнопки появлялся текстбокс в котором юзер пишет свою задачу ставит дедлайн и по чекбоксу отмечает готова эта задача или нет, позже они перемещаются в архив.
в дизайне выглядит все легко, но вот не понимаю как все эти виджеты привязать к одной кнопке, может кто-то поможет?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
25.04.2025, 12:16
Ответы с готовыми решениями:

Привязка нескольких lineedit к pushbutton
При реализации с одним полем lineedit используется связь типа QObject::connect(lineedit1,...

Точная привязка виджетов к своему местоположению
Приве всем! Столкнулся с такой проблемой, есть большой QLabel с картинкой(QPixmap). Необходимо...

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

6
 Аватар для Ender Che
501 / 393 / 75
Регистрация: 29.05.2018
Сообщений: 1,231
25.04.2025, 12:36
Цитата Сообщение от nesashkai Посмотреть сообщение
как все эти виджеты привязать к одной кнопке
Как сделать в дизайнере. не подскажу.

А в коде так: нужные виджеты напихать в класс от QWidget, и его вставлять в лэйаут по нажатию на кнопку.
2
0 / 0 / 0
Регистрация: 25.04.2025
Сообщений: 2
25.04.2025, 12:40  [ТС]
Ender Che, да, все(5) виджеты должны появиться у юзера. снизу как это выглядит. я понимаю, что сделала слишком сложно, но так как только начинаю разбираться, не понимаю как лучше реализовать
Миниатюры
Привязка к pushButton нескольких виджетов  
0
 Аватар для Ender Che
501 / 393 / 75
Регистрация: 29.05.2018
Сообщений: 1,231
25.04.2025, 12:42
nesashkai, выше ответил.
0
фрилансер
 Аватар для Алексей1153
6384 / 5540 / 1118
Регистрация: 11.10.2019
Сообщений: 14,719
25.04.2025, 13:07
Цитата Сообщение от Ender Che Посмотреть сообщение
и его вставлять в лэйаут по нажатию на кнопку
можно не вставлять/убирать, а просто show/hide
0
 Аватар для Ender Che
501 / 393 / 75
Регистрация: 29.05.2018
Сообщений: 1,231
25.04.2025, 13:10
Цитата Сообщение от Алексей1153 Посмотреть сообщение
можно не вставлять/убирать, а просто show/hide
Виджет существующей задачи - да. А новую как?
0
1092 / 694 / 186
Регистрация: 30.03.2021
Сообщений: 2,173
26.04.2025, 03:05
Без делегатов и всяких моделей, баз данных и тд. Потрениться новичку для. (Обычно для таких задач иной подход).
Но опыт в Qt и с++ должен быть несколько выше совсем новичка. Без Дизайнера Форм Qt.
Лепил быстро тестил мало -так что если что...

На форме таблица, в ячейке таблицы виджет (как советовали в постах выше).
Прицепил еще (недо) сохранение в файл, сортировку и скрытие отдельных строк.

Кликните здесь для просмотра всего текста

Создай пустой проект на виджетах без формы, добавь заголовочный файл Task.
Замени текст в соотв. файлах.
Кажется что текста дохрена, но это из-за обилия комментов, если их убрать, прога совсем маленькая.

Task.h
Это виджет для ввода текста и даты, он будет вставляться в ячейку таблицы.
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#ifndef TASK_H
#define TASK_H
 
#include<QGroupBox>
#include<QPlainTextEdit>
#include<QCheckBox>
#include<QDateTimeEdit>
#include<QHBoxLayout>
#include<QPushButton>
#include<QTableWidgetItem>
 
class TaskWidget : public QGroupBox
{
    Q_OBJECT
 
private:
    QPlainTextEdit *tedit;
    QCheckBox *tcheck;
    QDateTimeEdit *ttimeStart, *ttimeEnd;
    QPushButton *tbtnDel;
    QTableWidgetItem *ttableWidgetItem=nullptr;
 
public:
    TaskWidget(QWidget *parent = nullptr)
        : QGroupBox(parent),
          tedit(new QPlainTextEdit),
          tcheck(new QCheckBox),
          ttimeStart(new QDateTimeEdit), ttimeEnd(new QDateTimeEdit),
          tbtnDel(new QPushButton("x"))
    {
 
        setTitle("Task:");
        auto hlayout=new QHBoxLayout;
        setLayout(hlayout);
 
        hlayout->addWidget(tedit,Qt::AlignJustify);
        hlayout->addWidget(tcheck,0,Qt::AlignRight);
        hlayout->addWidget(ttimeStart,0,Qt::AlignRight);
        hlayout->addWidget(ttimeEnd,0,Qt::AlignRight);
        hlayout->addWidget(tbtnDel,0,Qt::AlignRight);
 
        connect(tbtnDel, &QPushButton::clicked, [this]{emit delTask();});
    }
 
signals:
    void delTask(); //сигнал для удаления строки с виджетом из таблицы
 
//сеттеры и геттеры из этого виджета:
public:
    bool isDone()const{return tcheck->isChecked();}
    QDateTime timeStart()const{return ttimeStart->dateTime();}
    QDateTime timeEnd()const{return ttimeEnd->dateTime();}
    QString text()const{return tedit->toPlainText();}
    QTableWidgetItem* tableWidgetItem()const{return ttableWidgetItem;}
 
    void setDone(bool status){tcheck->setChecked(status);}
    void setStartTime(QDateTime time){ttimeStart->setDateTime(time);}
    void setEndTime(QDateTime time){ttimeEnd->setDateTime(time);}
    void setText(QString text){tedit->setPlainText(text);}
    void setTableWidgetItem(QTableWidgetItem *item){ttableWidgetItem=item;}
};
#endif // TASK_H

Тут все и так понятно, надеюсь.
mainwindow.h
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
 
class QTableWidget;
class QPushButton;
class QVBoxLayout;
class QSettings;
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
private:
    QTableWidget *ttaskList; //таблица(по сути список) строк с данными.
    QPushButton *tbtnAddTask, *tbtnSave, *tbtnSort, *tbtnHide;
    QVBoxLayout *tlayout;
    QSettings *settings; //для записи/чтения таблицы из файла.
 
private:
    QString dateTimeFormat{"dd.MM.yyyy"};
 
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
 
private slots:
    void deleteRow(); //слот для удаления строчки таблицы
 
};
#endif // MAINWINDOW_H

Основная логика тут.
mainwindow.cpp
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#include "mainwindow.h"
 
#include<QTableWidget>
#include<QPushButton>
#include<QVBoxLayout>
#include<QHeaderView>
#include<QFile>
#include<QSettings>
#include<QApplication>
 
#include"Task.h"
 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      ttaskList(new QTableWidget),
      tbtnAddTask(new QPushButton("Add")),
      tbtnSave(new QPushButton("Save")),
      tbtnSort(new QPushButton("Sort by status")),
      tbtnHide(new QPushButton("Hide")),
      tlayout(new QVBoxLayout)
 
{
    //путь к файлу, где хранятся данные из таблицы.
    //файл будет лежать рядом с экзешником приложения.
    //при дебаге примерно в build-task-Desktop_Qt_6_4_0_MinGW_64_bit-Debug в папке debug
    //у меня проект называется "task", у тебя версия кути и название проекта свои.
 
    QString settingsPath=qApp->applicationDirPath()+"/set.txt"; //можно временно задать путь попроще для отладки.
 
    int fileSize{0};
 
    //создаем файл для данных:
    QFile file(settingsPath);
    if (file.open(QIODevice::ReadOnly | QIODevice::Text)){
        fileSize=file.size();
        file.close();
    }else qDebug()<<"no file";
 
    //QSettings - механизм Qt для хранения данных, можно так же бинарник или текстовой файл, json, xml,...
    settings=new QSettings(settingsPath, QSettings::IniFormat, this);
 
    //компоновка и настройка виджетов окна:
    auto form=new QWidget;
    setCentralWidget(form);
    form->setLayout(tlayout);
 
    ttaskList->setColumnCount(1);
    ttaskList->setShowGrid(false);
    ttaskList->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
    ttaskList->verticalHeader()->setDefaultSectionSize(ttaskList->verticalHeader()->defaultSectionSize()*2);
 
    ttaskList->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    ttaskList->verticalHeader()->setSectionResizeMode(QHeaderView::Interactive);
 
    ttaskList->horizontalHeader()->setStretchLastSection(true);
    ttaskList->verticalHeader()->setStretchLastSection(true);
 
    ttaskList->horizontalHeader()->hide();
 
    //тут делаю цвет шрифта таблицы прозрачным, так как в ячейках будет лежать виджет а не текст.
    auto palette=ttaskList->palette();
    palette.setColor(QPalette::Text, Qt::transparent);
    ttaskList->setPalette(palette);
 
    tlayout->addWidget(tbtnAddTask);
    tlayout->addWidget(tbtnSave);
    tlayout->addWidget(tbtnSort);
    tlayout->addWidget(tbtnHide);
 
    tbtnSort->setCheckable(true);//даем кнопкам возможность быть нажатыми/отжатыми.
    tbtnHide->setCheckable(true);
 
    tlayout->addWidget(ttaskList);
 
    //при старте приложения восстанавливаем сохраненную копию таблицы из файла.
    //если файл не пустой, берем из него данные,
    //создаем виджет TaskWidget (это строчка с текстом и датами), выставляем в него эти данные
    //и добавляем виджет в ячейку таблицы.
    //Как записывать и читать файл с помощью QSettings смотри в доке Qt
    //данные в файле хранятся примерно так:
/*
[TasksCount]
Count=...  //количество Task (строк таблицы)
 
[Task1]  //это отдельная строка в таблице
Status=true  //выполнена ли задача
StartTime=... //дата начала
EndTime=...  //дата окончания
TaskText=...  //текст задачи
 
[Task2]
Status=false
StartTime=...
EndTime=...
TaskText=...
*/
 
    if(fileSize>0){
        bool ok;
        int taskCount=settings->value("TasksCount/Count").toInt(&ok); //берем из файла кол-во строк с данными.
        if(ok && taskCount>0){
            ttaskList->clear();
            for(int i=0; i<taskCount; i++){
                settings->beginGroup("Task"+QString::number(i+1)); 
                auto taskWidget=new TaskWidget; //создаем виджет для ячейки таблицы, 
                //он визуальный, в нем находятся поля ввода текста и даты.
                //устанавливаем в него данные из файла:
                taskWidget->setDone(settings->value("Status").toBool());
 
                QString stime=settings->value("StartTime").toString(); //дата начала.
                QString etime=settings->value("EndTime").toString();   //дата окончания.
                taskWidget->setStartTime(QDateTime::fromString(stime, dateTimeFormat));
                taskWidget->setEndTime(QDateTime::fromString(etime, dateTimeFormat));
 
                taskWidget->setText(settings->value("TaskText").toString());
 
                ttaskList->insertRow(i); //добавить в таблицу строку 
 
                //создать итем для ячейки таблицы (он виртуальный, не отображается а просто хранит данные ячейки)
                //он понадобится при удалении, сортировке и скрытии строк таблицы
                //и будет хранить какие то служебные данные,
                //например 0-если задача не выполнена, 1-если выполнена.
                auto item=new QTableWidgetItem;
                ttaskList->setItem(i,0, item); //устанавливаем его в ячейку таблицы
 
                taskWidget->setTableWidgetItem(item); //передаем его виджету, который будет в ячейке таблицы
                ttaskList->setCellWidget(i, 0, taskWidget);//и устанавливаем виджет в ячейку таблицы
                //тут главное не запутаться, в ячейке item-виртуальная сущность, а taskWidget-визуальная.
 
                //от сигнала виджета на удаление- удаляем строчку в таблице
                connect(taskWidget, &TaskWidget::delTask, this, &MainWindow::deleteRow);
 
                settings->endGroup();
            }
        }
    }
 
    //реакция на нажатие кнопки "Add" -добавить строчку в таблицу
    //механика та же, что описана выше.
    connect(tbtnAddTask, &QPushButton::clicked, this, [this]{
 
        auto taskWidget=new TaskWidget; //создаем новый визуальный виджет.
        ttaskList->insertRow(ttaskList->rowCount()); //добавляем строчку.
 
        int row=ttaskList->rowCount()-1;
        auto item=new QTableWidgetItem; //виртуальный итем.
        ttaskList->setItem(row,0, item); //ложим виртуальный в ячейку таблицы
        taskWidget->setTableWidgetItem(item); //и в визуальный виджет.
 
        ttaskList->setCellWidget(row, 0, taskWidget); //ложим визуальный виджет в ячейку таблицы.
        ttaskList->scrollToBottom(); //скролим таблицу к последней(добавленной) строчке.
        connect(taskWidget, &TaskWidget::delTask, this, &MainWindow::deleteRow);
    });
 
 
    //сохранить таблицу в файл при нажатии кнопки "Save"
    connect(tbtnSave, &QPushButton::clicked, this, [this]{
        //находим в таблице все виджеты класса TaskWidget.
        auto list= ttaskList->findChildren<TaskWidget*>();
 
        settings->clear();//очищаем файл данных.
 
        if(list.isEmpty())
            return;
 
        //записываем в файл кол-во строк, которое есть в таблице.
        settings->beginGroup("TasksCount");
        settings->setValue("Count", list.size());
        settings->endGroup();
 
        //перебираем все виджеты с данными из таблицы, 
        //и пишем эти данные в файл.
        int c{0};
        for(TaskWidget *taskWidget : list){
            settings->beginGroup("Task"+QString::number(++c)); //раздел файла, включающий строчку таблицы.
            settings->setValue("Status", taskWidget->isDone()); //и данные из таблицы в этот раздел.
            settings->setValue("StartTime", taskWidget->timeStart().toString(dateTimeFormat));
            settings->setValue("EndTime", taskWidget->timeEnd().toString(dateTimeFormat));
            settings->setValue("TaskText", taskWidget->text());
            settings->endGroup(); //закрываем раздел.
        }
    });
 
    //сортировка. законченные задачи отдельно от незаконченных.
    //какие идут первыми -зависит нажата кнопка или отжата.
    connect(tbtnSort,  &QPushButton::toggled, this, [this](bool checked){
        //перебираем все строчки таблицы
        //достаем из ячейки визуальный и виртуальный виджет
        //и устанавливаем в виртуальный item 0 или 1, которые получаем из визуального виджета, isDone()
        //то есть пороверяем выполнена задача или нет.
        for(int row=0; row<ttaskList->rowCount(); row++){
            if(auto taskWidget=dynamic_cast<TaskWidget*>(ttaskList->cellWidget(row,0))){
                ttaskList->item(row, 0)->setData(Qt::EditRole, (int)taskWidget->isDone());
            }
        }
        //затем таблица сортируется на основе данных в виртуальных итемах ячеек.
        ttaskList->sortByColumn(0, checked ? Qt::AscendingOrder : Qt::DescendingOrder);
    });
 
 
    //прячем законченные или незаконченные задачи, по нажатию/отжатию кнопки.
    connect(tbtnHide,  &QPushButton::toggled, this, [this](bool checked){
        for(int row=0; row<ttaskList->rowCount(); row++){
            if(auto taskWidget=dynamic_cast<TaskWidget*>(ttaskList->cellWidget(row,0))){
                if(taskWidget->isDone())
                    checked ? ttaskList->hideRow(row) : ttaskList->showRow(row);
                else
                    checked ? ttaskList->showRow(row) : ttaskList->hideRow(row);
            }
        }
    });
}
 
//удаление строчки из таблицы:
void MainWindow::deleteRow()
{
    //sender() - это тот визуальный виджет в ячейке таблицы, где нажали кнопку [x]
    if(auto item=dynamic_cast<TaskWidget*>(sender())){
        //тут пригодился указатель на виртуальный итем в ячейке таблицы, который  мы сохранили в визуальном виджете.
        //иначе возникнет путаница при удалении/добавлении новых строк и это чревато крашем.
        int row=item->tableWidgetItem()->row();
        ttaskList->removeCellWidget(row, 0);
        ttaskList->removeRow(row);
        item->deleteLater();
    }
}
 
 
MainWindow::~MainWindow()
{
}
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
26.04.2025, 03:05
Помогаю со студенческими работами здесь

PushButton
Всем привет! Можно ли проверять, кто является источником сигнала? Т.е. в конструкторе...

Группы pushbutton
В общем такая проблема. есть в виджите три главные кнопки, и группа кнопок. Так вот когда я...

Как получить координаты "pushButton" если он внутри "verticalLayout"
Доброго времени суток! Как получить координаты кнопки если она внутри группировки? У меня по 0...

Файл: Выгрузить файл через нажатие кнопки pushButton и выгрузить его в listWidget
здравствуйте давно не заходил в QT и впринцепи им особо не когда не занимался не подскажите хочу...

При нажатии на pushButton чтение чисел из двух lineEdit
Как сделать так, чтоб при нажатии на кнопку, числа считывались из обоих lineEdit ? void...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Повышаем производительность игры на Unity 6 с GPU Resident Drawer
GameUnited 11.06.2025
Недавно копался в новых фичах Unity 6 и наткнулся на GPU Resident Drawer - штуку, которая заставила меня присвистнуть от удивления. По сути, это внутренний механизм рендеринга, который автоматически. . .
Множества в Python
py-thonny 11.06.2025
В Python существует множество структур данных, но иногда я сталкиваюсь с задачами, где ни списки, ни словари не дают оптимального решения. Часто это происходит, когда мне нужно быстро проверять. . .
Работа с ccache/sccache в рамках C++
Loafer 11.06.2025
Утилиты ccache и sccache занимаются тем, что кешируют промежуточные результаты компиляции, таким образом ускоряя последующие компиляции проекта. Это означает, что если проект будет компилироваться. . .
Настройка MTProxy
Loafer 11.06.2025
Дополнительная информация к инструкции по настройке MTProxy: Перед сборкой проекта необходимо добавить флаг -fcommon в конец переменной CFLAGS в Makefile. Через crontab -e добавить задачу: 0 3. . .
Изучаем Docker: что это, как использовать и как это работает
Mr. Docker 10.06.2025
Суть Docker проста - это платформа для разработки, доставки и запуска приложений в контейнерах. Контейнер, если говорить образно, это запечатанная коробка, в которой находится ваше приложение вместе. . .
Тип Record в C#
stackOverflow 10.06.2025
Многие годы я разрабатывал приложения на C#, используя классы для всего подряд - и мне это казалось естественным. Но со временем, особенно в крупных проектах, я стал замечать, что простые классы. . .
Разработка плагина для Minecraft
Javaican 09.06.2025
За годы существования Minecraft сформировалась сложная экосистема серверов. Оригинальный (ванильный) сервер не поддерживает плагины, поэтому сообщество разработало множество альтернатив. CraftBukkit. . .
Dapper - лучший среди микроORM под C#
UnmanagedCoder 09.06.2025
Знаете, в мире ORM-инструментов для . NET существует негласная иерархия. На вершине массивных фреймворков возвышается Entity Framework - неповоротливый, но всемогущий. А в категории легковесных. . .
Сравнение GCC 14 и Clang 18 компиляторов C для HPC
bytestream 08.06.2025
В высокопроизводительных вычислениях (HPC) выбор компилятора - это ход, способный радикально изменить производительность всей системы. Работая последние 15 лет с критическими HPC-системами, я видел. . .
Всё о конфигурации ASP.NET Core
stackOverflow 08.06.2025
Старый добрый web. config, похоже, отправился на пенсию вместе с классическим ASP. NET. За годы работы с различными проектами я убедился, что хорошо организованная конфигурация – это половина успеха. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
OSZAR »