2010-07-29 5 views
14

Qt 4.6.3에서 QTableView을 사용하고 있으며 각 셀에 확인란이있는 열이 필요합니다. 우리는 QTableView의 모델로 QAbstractTableModel의 사용자 정의 하위 클래스를 사용하고 있습니다. 지금은 Qt::ItemIsUserCheckable 플래그를 설정하여 체크 박스가 있습니다. 그러나 우리는 확인란 옆의 빈 텍스트 상자를 제거하는 방법을 알아낼 수 없습니다!Qt QTable 체크 박스 만 표시하는 방법

어떻게하면 에만에만 체크 박스가있을 수 있습니까?

답변

15

다음은 해결책입니다. 이 작업을 올바르게 수행하려면 이 아니고Qt::ItemIsEditable 또는 Qt::ItemIsUserCheckable 플래그가 설정되어 있어야합니다. 이 Qt::DisplayRole에서 부울 값을 읽고 Qt::EditRolesetData()를 호출

#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

8

주 (즉 하지Qt::CheckStateRole.) : 데이브의 대답은 파이썬 사용 PySide 또는 PyQt4에 대해서도 작동합니다. 나는 그것을 번역했고, 잘 작동한다. 또한 체크 박스가 사용자 입력을 허용하지 않고 셀을 편집 할 수없는 경우 ReadOnly 상태로 표시되는 기능을 추가했습니다. Dave에게 감사드립니다.

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,이 음역에 감사드립니다. 그러나 코드를 작동시킬 수 없습니다. 내 구현의 예를 들어 후속 조치 [여기.] (http://stackoverflow.com/questions/17748546/pyqt-column-of-checkboxes-in-a-qqableview)를 게시했습니다. – drexiya

+0

@Dave Mateer 정말 인상적 .... 나는 그렇지 않다면 (index.flags() & Qt.ItemIsEditable)> 0 :'로 약간 혼란 스럽다. 인덱스에 플래그가 있는지 확인해야하는 이유는 무엇입니까? – neuronet