Align checkable items in qTableWidget

2019-02-22 21:55发布

问题:

In tableWidget I have one column entirely made up of checkable items. I can't figure out how to center the checkbox or at least remove the text-box next to it. As you can see on this picture text-box has that ugly outline when I click on cell, I would like that turned off in entire table if it's possible. I've read that I need to use a delegates to control the positioning of items/icons, but for nooby like me it would take too long to understand that right, so if there is some simple solution that will make that column less ugly, please, examples would be appreciated.

回答1:

That rectangle is a focus recangle and cannot be hidden via an stylesheet.

Edit: So you have four options:

1 - It seems that u can use

 tablewidget->setFocusPolicy(Qt::NoFocus);

But you will lose the ability to process keyboard events. See FocusPolicy

2 - Set the checkable widgetitems as disabled, not selectable through setFlags. I don't know if this is a bug, but in my Qt i will be alowed to still click on checkboxes

3 - Set your first column as checkable though setFlags too, and just dont use that second column. Checkboxes will be shown in same column that the Strings but at left.

4- That custom delegate you dont want to create.

And you got here an example



回答2:

An example that worked using pyqt4. Adapted from falsinsoft

table = QTableWidget()   
cell_widget = QWidget()
chk_bx = QCheckBox()
chk_bx.setCheckState(Qt.Checked)
lay_out = QHBoxLayout(cell_widget)
lay_out.addWidget(chk_bx)
lay_out.setAlignment(Qt.AlignCenter)
lay_out.setContentsMargins(0,0,0,0)
cell_widget.setLayout(lay_out)
tableWidget.setCellWidget(i, 0, cell_widget)


回答3:

Usage:

pView->setItemDelegateForColumn( 1, new DELEGATE::CheckBoxDelegate( this ) );

CheckBoxDelegate.h

#ifndef CHECKBOXDELEGATE_H
#define CHECKBOXDELEGATE_H

#include <QStyledItemDelegate>
#include <QModelIndex>


namespace DELEGATE
{

    class CheckBoxDelegate
        : public QStyledItemDelegate
    {
        Q_OBJECT

    public:
        CheckBoxDelegate( QObject *parent );
        ~CheckBoxDelegate();

        void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
        bool editorEvent( QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index );

    private:
        QModelIndex m_lastClickedIndex;
    };

}


#endif // CHECKBOXDELEGATE_H

CheckBoxDelegate.cpp

#include "CheckBoxDelegate.h"

#include <QApplication>
#include <QStyleOptionButton>
#include <QPainter>
#include <QEvent>
#include <QMouseEvent>


namespace DELEGATE
{

    CheckBoxDelegate::CheckBoxDelegate( QObject *parent )
        : QStyledItemDelegate( parent )
    {
    }

    CheckBoxDelegate::~CheckBoxDelegate()
    {
    }

    void CheckBoxDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
    {
        // Setting parameters
        Qt::CheckState state = (Qt::CheckState)index.data( Qt::CheckStateRole ).toInt();
        QStyleOptionButton opt;

        opt.state = QStyle::State_Enabled; // CheckBox enabled
        if ( option.state & QStyle::State_MouseOver )
            opt.state |= QStyle::State_MouseOver; // Mouse over sell
        switch ( state )  // Check box state
        {
        case Qt::Unchecked:
            opt.state |= QStyle::State_Off;
            break;
        case Qt::PartiallyChecked:
            opt.state |= QStyle::State_NoChange;
            break;
        case Qt::Checked:
            opt.state |= QStyle::State_On;
            break;
        }
        // Check box rect
        opt.rect = QApplication::style()->subElementRect( QStyle::SE_CheckBoxIndicator, &opt, NULL );
        const int x = option.rect.center().x() - opt.rect.width() / 2;
        const int y = option.rect.center().y() - opt.rect.height() / 2;
        opt.rect.moveTo( x, y );

        // Optional: draw hover focus
        if ( option.state & QStyle::State_MouseOver )
            painter->fillRect( option.rect, QBrush( QColor( 0xff, 0xff, 0xaa, 0x60 ) ) );

        // Mandatory: drawing check box
        QApplication::style()->drawControl( QStyle::CE_CheckBox, &opt, painter );
    }

    bool CheckBoxDelegate::editorEvent( QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index )
    {
        switch ( event->type() )
        {
        case QEvent::MouseButtonPress:
            m_lastClickedIndex = index;
            break;

        case QEvent::MouseButtonRelease:
            {
                if ( index != m_lastClickedIndex )
                    break;
                QMouseEvent *e = static_cast< QMouseEvent * >( event );
                if ( e->button() != Qt::LeftButton )
                    break;
                m_lastClickedIndex = QModelIndex();

                QStyleOptionButton opt;
                opt.rect = QApplication::style()->subElementRect( QStyle::SE_CheckBoxIndicator, &opt, NULL );
                const int x = option.rect.center().x() - opt.rect.width() / 2;
                const int y = option.rect.center().y() - opt.rect.height() / 2;
                opt.rect.moveTo( x, y );

                if ( opt.rect.contains( e->pos() ) )
                {
                    // TODO: process click on checkbox logic
                    Qt::CheckState state = (Qt::CheckState)index.data( Qt::CheckStateRole ).toInt();
                    switch ( state )
                    {
                    case Qt::Unchecked:
                        state = Qt::PartiallyChecked;
                        break;
                    case Qt::PartiallyChecked:
                        state = Qt::Checked;
                        break;
                    case Qt::Checked:
                        state = Qt::Unchecked;
                        break;
                    }

                    model->setData( index, state, Qt::CheckStateRole );
                }
                return true;
            }

        default:
            break;
        }

        return QAbstractItemDelegate::editorEvent( event, model, option, index );
    }

}

Sample:

Subjects to improve:

  • Selection drawing
  • Mouse hover processing
  • Double click processing
  • Keyboard edit events // there are a lot of examples in google, stackoverflow

Note: your model should process setData method for Qt::CheckStateRole role.