找回密码
 立即注册
收起左侧

急求解决QTableview中插入checkbox的问题

6
回复
12021
查看
[复制链接]
累计签到:99 天
连续签到:1 天
来源: 2014-3-12 17:32:34 显示全部楼层 |阅读模式
10Qter豆
        各位好,我是论坛新人,也是qt新手。最近项目上有数据库开发的需求,我使用QTableview+QSqlqueryModel来显示数据,需要在表格的第一列添加复选框checkbox,我google了不少资料,网上大致有两种方法,一是自定义一个继承于QSqlqueryModel的子类,并重载flags(), data(),setdata()函数;二是自定义一个委托delegate,重载相关函数。参考了相关资料后,我的代码如下:
mydelegate.h
  1. #include<QtGui>

  2. class CheckBoxDelegate:public QStyledItemDelegate
  3. {
  4.     Q_OBJECT

  5. public:
  6.     CheckBoxDelegate(QObject *parent = 0);
  7.     QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
  8.     void setEditorData(QWidget *editor, const QModelIndex &index) const;
  9.     void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
  10.     void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
  11.     void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;

  12. };
复制代码
mydelegate.cpp
  1. #include"mydelegate.h"

  2. CheckBoxDelegate::CheckBoxDelegate(QObject *parent)
  3.     :QStyledItemDelegate(parent)
  4. {

  5. }

  6. void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
  7. {

  8.     bool data = index.model()->data(index, Qt::DisplayRole).toBool();
  9.     QStyleOptionButton checkboxstyle;
  10.     QRect checkbox_rect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkboxstyle);
  11.     checkboxstyle.rect = option.rect;
  12.     checkboxstyle.rect.setLeft(option.rect.x() + option.rect.width()/2 - checkbox_rect.width()/2);
  13.     checkboxstyle.palette.setColor(QPalette::Highlight, index.data(Qt::BackgroundRole).value<QColor>());
  14.     if(data)
  15.         checkboxstyle.state = QStyle::State_On|QStyle::State_Enabled;
  16.     else
  17.         checkboxstyle.state = QStyle::State_Off|QStyle::State_Enabled;
  18.     QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkboxstyle, painter);

  19. }



  20. QWidget* CheckBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
  21. {
  22.     if(index.isValid()&&index.column()==0){
  23.         QCheckBox *editor=new QCheckBox(parent);
  24.         editor->installEventFilter(const_cast<CheckBoxDelegate*>(this));
  25.         return editor;
  26.     }
  27.     else
  28.         return QStyledItemDelegate::createEditor(parent,option,index);

  29. }

  30. void CheckBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
  31. {
  32.     if(index.isValid() && index.column() == 0){
  33.         QString value=index.model()->data(index,Qt::CheckStateRole|Qt::DisplayRole).toString();
  34.         QCheckBox *checkBox = static_cast<QCheckBox*>(editor);
  35.         checkBox->setCheckState(Qt::Unchecked);
  36.     }
  37.     else
  38.          QStyledItemDelegate::setEditorData(editor,index);
  39. }


  40. void CheckBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
  41. {
  42.     if(index.isValid() && index.column() == 0)
  43.     {
  44.         QCheckBox *checkBox = static_cast<QCheckBox*>(editor);
  45.         QString value;
  46.         if(checkBox->checkState() == Qt::Checked)
  47.             value = "Y";
  48.         else
  49.             value = "N";

  50.         model->setData(index, value);
  51.     }
  52.     else
  53.     {
  54.         QStyledItemDelegate::setModelData(editor, model, index);
  55.     }

  56. }

  57. void CheckBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
  58. {
  59.     if(index.isValid() && index.column() == 0)
  60.             editor->setGeometry(option.rect);
  61.     else
  62.         QStyledItemDelegate::updateEditorGeometry(editor, option, index);


  63. }

  64. ///////////////////////////////////////////////////////////////////////////////////////
  65. void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
  66. {
  67.     QStyleOptionViewItemV4 viewItemOption(option);

  68.     if (index.column() == 0) {
  69.         const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
  70.         QRect newRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
  71.                                             QSize(option.decorationSize.width() + 5,option.decorationSize.height()),
  72.                                             QRect(option.rect.x() + textMargin, option.rect.y(),
  73.                                                   option.rect.width() - (2 * textMargin), option.rect.height()));
  74.         viewItemOption.rect = newRect;
  75.     }
  76.     QStyledItemDelegate::paint(painter, viewItemOption, index);




  77. }


  78. bool ItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
  79. {
  80.     Q_ASSERT(event);
  81.     Q_ASSERT(model);

  82.     // make sure that the item is checkable
  83.     Qt::ItemFlags flags = model->flags(index);
  84.     if (!(flags & Qt::ItemIsUserCheckable) || !(flags & Qt::ItemIsEnabled))
  85.         return false;
  86.     // make sure that we have a check state
  87.     QVariant value = index.data(Qt::CheckStateRole);
  88.     if (!value.isValid())
  89.         return false;
  90.     // make sure that we have the right event type
  91.     if (event->type() == QEvent::MouseButtonRelease) {
  92.         const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
  93.         QRect checkRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
  94.                                               option.decorationSize,
  95.                                               QRect(option.rect.x() + (2 * textMargin), option.rect.y(),
  96.                                                     option.rect.width() - (2 * textMargin),
  97.                                                     option.rect.height()));
  98.         if (!checkRect.contains(static_cast<QMouseEvent*>(event)->pos()))
  99.             return false;
  100.     } else if (event->type() == QEvent::KeyPress) {
  101.         if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space&& static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
  102.             return false;
  103.     } else {
  104.         return false;
  105.     }
  106.     Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
  107.                             ? Qt::Unchecked : Qt::Checked);
  108.     return model->setData(index, state, Qt::CheckStateRole);


  109. }
