|
10Qter豆
各位好,我是论坛新人,也是qt新手。最近项目上有数据库开发的需求,我使用QTableview+QSqlqueryModel来显示数据,需要在表格的第一列添加复选框checkbox,我google了不少资料,网上大致有两种方法,一是自定义一个继承于QSqlqueryModel的子类,并重载flags(), data(),setdata()函数;二是自定义一个委托delegate,重载相关函数。参考了相关资料后,我的代码如下:
mydelegate.h- #include<QtGui>
- class CheckBoxDelegate:public QStyledItemDelegate
- {
- Q_OBJECT
- public:
- CheckBoxDelegate(QObject *parent = 0);
- QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
- void setEditorData(QWidget *editor, const QModelIndex &index) const;
- void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
- void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
- void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
- };
复制代码 mydelegate.cpp- #include"mydelegate.h"
- CheckBoxDelegate::CheckBoxDelegate(QObject *parent)
- :QStyledItemDelegate(parent)
- {
- }
- void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
- {
- bool data = index.model()->data(index, Qt::DisplayRole).toBool();
- QStyleOptionButton checkboxstyle;
- QRect checkbox_rect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkboxstyle);
- checkboxstyle.rect = option.rect;
- checkboxstyle.rect.setLeft(option.rect.x() + option.rect.width()/2 - checkbox_rect.width()/2);
- checkboxstyle.palette.setColor(QPalette::Highlight, index.data(Qt::BackgroundRole).value<QColor>());
- if(data)
- checkboxstyle.state = QStyle::State_On|QStyle::State_Enabled;
- else
- checkboxstyle.state = QStyle::State_Off|QStyle::State_Enabled;
- QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkboxstyle, painter);
- }
- QWidget* CheckBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
- {
- if(index.isValid()&&index.column()==0){
- QCheckBox *editor=new QCheckBox(parent);
- editor->installEventFilter(const_cast<CheckBoxDelegate*>(this));
- return editor;
- }
- else
- return QStyledItemDelegate::createEditor(parent,option,index);
- }
- void CheckBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
- {
- if(index.isValid() && index.column() == 0){
- QString value=index.model()->data(index,Qt::CheckStateRole|Qt::DisplayRole).toString();
- QCheckBox *checkBox = static_cast<QCheckBox*>(editor);
- checkBox->setCheckState(Qt::Unchecked);
- }
- else
- QStyledItemDelegate::setEditorData(editor,index);
- }
- void CheckBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
- {
- if(index.isValid() && index.column() == 0)
- {
- QCheckBox *checkBox = static_cast<QCheckBox*>(editor);
- QString value;
- if(checkBox->checkState() == Qt::Checked)
- value = "Y";
- else
- value = "N";
- model->setData(index, value);
- }
- else
- {
- QStyledItemDelegate::setModelData(editor, model, index);
- }
- }
- void CheckBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
- {
- if(index.isValid() && index.column() == 0)
- editor->setGeometry(option.rect);
- else
- QStyledItemDelegate::updateEditorGeometry(editor, option, index);
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
- {
- QStyleOptionViewItemV4 viewItemOption(option);
- if (index.column() == 0) {
- const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
- QRect newRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
- QSize(option.decorationSize.width() + 5,option.decorationSize.height()),
- QRect(option.rect.x() + textMargin, option.rect.y(),
- option.rect.width() - (2 * textMargin), option.rect.height()));
- viewItemOption.rect = newRect;
- }
- QStyledItemDelegate::paint(painter, viewItemOption, index);
- }
- bool ItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
- {
- Q_ASSERT(event);
- Q_ASSERT(model);
- // make sure that the item is checkable
- Qt::ItemFlags flags = model->flags(index);
- if (!(flags & Qt::ItemIsUserCheckable) || !(flags & Qt::ItemIsEnabled))
- return false;
- // make sure that we have a check state
- QVariant value = index.data(Qt::CheckStateRole);
- if (!value.isValid())
- return false;
- // make sure that we have the right event type
- if (event->type() == QEvent::MouseButtonRelease) {
- const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
- QRect checkRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
- option.decorationSize,
- QRect(option.rect.x() + (2 * textMargin), option.rect.y(),
- option.rect.width() - (2 * textMargin),
- option.rect.height()));
- if (!checkRect.contains(static_cast<QMouseEvent*>(event)->pos()))
- return false;
- } else if (event->type() == QEvent::KeyPress) {
- if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space&& static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
- return false;
- } else {
- return false;
- }
- Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
- ? Qt::Unchecked : Qt::Checked);
- return model->setData(index, state, Qt::CheckStateRole);
- }
复制代码 mysqlquerymodel.h- #include <QSqlQueryModel>
- #include<QApplication>
- #include<QModelIndex>
- #include<QSqlTableModel>
- class MySqlQueryModel : public QSqlQueryModel
- {
- Q_OBJECT
- public:
- explicit MySqlQueryModel(QObject * = 0);
- public:
- Qt::ItemFlags flags(const QModelIndex &index) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- };
复制代码 mysqlquerymodel.cpp- #include "mysqlquerymodel.h"
- #include<QSqlQuery>
- #include<QStandardItem>
- MySqlQueryModel::MySqlQueryModel(QObject *parent) :
- QSqlQueryModel(parent)
- {
- }
- Qt::ItemFlags MySqlQueryModel::flags(
- const QModelIndex &index) const //返回表格是否可更改的标志
- {
- Qt::ItemFlags flags = QSqlQueryModel::flags(index);
- if (index.column() == 0) //第1个属性可更改
- {
- return Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsEditable;
- }
- else
- return flags;
- }
- QVariant MySqlQueryModel::data(const QModelIndex &index, int role) const
- {
- QVariant value = QSqlQueryModel::data(index, role);
- if (role == Qt::CheckStateRole && index.column() == 0)
- return (QSqlQueryModel::data(index).toInt() != 0) ? Qt::Checked : Qt::Unchecked;
- else
- return value;
- }
- bool MySqlQueryModel::setData(const QModelIndex &index, const QVariant &value, int role)
- {
- if (!index.isValid())
- return false;
- if (role == Qt::CheckStateRole)
- {
- if ((Qt::CheckState)value.toInt() == Qt::Checked)
- {
- //user has checked item
- return true;
- }
- else
- {
- //user has unchecked item
- return true;
- }
- }
- return false;
- }
复制代码 加载delegate后,checkbox居中显示,如下图:
这时问题来了,我必须双击才能进入cell勾选checkbox,并且checkbox的位置跑到了左边,如下图:
并且当鼠标焦点转到其他地方时,checkbox会复位,且刚才打的勾也没了,回到第一张图的状态。
这个复选框整了我好几天了,各位大虾帮忙看看,万分感谢! |
最佳答案
查看完整内容
上面的所有代码都搞明白了吗?
可以尝试搞明白Qt的模型视图编程,委托是干什么的,需要设置哪些内容。
|