ПБ
Jan. 11, 2019, 6:09 p.m.
Qt, Qml, QAbstractTableModel
Всем привет, часто нахожу ответы на вашем форуме. Огромное спасибо. Пролистал кучу других форумов, просмотрел документацию. Ничего не получается.
Не могу заставить чекбокс в хэдере таблицы работать с чекбоксами в колонке таблицы. Мне нужно либо выделить все, либо снять все чекбоксы. Пробовал двумя способами. Не работает. Помогите, пожалуйста.
- #ifndef FOODTABLEMODEL_H
- #define FOODTABLEMODEL_H
- #include <QAbstractTableModel>
- #include <QModelIndex>
- #include <QHash>
- #include <QVariant>
- #include <QByteArray>
- #include <QList>
- struct Food
- {
- bool check;
- QString description;
- int price;
- QString code;
- };
- class FoodTableModel : public QAbstractTableModel
- {
- Q_OBJECT
- public:
- enum RoleNames
- {
- CHECK = 0,
- DESCRIPTION = 1,
- PRICE = 2,
- CODE = 3
- };
- FoodTableModel(QObject *parent = nullptr);
- int rowCount(const QModelIndex &parent) const;
- int columnCount(const QModelIndex &parent) const;
- QVariant data(const QModelIndex &index, int role) const;
- QHash<int, QByteArray> roleNames() const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
- Q_INVOKABLE void checkTable(bool value);
- private:
- QList<Food> foods;
- };
- #endif // FOODTABLEMODEL_H
- #include "foodtablemodel.h"
- #include <QDebug>
- FoodTableModel::FoodTableModel(QObject *parent) :
- QAbstractTableModel { parent }
- {
- foods.append({ false, "Pizza", 12, "ASR1" });
- foods.append({ false, "Milk", 1, "BE-23" });
- foods.append({ false, "Coffe", 4, "ARTY8-9" });
- /*foods.append({ "Lizza", "12", "ASR1" });
- foods.append({ "SMilk", "34", "BE-23" });
- foods.append({ "YCoffe", "5", "QRTY8-9" });*/
- }
- int FoodTableModel::rowCount(const QModelIndex &parent) const
- {
- return foods.size();
- }
- int FoodTableModel::columnCount(const QModelIndex &parent) const
- {
- return roleNames().size();
- }
- QVariant FoodTableModel::data(const QModelIndex &index, int role) const
- {
- QVariant variant;
- const int row = index.row();
- const int col = role;
- switch (col) {
- case CHECK: variant = foods.at(row).check; break;
- case DESCRIPTION: variant = foods.at(row).description; break;
- case PRICE: variant = foods.at(row).price; break;
- case CODE: variant = foods.at(row).code; break;
- }
- return variant;
- }
- QHash<int, QByteArray> FoodTableModel::roleNames() const
- {
- QHash<int, QByteArray> roles;
- roles.insert(CHECK, "check");
- roles.insert(DESCRIPTION, "description");
- roles.insert(PRICE, "price");
- roles.insert(CODE, "code");
- return roles;
- }
- bool FoodTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
- {
- if(index.isValid() && role == CHECK) {
- foods[index.row()].check = value.toBool();
- emit dataChanged(index, index, { role });
- return true;
- }
- else return false;
- }
- void FoodTableModel::checkTable(bool value)
- {
- for (int i = 0; i < foods.size(); i++) {
- qDebug() << i << value;
- foods[i].check = value;
- }
- }
- #include <QGuiApplication>
- #include <QQmlApplicationEngine>
- #include <QQmlContext>
- #include "foodtablemodel.h"
- #include "person.h"
- #include "sortfilterproxymodel.h"
- int main(int argc, char *argv[]) {
- QGuiApplication app(argc, argv);
- QQmlApplicationEngine engine;
- FoodTableModel food;
- qmlRegisterType<SortFilterProxyModel>("SortFilterProxyModel", 0, 1, "SortFilterProxyModel");
- engine.rootContext()->setContextProperty("food", &food);
- engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
- if (engine.rootObjects().isEmpty())
- return -1;
- return app.exec();
- }
- import QtQuick 2.12
- import QtQuick.Controls 1.4 as C1
- import QtQuick.Controls.Styles 1.4
- import QtQuick.Controls 2.4
- import SortFilterProxyModel 0.1
- import "JavaScript/TableViewCheck.js" as TVC
- C1.TableView {
- id: tableView
- clip: true
- sortIndicatorVisible: true
- currentRow: rowCount ? 0 : -1
- model: SortFilterProxyModel {
- source: food.rowCount() > 0 ? food : null
- sortOrder: tableView.sortIndicatorOrder
- sortCaseSensitivity: Qt.CaseInsensitive
- sortRole: food.rowCount() && tableView.getColumn(tableView.sortIndicatorColumn).role !== "check" > 0 ?
- tableView.getColumn(tableView.sortIndicatorColumn).role : ""
- }
- C1.TableViewColumn {
- width: 30
- role: "check"
- resizable: false
- delegate: C1.CheckBox {
- id: checkBox
- anchors.left: parent.left
- anchors.leftMargin: parent.width / 3
- checked: model.check
- onVisibleChanged: if (visible) checked = model.check
- onClicked: model.check = checked
- }
- }
- C1.TableViewColumn {
- role: "description"
- title: "Description"
- }
- C1.TableViewColumn {
- role: "price"
- title: "Price"
- }
- C1.TableViewColumn {
- role: "code"
- title: "Code"
- }
- style: TableViewStyle {
- headerDelegate: Rectangle {
- height: textItem.implicitHeight
- width: textItem.implicitWidth
- Text {
- id: textItem
- anchors.fill: parent
- anchors.leftMargin: 6
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: styleData.textAlignment
- text: styleData.value
- }
- C1.CheckBox {
- anchors.left: parent.left
- anchors.leftMargin: parent.width / 3
- property bool isPressed: styleData.pressed
- visible: styleData.column === 0
- onIsPressedChanged: {
- if(isPressed) {
- checked = !checked
- for(var i = 0; i < rowCount; i++) {
- food.setData(foods.index(i, 0), checked, "check")
- }
- //food.checkTable(checked)
- }
- }
- }
- }
- }
- }
3
99
Do you like it? Share on social networks!
- Last comments
- AKApril 1, 2025, 11:41 a.m.Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
- VPMarch 9, 2025, 4:14 p.m.Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
- ИМNov. 22, 2024, 9:51 p.m.Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
- Now discuss on the forum
- МАApril 1, 2025, 4:21 p.m.0ff763fe-4e50-455d-a3a6-5699c243b1a5_17_44_22_1.xml
- fFeb. 15, 2025, 1:46 p.m.Подскажите, пожалуйста! Как данный класс можно дополнить, чтобы созданные объекты можно было перемещать мышкой по сцене?
- Не запускается компьютер (точнее работает блок , но сам монитор вообще жесть)В общем я ничего с интернета не скачивала в последнее время. На компе никаких левых пр…
- Вопрос решен. Узнать QModelIndex элемента на который мы перетаскиваем другой элемент, можно с помощью функции indexAt(event->position().toPoint()) представления QTreeViev вызываемой в переопр…
Добрый день. Интересная задача. Мне тоже нужно будет что-то подобное сделать. Так что с удовольствием поковыряюсь. Но большая просьба - оформите исходники, пожалуйста. В текущем виде ими невозможно воспользоваться.
Александр, я все исправил, но случайно ответил ваш ответ как решение. Теперь вы просто обязаны мне помочь.
:)))) это было очень ошибочное решение, настолько поверить в меня. Но я постараюсь.
Не увидел в исходниках описание этой модели - SortFilterProxyModel.
Из QML кода обращение идёт к ней.
Эта модель отвечает за сортировку колонок, поэтому я не скидывал файлы реализации.
Несколько упросил ваш пример и сделал его рабочим - проверяйте:
main.c
checkmodel.h
checkmodel.cpp
main.qml
Также прикладываю исходники для удобства.
QmlAllColumnCheckBox.zip
На идеальный код мой вариант не претендует. Если будут замечания у вас или других более опытных коллег - буду рад услышать.
Но в целом поставленную вами задачу он решает.
Будут вопросы - задавайте.
Маленькие заметки:
- QML != JS. Старайтесь избегать использования кода javascript.
- struct заставляет выдумывать массу не нужных костылей (enum, например, или ручное прописывание ролей) - замените его на класс, туда же можно кучу логики вынести.
- в своем примере вы добавили в качестве модели прокси-модель - это хорошо, но я не зря просил её реализацию, т.к. в дальнейшем вы пытались обращаться к функциям модели. В таком случае вам нужно было либо сделать подобные функции в прокси, либо обращаться к модели прокси-модели.
Александр, огромное спасибо. Я надеюсь, что у вас опыта побольше, чем у меня, и те нюансы, которые вы внесли, они обоснованы. Если у меня возникнут проблемы с объединением прокси модели и модели, которую вы реализовали, можно я буду у вас спрашивать здесь (или лучше задать новый вопрос)?
Обращайтесь, чем смогу - помогу.
Александр, как я и ожидал, проблема появилась, причем очень странная. Когда кликая по хедеру табдицы, чтобы отсортировать колонку таблицы, то выделяются все чекбоксы. Прикладываю исходники модели сортровки (Это код не мой, я его нашел на просторах интернета). Стоит объеденить модели?
Это измененное место инициализации модели в файле main.qml
Дописал вопрос, и понял. Выделение должно происходить, когда мы кликаем по чекбоксу в хедере, а оно происходит при нажатии в любом месте хедера.
Вот решение.
Qt не поддерживает чекбоксы в хедерах таблицы, чтобы это сделать
Попробуйте создать класс отнаследованный от QHeaderView и в нем переопределить метод data ( if(role==CheckStateRole и т.д.)
и добавить сигнал (checkedChanged)
HeaderClass{
id:header
}
// in tableView
delegate: Checkbox {
id: headerDelegate
checked: header.checked
onCheckedChanged: headerDelegate.checked = checked // пишем состояние куда надо
}
или засунуть в роли модели роль 'HeaderCheckedState'
и брать оттуда