2010-07-29 36 views
14

我們在Qt 4.6.3中使用了一個QTableView,並且需要一列只在每個單元格中有一個複選框。我們使用QAbstractTableModel的自定義子類作爲QTableView的模型。現在,我們有一個複選框,通過設置Qt::ItemIsUserCheckable標誌。但我們無法弄清楚如何擺脫複選框旁邊的空白文本框!Qt QTableView如何只有一個複選框列

我們如何才能使列只有有一個複選框,沒有別的?

回答

15

這是一個解決方案。爲使此功能正常運行,您的列應設置而不是已設置Qt::ItemIsEditableQt::ItemIsUserCheckable標誌。這從Qt::DisplayRole讀取布爾值調用setData()Qt::EditRole

#include "check_box_delegate.h" 

#include <QtGui/QApplication> 
#include <QtGui/QMouseEvent> 

static QRect CheckBoxRect(const QStyleOptionViewItem &view_item_style_options) { 
    QStyleOptionButton check_box_style_option; 
    QRect check_box_rect = QApplication::style()->subElementRect(
     QStyle::SE_CheckBoxIndicator, 
     &check_box_style_option); 
    QPoint check_box_point(view_item_style_options.rect.x() + 
         view_item_style_options.rect.width()/2 - 
         check_box_rect.width()/2, 
         view_item_style_options.rect.y() + 
         view_item_style_options.rect.height()/2 - 
         check_box_rect.height()/2); 
    return QRect(check_box_point, check_box_rect.size()); 
} 

CheckBoxDelegate::CheckBoxDelegate(QObject *parent) 
    : QStyledItemDelegate(parent) { 
} 

void CheckBoxDelegate::paint(QPainter *painter, 
          const QStyleOptionViewItem &option, 
          const QModelIndex &index) const { 
    bool checked = index.model()->data(index, Qt::DisplayRole).toBool(); 

    QStyleOptionButton check_box_style_option; 
    check_box_style_option.state |= QStyle::State_Enabled; 
    if (checked) { 
    check_box_style_option.state |= QStyle::State_On; 
    } else { 
    check_box_style_option.state |= QStyle::State_Off; 
    } 
    check_box_style_option.rect = CheckBoxRect(option); 

    QApplication::style()->drawControl(QStyle::CE_CheckBox, 
            &check_box_style_option, 
            painter); 
} 

// This is essentially copied from QStyledItemEditor, except that we 
// have to determine our own "hot zone" for the mouse click. 
bool CheckBoxDelegate::editorEvent(QEvent *event, 
            QAbstractItemModel *model, 
            const QStyleOptionViewItem &option, 
            const QModelIndex &index) { 
    if ((event->type() == QEvent::MouseButtonRelease) || 
     (event->type() == QEvent::MouseButtonDblClick)) { 
    QMouseEvent *mouse_event = static_cast<QMouseEvent*>(event); 
    if (mouse_event->button() != Qt::LeftButton || 
     !CheckBoxRect(option).contains(mouse_event->pos())) { 
     return false; 
    } 
    if (event->type() == QEvent::MouseButtonDblClick) { 
     return true; 
    } 
    } 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; 
    } 

    bool checked = index.model()->data(index, Qt::DisplayRole).toBool(); 
    return model->setData(index, !checked, Qt::EditRole); 
} 
1

他們在qtcentre有同樣的問題。他們在那裏與代表們達成了一個解決方案,也許你應該看看那些。

+0

似乎更像是評論而不是答案? – neuronet 2015-07-16 20:23:45

8

注(即Qt::CheckStateRole):戴夫的答案也適用於使用Python PySide或PyQt4的。我翻譯了它,它效果很好。此外,我添加了複選框不接受用戶輸入的功能,如果單元格不可編輯,則顯示爲ReadOnly狀態。 感謝戴夫爲您的代碼!

class CheckBoxDelegate(QStyledItemDelegate): 

    def createEditor(self, parent, option, index): 
     ''' 
     Important, otherwise an editor is created if the user clicks in this cell. 
     ''' 
     return None 

    def paint(self, painter, option, index): 
     ''' 
     Paint a checkbox without the label. 
     ''' 
     checked = bool(index.model().data(index, Qt.DisplayRole)) 
     check_box_style_option = QStyleOptionButton() 

     if (index.flags() & Qt.ItemIsEditable) > 0: 
      check_box_style_option.state |= QStyle.State_Enabled 
     else: 
      check_box_style_option.state |= QStyle.State_ReadOnly 

     if checked: 
      check_box_style_option.state |= QStyle.State_On 
     else: 
      check_box_style_option.state |= QStyle.State_Off 

     check_box_style_option.rect = self.getCheckBoxRect(option) 
      if not index.model().hasFlag(index, Qt.ItemIsEditable): 
      check_box_style_option.state |= QStyle.State_ReadOnly 

     QApplication.style().drawControl(QStyle.CE_CheckBox, check_box_style_option, painter) 


    def editorEvent(self, event, model, option, index): 
     ''' 
     Change the data in the model and the state of the checkbox 
     if the user presses the left mousebutton or presses 
     Key_Space or Key_Select and this cell is editable. Otherwise do nothing. 
     ''' 
     if not (index.flags() & Qt.ItemIsEditable) > 0: 
      return False 

     # Do not change the checkbox-state 
     if event.type() == QEvent.MouseButtonRelease or event.type() == QEvent.MouseButtonDblClick: 
      if event.button() != Qt.LeftButton or not self.getCheckBoxRect(option).contains(event.pos()): 
       return False 
      if event.type() == QEvent.MouseButtonDblClick: 
       return True 
     elif event.type() == QEvent.KeyPress: 
      if event.key() != Qt.Key_Space and event.key() != Qt.Key_Select: 
       return False 
     else: 
      return False 

     # Change the checkbox-state 
     self.setModelData(None, model, index) 
     return True 

    def setModelData (self, editor, model, index): 
     ''' 
     The user wanted to change the old state in the opposite. 
     ''' 
     newValue = not bool(index.model().data(index, Qt.DisplayRole)) 
     model.setData(index, newValue, Qt.EditRole) 


    def getCheckBoxRect(self, option): 
     check_box_style_option = QStyleOptionButton() 
     check_box_rect = QApplication.style().subElementRect(QStyle.SE_CheckBoxIndicator, check_box_style_option, None) 
     check_box_point = QPoint (option.rect.x() + 
          option.rect.width()/2 - 
          check_box_rect.width()/2, 
          option.rect.y() + 
          option.rect.height()/2 - 
          check_box_rect.height()/2) 
     return QRect(check_box_point, check_box_rect.size()) 
+0

raorao和@Niklas,感謝這個音譯,但我無法讓代碼工作。我已經發布了一個後續[here。](http://stackoverflow.com/questions/17748546/pyqt-column-of-checkboxes-in-a-qtableview)以及我的實現示例。 – drexiya 2013-07-19 14:33:14

+0

@Dave Mateer真正令人印象深刻....我有點困惑,如果不是(index.flags()&Qt.ItemIsEditable)> 0:'。爲什麼要檢查索引上是否存在標誌? – neuronet 2015-07-20 17:02:02