复制代码
mysqlquerymodel.h
  1. #include <QSqlQueryModel>
  2. #include<QApplication>
  3. #include<QModelIndex>
  4. #include<QSqlTableModel>
  5. class MySqlQueryModel : public QSqlQueryModel
  6. {
  7.     Q_OBJECT
  8. public:
  9.     explicit MySqlQueryModel(QObject * = 0);

  10. public:
  11.     Qt::ItemFlags flags(const QModelIndex &index) const;
  12.     bool setData(const QModelIndex &index, const QVariant &value, int role);
  13.     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;   
  14. };
复制代码
mysqlquerymodel.cpp
  1. #include "mysqlquerymodel.h"
  2. #include<QSqlQuery>
  3. #include<QStandardItem>
  4. MySqlQueryModel::MySqlQueryModel(QObject *parent) :
  5.     QSqlQueryModel(parent)
  6. {

  7. }

  8. Qt::ItemFlags MySqlQueryModel::flags(
  9.        const QModelIndex &index) const //返回表格是否可更改的标志
  10. {
  11.     Qt::ItemFlags flags = QSqlQueryModel::flags(index);
  12.     if (index.column() == 0) //第1个属性可更改
  13.     {
  14.         return Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsEditable;
  15.     }
  16.     else
  17.         return flags;
  18. }


  19. QVariant MySqlQueryModel::data(const QModelIndex &index,  int role) const
  20. {
  21.     QVariant value = QSqlQueryModel::data(index, role);
  22.     if (role == Qt::CheckStateRole && index.column() == 0)
  23.         return (QSqlQueryModel::data(index).toInt() != 0) ? Qt::Checked : Qt::Unchecked;
  24.     else
  25.         return value;
  26. }

  27. bool MySqlQueryModel::setData(const QModelIndex &index, const QVariant &value, int role)
  28. {
  29.     if (!index.isValid())
  30.         return false;
  31.     if (role == Qt::CheckStateRole)
  32.     {
  33.         if ((Qt::CheckState)value.toInt() == Qt::Checked)
  34.         {
  35.             //user has checked item
  36.             return true;
  37.         }
  38.         else
  39.         {
  40.             //user has unchecked item
  41.             return true;
  42.         }
  43.     }
  44.     return false;
  45. }

复制代码
加载delegate后,checkbox居中显示,如下图:

这时问题来了,我必须双击才能进入cell勾选checkbox,并且checkbox的位置跑到了左边,如下图:


并且当鼠标焦点转到其他地方时,checkbox会复位,且刚才打的勾也没了,回到第一张图的状态。

这个复选框整了我好几天了,各位大虾帮忙看看,万分感谢!
附件: 您需要 登录 才可以下载或查看,没有帐号?立即注册

最佳答案

查看完整内容

上面的所有代码都搞明白了吗? 可以尝试搞明白Qt的模型视图编程,委托是干什么的,需要设置哪些内容。
回复

使用道具 举报

累计签到:1569 天
连续签到:1 天
2014-3-12 17:32:35 显示全部楼层
Qthm 发表于 2014-3-18 09:43
没人做过类似的东西吗,提供点思路也好啊

上面的所有代码都搞明白了吗?

可以尝试搞明白Qt的模型视图编程,委托是干什么的,需要设置哪些内容。

回复

使用道具 举报

累计签到:99 天
连续签到:1 天
2014-3-12 17:38:55 显示全部楼层
mydelegate.cpp中82行以后的代码请忽略,是另一个委托的代码
回复

使用道具 举报

累计签到:99 天
连续签到:1 天
2014-3-14 10:02:58 显示全部楼层
自己顶,希望大神能看到
回复

使用道具 举报

累计签到:99 天
连续签到:1 天
2014-3-18 09:43:44 显示全部楼层
没人做过类似的东西吗,提供点思路也好啊
回复

使用道具 举报

累计签到:99 天
连续签到:1 天
2014-3-20 16:53:17 显示全部楼层
yafeilinux 发表于 2014-3-18 11:23
上面的所有代码都搞明白了吗?

可以尝试搞明白Qt的模型视图编程,委托是干什么的,需要设置哪些内容。

谢谢yafei老师,问题已经解决,还是得静下心来好好看文档啊,过阵子有空我会把代码和思路贴出来,给遇到类似问题的朋友一些参考。
回复

使用道具 举报

累计签到:1 天
连续签到:1 天
2015-8-29 16:24:51 显示全部楼层
楼主不厚道啊,提出了问题,也要出来说一下解决方法

这个问题主要是因为TabelView默认也有一个CheckBox,可以在model中的flags()方法中将这个checkbox使能

参考http://qimo601.iteye.com/blog/1530232
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了