Как заменить checkBox на radioButton в QTreeWidget?

Материал из Wiki.crossplatform.ru

Версия от 10:25, 15 декабря 2010; Igor_bogomolov (Обсуждение | вклад)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

right Что бы заменить checkBox на radioButton в QTreeWidget, создадим собственный делегат на основе QItemDelegate и переопределим в нём метод paint следующим образом.

Замечание Замечание: Это только минимальный пример, демонстрирующий, как можно достичь нужного функционала.
В данном примере, элементам дерева, для которых нужно установить индикатор radioButton, устанавливается Qt::UserRole в состояние true.
Замечание Замечание: В коде используются не документированные возможности 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);
}

[править] Смотрите также

[править] Обсуждение

Обсудить на форуме...