我們在Qt 4.6.3中使用了一個QTableView
,並且需要一列只在每個單元格中有一個複選框。我們使用QAbstractTableModel
的自定義子類作爲QTableView
的模型。現在,我們有一個複選框,通過設置Qt::ItemIsUserCheckable
標誌。但我們無法弄清楚如何擺脫複選框旁邊的空白文本框!Qt QTableView如何只有一個複選框列
我們如何才能使列只有有一個複選框,沒有別的?
我們在Qt 4.6.3中使用了一個QTableView
,並且需要一列只在每個單元格中有一個複選框。我們使用QAbstractTableModel
的自定義子類作爲QTableView
的模型。現在,我們有一個複選框,通過設置Qt::ItemIsUserCheckable
標誌。但我們無法弄清楚如何擺脫複選框旁邊的空白文本框!Qt QTableView如何只有一個複選框列
我們如何才能使列只有有一個複選框,沒有別的?
這是一個解決方案。爲使此功能正常運行,您的列應設置而不是已設置Qt::ItemIsEditable
或Qt::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);
}
他們在qtcentre有同樣的問題。他們在那裏與代表們達成了一個解決方案,也許你應該看看那些。
注(即不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())
raorao和@Niklas,感謝這個音譯,但我無法讓代碼工作。我已經發布了一個後續[here。](http://stackoverflow.com/questions/17748546/pyqt-column-of-checkboxes-in-a-qtableview)以及我的實現示例。 – drexiya 2013-07-19 14:33:14
@Dave Mateer真正令人印象深刻....我有點困惑,如果不是(index.flags()&Qt.ItemIsEditable)> 0:'。爲什麼要檢查索引上是否存在標誌? – neuronet 2015-07-20 17:02:02
似乎更像是評論而不是答案? – neuronet 2015-07-16 20:23:45