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.