QtQuick TableView CheckBox 委托调用 QAbstractTableModel 的 setData 函数
Posted
技术标签:
【中文标题】QtQuick TableView CheckBox 委托调用 QAbstractTableModel 的 setData 函数【英文标题】:QtQuick TableView CheckBox delegate calling setData function of QAbstractTableModel 【发布时间】:2014-06-16 11:40:36 【问题描述】:我无法连接 qml 中的 TableView 和 QT 中 QAbstractTableModel 的 setData 函数。我的想法是能够通过 CkeckBox 委托将活动检查为“已完成”。我尝试覆盖 setData 函数以使用 row 而不是 QmodelIndex 并将其 view.currentrow 作为来自 qml 文件的参数发送。但它不起作用(currentrow 总是发送默认的 -1 值)。
main.qml
import QtQuick 2.0
import QtQuick.Window 2.1
import QtQuick.Controls 1.1
import QtQuick.Dialogs 1.0
import TodoM 1.0
Rectangle
width: 600
height: 400
TextField
id:activityDescriptionTextEdit
anchors.top: parent.top
width: 500
height: 50
Button
id: saveActivityButton
text: "Save Activity"
anchors.left: activityDescriptionTextEdit.right
onClicked: myModel.appendTodoFromQtQuick ( activityDescriptionTextEdit.text )
TextField
id: filePathDisplay
anchors.top: activityDescriptionTextEdit.bottom
width: 500
height: 50
Button
text: "Save File"
anchors.left: filePathDisplay.right
anchors.top: activityDescriptionTextEdit.bottom
onClicked: saveFileDialog.open()
TableView
id:view
anchors.top: filePathDisplay.bottom
width: 500
height: 400
TableViewColumn
id: firstColumn
title: "Is Done"
role: "isDoneStateCheckState"
width:100;
delegate: CheckBox
id: checkBox
onCheckedChanged:
//Here is where I want to call setData
TableViewColumn
title: "Activity"
role: "activityDescriptionState"
width:200
TableViewColumn
role: "timeStampState"
width:200
model: myModel
FileDialog
id: saveFileDialog
title: "Save File As"
selectExisting: false
selectMultiple: false
nameFilters: "*txt"
onAccepted:
_ft.saveFile( saveFileDialog.fileUrl, myModel )
onRejected:
console.log("Canceled")
TodoModel.cpp
#include "TodoModel.h"
#include "QModelIndex"
#include "QDebug"
TodoModel::TodoModel( QObject *parent )
: QAbstractTableModel( parent )
TodoModel::~TodoModel()
QModelIndex TodoModel::parent( const QModelIndex& child ) const
Q_UNUSED( child )
return QModelIndex();
int TodoModel::rowCount( const QModelIndex& parent ) const
Q_UNUSED( parent )
return m_todos.count();
int TodoModel::columnCount( const QModelIndex& parent ) const
Q_UNUSED( parent )
return ColumnsCount;
QVariant TodoModel::data( const QModelIndex& index, int role ) const
int columnIndex = index.column();
const int rowIndex = index.row();
switch ( role )
case IsDoneRole:
case IsDoneCheckStateRole:
columnIndex = ColumnIndexIsDone;
break;
case ActivityDesctriptionRole:
columnIndex = ColumnIndexActivityDescription;
break;
case TimeStampRole:
columnIndex = ColumnIndexTimestamp;
break;
default:
break;
if ( ! this->isValidColumnIndex( columnIndex )
|| ! this->isValidRowIndex( rowIndex ) )
return QVariant();
const Todo& todo = m_todos[ rowIndex ];
switch ( columnIndex )
case ColumnIndexIsDone:
if ( role == Qt::CheckStateRole
|| role == IsDoneCheckStateRole )
return todo.isDone()
? Qt::Checked
: Qt::Unchecked;
else if ( role == Qt::UserRole
|| role == IsDoneRole )
return todo.isDone();
break;
case ColumnIndexActivityDescription:
if ( role == Qt::DisplayRole )
return todo.activityDescription();
else if ( role == Qt::UserRole
|| role == ActivityDesctriptionRole )
return todo.activityDescription();
//Maham Brake-ovete i stava o.O
break;
case ColumnIndexTimestamp:
if ( role == Qt::DisplayRole )
return todo.addedTimestamp().toString( "dd/MM/yyyy hh:mm:ss.zzz" );
else if ( role == Qt::UserRole
|| role == TimeStampRole )
return todo.addedTimestamp();
break;
default:
break;
return QVariant();
QVariant TodoModel::headerData( int section, Qt::Orientation orientation, int role ) const
if ( ! this->isValidColumnIndex( section )
|| orientation != Qt::Horizontal
|| role != Qt::DisplayRole )
return QVariant();
switch ( section )
case ColumnIndexIsDone:
return tr( "Is Done" );
case ColumnIndexActivityDescription:
return tr( "Activity Description" );
case ColumnIndexTimestamp:
return tr( "Timestamp" );
default:
break;
return QVariant();
Qt::ItemFlags TodoModel::flags( const QModelIndex& index ) const
Qt::ItemFlags finalFlags = QAbstractTableModel::flags( index );
if ( index.column() == ColumnIndexIsDone )
finalFlags |= Qt::ItemIsUserCheckable;
return finalFlags;
bool TodoModel::setData( const QModelIndex& index, const QVariant& value, int role )
const int rowIndex = index.row();
const int columnIndex = index.column();
if ( ! this->isValidRowIndex( rowIndex )
|| ! this->isValidColumnIndex( columnIndex ) )
return false;
Todo& todo = m_todos[ rowIndex ];
switch ( columnIndex )
case ColumnIndexIsDone:
if ( role != Qt::CheckStateRole
&& role != IsDoneRole
&& role != IsDoneCheckStateRole )
return false;
bool converted = false;
const Qt::CheckState checkState = static_cast< Qt::CheckState > ( value.toInt( & converted ) );
const bool isChecked = checkState == Qt::Checked;
if ( ! isChecked
&& checkState != Qt::Unchecked )
return false;
if ( todo.isDone() == isChecked )
return false;
todo.setIsDone( isChecked );
QModelIndex index;
index = index.child( rowIndex, 0 );
emit dataChanged( index, index );
break;
default:
break;
return true;
void TodoModel::appendTodo( const Todo& aTodo )
const int previousRowsCount = this->rowCount();
this->beginInsertRows( QModelIndex(), previousRowsCount, previousRowsCount );
m_todos.append( aTodo );
this->endInsertRows();
void TodoModel::clear()
const int rowsCount = this->rowCount();
if ( rowsCount <= 0 )
return;
this->beginRemoveRows( QModelIndex(), 0, rowsCount - 1 );
m_todos.clear();
this->endRemoveRows();
bool TodoModel::isValidColumnIndex(const int columnIndex) const
return 0 <= columnIndex && columnIndex < this->columnCount();
bool TodoModel::isValidRowIndex( const int rowIndex ) const
return 0 <= rowIndex && rowIndex < this->rowCount();
QList<Todo> TodoModel::todos() const
return m_todos;
void TodoModel::appendTodoFromQtQuick(QString aActivityDescription)
Todo todo;
todo.setIsDone( false );
todo.setActivityDescription( aActivityDescription );
todo.setAddedTimestamp( QDateTime::currentDateTime() );
appendTodo(todo);
QHash<int, QByteArray> TodoModel::roleNames() const
QHash<int, QByteArray> roles;
roles[IsDoneRole] = "isDoneState";
roles[IsDoneCheckStateRole] = "isDoneStateCheckState";
roles[ActivityDesctriptionRole] = "activityDescriptionState";
roles[TimeStampRole] = "timeStampState";
return roles;
TodoModel.h
#ifndef TODOMODEL_H
#define TODOMODEL_H
#include "Todo.h"
#include <QAbstractTableModel>
#include <QList>
enum ColumnIndex
ColumnIndexIsDone = 0,
ColumnIndexActivityDescription = 1,
ColumnIndexTimestamp = 2,
ColumnsCount = 3
;
class TodoModel : public QAbstractTableModel
Q_OBJECT
public:
explicit TodoModel( QObject* parent = 0 );
virtual ~TodoModel();
enum TodoColumnRoles
IsDoneRole = Qt::UserRole + 1,
IsDoneCheckStateRole = Qt::UserRole + 2,
ActivityDesctriptionRole = Qt::UserRole + 3,
TimeStampRole = Qt::UserRole + 4
;
virtual QModelIndex parent( const QModelIndex& child ) const;
virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const;
virtual int columnCount( const QModelIndex& parent = QModelIndex() ) const;
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
virtual QVariant headerData( int section, Qt::Orientation orientation,
int role = Qt::DisplayRole ) const;
// https://Radost@bitbucket.org/Radost/qtquickcontrols.git
Qt::ItemFlags flags( const QModelIndex& index ) const;
Q_INVOKABLE virtual bool setData( const QModelIndex& index, const QVariant &value, int role = Qt::EditRole );
void appendTodo( const Todo& aTodo );
void clear();
bool isValidColumnIndex( const int columnIndex ) const;
bool isValidRowIndex( const int rowIndex ) const;
Q_INVOKABLE QList<Todo> todos() const;
//Q_INVOKABLE QList<Todo*> ptodos() const;
public slots:
Q_INVOKABLE void appendTodoFromQtQuick( QString aActivityDescription);
protected:
QHash<int, QByteArray> roleNames() const;
private:
QList< Todo > m_todos;
//Q_QList< Todo* > m_ptodos;
;
#endif // TODOMODEL_H
知道我该怎么做吗?
【问题讨论】:
【参考方案1】:您的代码是阅读和维护的噩梦。请注意制表符和空白。
您通过在委托中设置变量(称为角色名称)隐式调用setData
:
TableViewColumn
id: firstColumn
title: "Is Done"
role: "isDoneStateCheckState"
width:100;
delegate: CheckBox
id: checkBox
onCheckedChanged:
isDoneState = checked
枚举是自动枚举的,去吧:
enum TodoColumnRoles
IsDoneRole = Qt::UserRole,
IsDoneCheckStateRole,
ActivityDesctriptionRole,
TimeStampRole
;
setData
中应该只有一个大的 switch 语句来查找 role
的不同值。
为dataChanged()创建新索引是没有意义的:
QModelIndex index;
index = index.child( rowIndex, 0 );
emit dataChanged( index, index );
您应该重用setData( const QModelIndex& index ...
中的参数,因为它具有唯一可能的正确值。
【讨论】:
以上是关于QtQuick TableView CheckBox 委托调用 QAbstractTableModel 的 setData 函数的主要内容,如果未能解决你的问题,请参考以下文章
来自 C++ 的 QStandardItemModel 在 QtQuick / QML TableView 中不可见
QtQuick Controls 2 中的新 TableView 是不是支持不同的“角色”
QtQuick TableView CheckBox 委托调用 QAbstractTableModel 的 setData 函数
将 QStandardItemModel 从 C++ 传递到 QtQuick / QML TableView 并显示它