Как заменить checkBox на radioButton в QTreeWidget?
Материал из Wiki.crossplatform.ru
Версия от 10:25, 15 декабря 2010; Igor_bogomolov (Обсуждение | вклад)
Что бы заменить checkBox на radioButton в QTreeWidget, создадим собственный делегат на основе QItemDelegate и переопределим в нём метод paint следующим образом.
Замечание: | В коде используются не документированные возможности Qt. |
#define RadioButtonRole Qt::UserRole void RadioDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (index.data(RadioButtonRole).toBool() && index.flags().testFlag(Qt::ItemIsUserCheckable)) { QString data = index.data(Qt::DisplayRole).toString(); QRect displayRect, checkRect, textRect, decorationRect; QRect rect = option.rect; rect.setWidth(option.decorationSize.width()); displayRect = textRectangle(painter, rect ,option.font, data); QPixmap pixmap; QVariant value = index.data(Qt::DecorationRole); if (value.isValid()) { pixmap = decoration(option, value); decorationRect = QRect(QPoint(0, 0), pixmap.size()); } checkRect = check(option, option.rect, Qt::Checked); doLayout(option, &checkRect, &decorationRect, &textRect, false); QStyleOptionButton styleOptionButton; styleOptionButton.rect = checkRect; styleOptionButton.state = option.state; if (index.data(Qt::CheckStateRole) == Qt::Checked) { styleOptionButton.state |= QStyle::State_On; styleOptionButton.state &=~ QStyle::State_Off; } else { styleOptionButton.state |= QStyle::State_Off; styleOptionButton.state &=~ QStyle::State_On; } drawBackground(painter, option, index); QApplication::style()->drawPrimitive(QStyle::PE_IndicatorRadioButton, &styleOptionButton, painter); drawDisplay(painter, option, textRect, data); drawFocus(painter, option, displayRect); } else { QItemDelegate::paint(painter, option, index); } }
Далее нам необходимо сделать так, что бы только для одного элемента родительской ветки индикатор был в состоянии checked. Сделать это так же на уровне делегата, переопределив метод editorEvent
bool RadioDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { if (event->type() == QEvent::MouseButtonRelease) { if (index.data(RadioButtonRole).toBool() && index.flags().testFlag(Qt::ItemIsUserCheckable)) { QRect checkRect, emptyRect; Qt::ItemFlags flags = index.model()->flags(index); if (flags.testFlag(Qt::ItemIsUserCheckable)) checkRect = check(option, option.rect, Qt::Checked); doLayout(option, &checkRect, &emptyRect, &emptyRect, false); QMouseEvent *mouse_event = static_cast<QMouseEvent*>(event); if (checkRect.contains(mouse_event->pos())) { bool state = index.data(Qt::CheckStateRole).toBool(); if (state == 0) { model->setData(index, Qt::Checked, Qt::CheckStateRole); QModelIndex parentItem = index.parent(); int rowCount = model->rowCount(parentItem); for (int i=0; i!=rowCount; ++i) { QModelIndex child = parentItem.child(i,0); if (child != index) model->setData(child, Qt::Unchecked, Qt::CheckStateRole); } } return true; } } } return QItemDelegate::editorEvent(event,model,option,index); }