2010-07-29 26 views
14

Chúng tôi đang sử dụng QTableView với Qt 4.6.3 và cần cột chỉ có hộp kiểm trong mỗi ô. Chúng tôi đang sử dụng một lớp con tùy chỉnh của QAbstractTableModel làm mô hình cho QTableView. Ngay bây giờ, chúng tôi có một hộp kiểm bằng cách đặt cờ Qt::ItemIsUserCheckable. Nhưng chúng tôi không thể tìm ra cách để loại bỏ hộp văn bản trống bên cạnh hộp kiểm!Qt QTableView cách chỉ có một cột hộp kiểm

Làm cách nào để chúng tôi có thể làm cho cột chỉ có hộp kiểm, không có gì khác?

Trả lời

15

Đây là giải pháp. Để làm việc này đúng cách, cột của bạn nên không có các cờ Qt::ItemIsEditable hoặc Qt::ItemIsUserCheckable được đặt. Đây đọc các giá trị boolean từ Qt::DisplayRole và gọi setData() với 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

Họ gặp sự cố tương tự tại qtcentre. Ở đó họ đã đến một giải pháp với các đại biểu, có lẽ bạn nên có một cái nhìn vào những người.

+0

Dường như nhận xét hơn là câu trả lời? – neuronet

8

Lưu ý (ví dụ: khôngQt::CheckStateRole.): Câu trả lời của Dave cũng làm việc cho Python sử dụng PySide hoặc PyQt4. Tôi đã dịch nó và nó hoạt động rất tốt. Ngoài ra, tôi đã thêm chức năng mà hộp kiểm không chấp nhận đầu vào của người dùng và được hiển thị trong trạng thái ReadOnly nếu ô không thể chỉnh sửa được. Cảm ơn Dave về mã của bạn!

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 và @Niklas, cảm ơn cho phiên âm này, nhưng tôi không thể nhận được mã để hoạt động. Tôi đã đăng một theo dõi [ở đây.] (Http://stackoverflow.com/questions/17748546/pyqt-column-of-checkboxes-in-a-qtableview) với một ví dụ về việc thực hiện của tôi. – drexiya

+0

@Dave Mateer Rất ấn tượng .... Tôi hơi bối rối bởi 'if not (index.flags() & Qt.ItemIsEditable)> 0:'. Tại sao kiểm tra sự tồn tại của cờ trên chỉ mục? – neuronet

Các vấn đề liên quan