Align checkable items in qTableWidget

12,360

Solution 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

Solution 2

An example that worked using pyqt4. Adapted from falsinsoft

qcheck box centre inside pyqt4 atble widget

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)

Solution 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:

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.

Share:
12,360
Aleksandar
Author by

Aleksandar

Python developer beginner

Updated on June 25, 2022

Comments

  • Aleksandar
    Aleksandar almost 2 years

    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 enter image description here 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.

  • Aleksandar
    Aleksandar about 11 years
    1 - tableWidget.setFocusPolicy(QtCore.Qt.NoFocus) helps with focus border (I have only mouse events in table, so tnx for that) 2 - Can't do with Python. setCheckState is not working, I need it to be done automaticaly in some cases 3 - Can't do. I have few columns with checkboxes and I need them separated. 4 - delegate from example removes focus (solved in item no. 1), can you give me example where it's used for alignment?
  • Aleksandar
    Aleksandar about 11 years
    I guess that's it. Didn't have time to translate it to python but it seems legit. Bounty is yours
  • Dmitry Sazonov
    Dmitry Sazonov about 11 years
    Feel free to ask, if you'll have additional questions.