HowTo draw pixmap in QHeaderView section using delegate? - qt

Problem: I need to draw small pixmap to QHeaderView section like presented on this figure (pixmap located on the right corner of the section, marked with red square):
As I understand, there is two ways to do that:
reimplement QHeaderView's paintSection() method.
create an delegate from QStyledItemDelegate class and reimplement paint() method.
If I tried (1) variant with this code below, filter pixmap are not shown at all:
void DecorativeHeaderView::paintSection( QPainter* painter, const QRect& rect, int logicalIndex ) const
{
if( !rect.isValid() )
{
return;
}
// get the state of the section
QStyleOptionHeader option;
initStyleOption( &option );
// setup the style options structure
option.rect = rect;
option.section = logicalIndex;
option.iconAlignment = Qt::AlignVCenter | Qt::AlignHCenter;
QVariant variant = model()->headerData( logicalIndex, orientation(), Qt::DecorationRole );
option.icon = qvariant_cast< QIcon >( variant );
if( option.icon.isNull() )
{
option.icon = qvariant_cast< QPixmap >( variant );
}
// draw the section
if( !option.icon.isNull() )
{
style()->drawControl( QStyle::CE_Header, &option, painter, this );
}
else
{
QHeaderView::paintSection( painter, rect, logicalIndex );
// HERE is where I'm trying to draw my filter picture!!!
if( logicalIndex == filteredLogicalIndex_ )
{
QPixmap pixmap( ":/spreadsheet/images/spreadsheet/filter_icon_table.png" );
int x = rect.right() - pixmap.width();
int y = rect.top() + ( rect.height() - pixmap.height() ) / 2;
painter->drawPixmap( QPoint( x, y ), pixmap );
}
}
}
The (2) variant is this:
class HeaderDelegate : public QStyledItemDelegate
{
Q_OBJECT
Q_DISABLE_COPY( HeaderDelegate )
public:
HeaderDelegate( QObject* parent = 0 ) : QStyledItemDelegate( parent ) {}
virtual ~HeaderDelegate() {}
virtual void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
}; // HeaderDelegate
void HeaderDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
// THIS method never starts!!!
if( index.column() == 2 )
{
QPixmap pixmap( ":/spreadsheet/images/spreadsheet/filter_icon_table.png" );
int x = option.rect.right() - pixmap.width();
int y = option.rect.top() + ( option.rect.height() - pixmap.height() ) / 2;
painter->save();
painter->drawPixmap( QPoint( x, y ), pixmap );
painter->restore();
}
QStyledItemDelegate::paint( painter, option, index );
}
DecorativeHeaderView::DecorativeHeaderView( Qt::Orientation orientation, QWidget* parent /* = 0 */ )
: QHeaderView( orientation, parent )
, filteredLogicalIndex_( -1 )
{
setItemDelegate( new HeaderDelegate( this ) );
}
Delegate created, but function did not start the paint() method!
Any help?
Thanks!

It Seems like it isn't possible at this time.
From Qt documentation:
Note: Each header renders the data for each section itself, and does not rely on a delegate. As a result, calling a header's setItemDelegate() function will have no effect.
How to have dynamic pixmap in a QHeaderView item
But you may override QHeaderView::paintSection method.
subclassing-QHeaderView
class HeaderView : public QHeaderView {
Q_OBJECT
public:
HeaderView(Qt::Orientation orientation, QWidget * parent = 0)
: QHeaderView(orientation, parent), p("333222.jpeg") {
}
int sectionSizeHint ( int /*logicalIndex*/ ) const { return p.width(); }
protected:
void paintSection(QPainter * painter, const QRect & rect, int /*logicalIndex*/) const {
painter->drawPixmap(rect, p);
}
private:
QPixmap p;
};

Related

QT Custom QStyle for QTabBar and QIcon

I have customize a Qtabbar's QMdiarea to get horizontal tab instead of vertical tab like this :
http://www.qtcentre.org/wiki/index.php?title=Customizing_QTabWidget%27s_QTabBar
But i want to insert icon in my QTabBar.
If I apply my custom style to my QTabBar my icons doesn't appear.
If I don't apply, my icon appear.
here my custom style :
class CustomTabStyle : public QPlastiqueStyle
{
Q_OBJECT
public:
QSize sizeFromContents(ContentsType type, const QStyleOption *option,const QSize &size, const QWidget *widget) const
{
QSize s = QPlastiqueStyle::sizeFromContents(type, option, size, widget);
if (type == QStyle::CT_TabBarTab)
s.transpose();
return s;
}
void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
{
if (element == CE_TabBarTabLabel)
{
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option))
{
QStyleOptionTab opt(*tab);
opt.shape = QTabBar::RoundedNorth;
QPlastiqueStyle::drawControl(element, &opt, painter, widget);
return;
}
}
QPlastiqueStyle::drawControl(element, option, painter, widget);
}
};
and i apply my style like this :
mMdiAreaDock=aMdiArea;
m_pMdiAreaTabBar = NULL;
QObjectList listChildren = mMdiAreaDock->children();
for (QObjectList::Iterator i = listChildren.begin(); i != listChildren.end(); ++i)
{
if (QString((*i)->metaObject()->className()) == "QTabBar")
{
m_pMdiAreaTabBar = dynamic_cast<QTabBar*>(*i);
break;
}
}
m_pMdiAreaTabBar->setStyle(new CustomTabStyle());
return 0;
where mMdiAreaDock is an QMdiArea
and m_pMdiAreaTabBar is a QTabBar
Look at this code:
const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option));
QStyleOptionTab opt(*tab);
option is an instance of QStyleOptionTabV2.
When you create a new object QStyleOptionTab opt with copy constructor, you lose some important data which extended QStyleOptionTabV2 contains including information about an icon.
Use this code instead:
if (const QStyleOptionTabV2 *tab = qstyleoption_cast<const QStyleOptionTabV2 *>(option))
{
QStyleOptionTabV2 opt(*tab);
opt.shape = QTabBar::RoundedNorth;
QPlastiqueStyle::drawControl(element, &opt, painter, widget);
return;
}
ps. I used this code to assign an icon for a specific tab:
m_pMdiAreaTabBar->setTabIcon(0, icon);

Custom ItemDelegate for QListView State_Selected

I created CustomItemDelegate from QStyledItemDelegate and i'm using the paint() method to give a better look to my QListView.
If I click on an item, option.state never has State_Selected, why is that?
I have a selection model, single, row, and the selection rectangle is visible.
qDebug only prints out these:
QStyle::State( "Active | Enabled" )
QStyle::State( "Active | Enabled | MouseOver" )
void SyrupItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QRect rect = option.rect;
qDebug() << option.state;
if (option.state & QStyle::State_Selected)
{
painter->drawRoundedRect(option.rect,5,5);
painter->setPen(QPen(QPalette::HighlightedText ) );
if (option.state & QStyle::State_Active)
{
painter->setBrush(QBrush(QPalette().highlight()));
} else
{
//painter->setBrush(QBrush(QPalette().color(QPalette::Inactive,
//QPalette::Highlight)));
QLinearGradient gradient(0, 0, 0, 100);
gradient.setColorAt(0.0, QColor(0,0,230));
gradient.setColorAt(1.0, QColor(250,250,250));
painter->setBrush(gradient);
}
} else
painter->setPen(QPen(QPalette::Text));
if ( !index.isValid() )
return;
int row = index.row();
// painter->save();
// painter->setRenderHint(QPainter::Antialiasing,true);
QString res = index.sibling(row,SyrupsSQLModel::SYRUP_NM_COL_INDEX).data().toString();
QRectF rc(rect);
rc.setTop(rc.top()+ PADDING);
rc.setLeft(rc.left()+ 2* PADDING + IMG_WIDTH);
QFont font = option.font;
font.setPointSize(font.pointSize()+4);
painter->setFont(font);
painter->drawText(rc,res);
res = index.sibling(row,SyrupsSQLModel::SYRUP_GRP_COL_INDEX).data().toString().toLower();
rc.setTop(rect.top()+PADDING );
rc.setLeft(rect.left()+PADDING );
painter->drawPixmap(rc.topLeft(),QIcon(":/prodgrp/"+res).pixmap(QSize(IMG_WIDTH,IMG_HEIGHT)));
//SyrupsSQLModel::FORMULA_COL_INDEX:
//SyrupsSQLModel::SYRUP_ID_COL_INDEX:
//Painter->restore();
}
I'm using Qt 5.0.2 32bit (Win).
The problem was in the delegate class I reimplemented editorEvent() function badly. I commented out that sections and it works.

Customizing scrollbar over QListWidget

I'd like to implement my own semi-transparent scrollbar, that draws on top of the QListWidget instead of taking up permanent space in its viewport. I do not wish to use QML as my QListWidget and its dynamic content is already fully developed over 6 months now.
How can I achieve that. Stylesheets are useless for that purpose as they will not determine the positioning of the scrollbar. I'd like it to be on top of the QListWidget, not on its side, taking up its space.
I'm talking about something in the neighborhood of this:
Any hints as to how to do that will be appreciated.
What you are trying to do is a perfect example of one thing that persistently annoys me about qt - if there is some graphical effect that Qt's designers haven't thought of, creating it on your own is a pain, constant fight against Qt, and usually ends with giving up anyway.
I suspect that you do it with small screens on your mind (cell phones? tablets?), so i guess there is no other way to solve this problem.
What I am trying here is hacky, but otherwise you would probably have to rewrite entire scrollbar yourself just to add those few missing details. My proposition is:
#ifndef MYSCROLLBAR_H
#define MYSCROLLBAR_H
#include <QScrollBar>
class MyScrollBar : public QScrollBar
{
Q_OBJECT
public:
explicit MyScrollBar(QWidget *parent = 0);
protected:
void showEvent ( QShowEvent * event );
signals:
public slots:
void updateMask();
};
#endif // MYSCROLLBAR_H
And in myscrollbar.cpp
#include "myscrollbar.h"
#include <QPaintEvent>
#include <QRegion>
#include <QStyleOptionSlider>
MyScrollBar::MyScrollBar(QWidget *parent) :
QScrollBar(parent)
{
connect(this, SIGNAL(valueChanged(int)), this, SLOT(updateMask()));
}
void MyScrollBar::updateMask(){
QStyleOptionSlider opt;
initStyleOption(&opt);
QRegion r(style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarSlider, this));
r+= style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarAddLine, this);
r+= style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarSubLine, this);
setMask(r);
}
void MyScrollBar::showEvent ( QShowEvent * event ){
QScrollBar::showEvent(event);
updateMask();
}
Such scroller will be transparent (both visually and event-wise) in any of it's non-vital parts. It still creates some artifacts on widgets laying below it - I guess setMask() was never supposed to be used like this. To mitigate it you can connect valueChanged() signal to update() slot of the viewport of your list widget. This worked nice on my toy-example, but if you embed custom widgets in your list it might become unbearable to cope with. It might also run you into performance problems in case of more complex applications - especially if you write for mobile platforms.
Alternatively you can just "fork" entire QScrollBar class and simply modify it's paintEvent to use less subControls than SC_All - with additional setAttribute(Qt::WA_OpaquePaintEvent, false); in constructor it should provide visual transparency. Then you should also forward mouse events (if not hitting anything important) to your viewport of list widget (again, trouble with custom widgets in view).
Now what remains is writing your own layout class (or just manually positioning it) that will put both listview and scrollbar on one another in correct positions - QStackedLayout sounds nice, but it allows only one layer to be visible at any given time - clearly not what we are looking for.
Last step is switching off default scrollbars on view, and connecting signals/slots of the default (invisible) scrollbar to slots/signals of your scrollbar, to achieve effect of actual scrolling.
Shortly this will require a LOT of coding to get done. Are you sure that such a simple effect is worth it?
** EDIT: **
I create a layout class for stacking widgets on top of one another - this question gave me motivation to do it finally ;)
#ifndef STACKLAYOUT_H
#define STACKLAYOUT_H
#include <QLayout>
class StackLayout : public QLayout
{
Q_OBJECT
public:
StackLayout();
explicit StackLayout(QWidget *parent);
~StackLayout();
void addItem ( QLayoutItem * item );
int count () const;
Qt::Orientations expandingDirections () const;
bool hasHeightForWidth () const;
int heightForWidth ( int w ) const;
QLayoutItem * itemAt ( int index ) const;
bool isEmpty () const;
QSize maximumSize () const;
int minimumHeightForWidth ( int w ) const;
QSize minimumSize () const;
void setGeometry ( const QRect & r );
QSize sizeHint () const;
QLayoutItem * takeAt ( int index );
private:
QList<QLayoutItem *> itemList;
};
#endif // STACKLAYOUT_H
And the stacklayout.cpp file:
StackLayout::StackLayout()
:QLayout()
{}
StackLayout::StackLayout(QWidget *parent) :
QLayout(parent)
{
}
StackLayout::~StackLayout(){
QLayoutItem *item;
foreach (item, itemList){
delete item;
}
}
void StackLayout::addItem ( QLayoutItem * item ){
itemList.append(item);
}
int StackLayout::count () const{
return itemList.count();
}
Qt::Orientations StackLayout::expandingDirections () const{
Qt::Orientations result = 0;
QLayoutItem *item;
foreach (item, itemList){
result = result | item->expandingDirections();
}
return result;
}
bool StackLayout::hasHeightForWidth () const{
QLayoutItem *item;
foreach (item, itemList){
if (item->hasHeightForWidth())
return true;
}
return false;
}
int StackLayout::heightForWidth ( int w ) const{
int result = 0;
QLayoutItem *item;
foreach (item, itemList){
if (item->hasHeightForWidth())
result = qMax(result, item->heightForWidth(w));
}
return result;
}
QLayoutItem * StackLayout::itemAt ( int index ) const{
if (index<itemList.count())
return itemList[index];
return 0;
}
bool StackLayout::isEmpty () const{
QLayoutItem *item;
foreach (item, itemList){
if (!item->isEmpty())
return false;
}
return true;
}
QSize StackLayout::maximumSize () const{
QSize result=QLayout::maximumSize();
QLayoutItem *item;
foreach (item, itemList){
result = result.boundedTo(item->maximumSize());
}
return result;
}
int StackLayout::minimumHeightForWidth ( int w ) const{
int result = 0;
QLayoutItem *item;
foreach (item, itemList){
if (item->hasHeightForWidth())
result = qMax(result, item->minimumHeightForWidth(w));
}
return result;
}
QSize StackLayout::minimumSize () const{
QSize result=QLayout::minimumSize();
QLayoutItem *item;
foreach (item, itemList){
result = result.expandedTo(item->minimumSize());
}
return result;
}
void StackLayout::setGeometry ( const QRect & r ){
QLayoutItem *item;
foreach (item, itemList){
item->setGeometry(r);
}
}
QSize StackLayout::sizeHint () const{
QSize result=QSize(0,0);
QLayoutItem *item;
foreach (item, itemList){
result = result.expandedTo(item->sizeHint());
}
return result;
}
QLayoutItem * StackLayout::takeAt ( int index ){
if (index < itemList.count())
return itemList.takeAt(index);
return 0;
}
Assuming you already have some nice transparent scrollbar, to insert it you would do:
QWidget* w = new QWidget();
StackLayout* sl = new StackLayout(w);
QListView* lv = new QListView(w);
sl->addWidget(lv);
QHBoxLayout* hbl = new QHBoxLayout();
sl->addItem(hbl);
TransparentScrollBar* tsc = new TransparentScrollBar(w);
hbl->addWidget(tsc,0);
hbl->insertStretch(0,1);
Here is sample code for your questoin.
Not done:
Mouse dragging of scroller
Done:
Support of any mouse hover/leave events
Support of scrolling
Scroll bar is transparent for mouse events
It is good start point for any customization depending on you task. Usage:
GUI::MegaScrollBar *bar = new GUI::MegaScrollBar( ui->listWidget );
bar->resize( 40, 30 ); // First arg - width of scroller
MegaScrollBar.h
#ifndef MEGASCROLLBAR_H
#define MEGASCROLLBAR_H
#include <QWidget>
#include <QPointer>
class QAbstractItemView;
class QResizeEvent;
namespace GUI
{
class MegaScrollBar
: public QWidget
{
Q_OBJECT
public:
MegaScrollBar( QAbstractItemView *parentView );
~MegaScrollBar();
private slots:
void updatePos();
private:
bool eventFilter( QObject *obj, QEvent *event );
void onResize( QResizeEvent *e );
void paintEvent( QPaintEvent * event );
void resizeEvent( QResizeEvent * event );
QPointer< QAbstractItemView > m_view;
QPointer< QWidget > m_scrollBtn;
};
}
#endif // MEGASCROLLBAR_H
MegaScrollBar.cpp
#include "MegaScrollBar.h"
#include <QAbstractItemView>
#include <QEvent>
#include <QResizeEvent>
#include <QScrollBar>
#include <QDebug>
#include <QPainter>
#include "ScrollButton.h"
namespace GUI
{
MegaScrollBar::MegaScrollBar( QAbstractItemView *parentView )
: QWidget( parentView, Qt::FramelessWindowHint )
, m_view( parentView )
{
Q_ASSERT( parentView );
setAttribute( Qt::WA_TranslucentBackground );
setAttribute( Qt::WA_TransparentForMouseEvents );
m_scrollBtn = new ScrollButton( parentView );
m_scrollBtn->setFixedSize( 20, 40 );
m_view->installEventFilter( this );
QScrollBar *sb = m_view->verticalScrollBar();
connect( sb, SIGNAL( valueChanged( int ) ), this, SLOT( updatePos() ) );
}
MegaScrollBar::~MegaScrollBar()
{
removeEventFilter( m_view );
}
bool MegaScrollBar::eventFilter( QObject *obj, QEvent *event )
{
switch ( event->type() )
{
case QEvent::Enter:
m_scrollBtn->show();
break;
case QEvent::Leave:
m_scrollBtn->hide();
break;
case QEvent::Resize:
onResize( static_cast< QResizeEvent * >( event ) );
break;
}
return QWidget::eventFilter( obj, event );
}
void MegaScrollBar::onResize( QResizeEvent *e )
{
const int x = e->size().width() - width();
const int y = 0;
const int w = width();
const int h = e->size().height();
move( x, y );
resize( w, h );
updatePos();
}
void MegaScrollBar::updatePos()
{
QScrollBar *sb = m_view->verticalScrollBar();
const int min = sb->minimum();
const int val = sb->value();
const int max = sb->maximum();
const int x = pos().x() + ( width() - m_scrollBtn->width() ) / 2;
if ( max == 0 )
{
m_scrollBtn->move( x, pos().y() );
return ;
}
const int maxY = height() - m_scrollBtn->height();
const int y = ( maxY * val ) / max;
m_scrollBtn->move( x, y );
}
void MegaScrollBar::paintEvent( QPaintEvent * event )
{
Q_UNUSED( event );
QPainter p( this );
QRect rc( 0, 0, rect().width() - 1, rect().height() - 1 );
// Draw any scroll background
p.fillRect( rc, QColor( 255, 255, 200, 100 ) );
}
void MegaScrollBar::resizeEvent( QResizeEvent * event )
{
Q_UNUSED( event );
updatePos();
}
}
Preview:
It is possible to set up any widget for scroll button: Here is custom one:
ScrollButton.h
#ifndef SCROLLBUTTON_H
#define SCROLLBUTTON_H
#include <QWidget>
namespace GUI
{
class ScrollButton
: public QWidget
{
Q_OBJECT
public:
ScrollButton( QWidget *parent );
~ScrollButton();
private:
void paintEvent( QPaintEvent * event );
};
}
#endif // SCROLLBUTTON_H
ScrollButton.cpp
#include "ScrollButton.h"
#include <QPainter>
#include <QGraphicsOpacityEffect>
#include <QColor>
namespace GUI
{
ScrollButton::ScrollButton( QWidget *parent )
: QWidget( parent )
{
QGraphicsOpacityEffect *op = new QGraphicsOpacityEffect( this );
op->setOpacity( 0.5 );
setGraphicsEffect( op );
}
ScrollButton::~ScrollButton()
{
}
void ScrollButton::paintEvent( QPaintEvent * event )
{
Q_UNUSED( event );
// Draw any scroll button
QPainter p( this );
QRect rc( 5, 5, rect().width() - 6, rect().height() - 6 );
p.fillRect( rc, QColor( 0, 0, 0, 255 ) );
}
}
Please comment, if you can't handle mouse interaction.

QItemDelegate: painting an unwanted QCheckBox

I have an editable model, which inherits QAbstractTableModel. Also have a custom delegate to go with it. This is my first editable model, and I think I'm missing something. I'm pretty much following the examples found at Nokia. My model tells the delegate that the data is editable via flags(). When I do this, it draws a QSpinBox in the cell.
Underlying model is a simple std::map. The key is days, the value is a rate.
Generally, what is painted in any editable cell, is a QCheckBox, but is ghosted out, then the data. If I double-click on the value, I am shown the editor, which happens to be a custom widget based on QDoubleSpinbox.
Qt::ItemFlags my_model_t::flags( const QModelIndex& index ) const
{
if ( !index.isValid() ) {
return Qt::NoItemFlags;
}
if ( index.column() == col_rates ) {
return QAbstractItemModel::flags( index ) | Qt::ItemIsEditable;
}
return QAbstractItemModel::flags( index );
}
QVariant my_model_t::data( const QModelIndex& index, int role ) const
{
if ( !index.isValid() ) {
return QVariant();
}
if ( role == Qt::DisplayRole || Qt::EditRole ) {
if ( static_cast<int>( rates.size() ) <= index.row() ) {
return QVariant();
}
int day = vec[index.row()];
if ( index.column() == col_days ) {
return day;
} else if ( index.column() == col_rates ) {
std::map<int, double>::const_iterator it = rates.find( day );
if ( it != rates.end() ) {
return (*it).second;
}
}
}
return QVariant();
}
QWidget* my_delegate_t::createEditor( QWidget* parent, const QStyleOptionViewItem& /*option*/, const QModelIndex& index ) const
{
gui_spinbox* editor = new gui_spinbox( parent );
if ( index.column() == col_rate ) {
const my_model_t* model = static_cast<my_model_t*>( index.model() );
}
return editor;
}
void my_delegate_t::setEditorData( QWidget* editor, const QModelIndex& index ) const
{
double value = index.model()->data( index, Qt::EditRole ).toDouble();
gui_spinbox* spin_box = static_cast<gui_spinbox*>( editor );
if ( spin_box ) {
spin_box->setValue( value );
}
}
void my_delegate_t::setModelData( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const
{
gui_spinbox* spin_box = static_cast<gui_spinbox*>( editor );
if ( spin_box ) {
double value = spin_box->value();
model->setData( index, value, Qt::EditRole );
}
}
void my_delegate_t::updateEditorGemoetry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& /*index*/ ) const
{
editor->setGeometry( option.rect );
}
I'm not pretty sure about your problem. Do you want to paint a QCheckBox?
In your createEditor method, you created an editor use QSpinbox but in the Title you said it was unwanted.
If you want to be shown an editor based on an QCheckBox when you double clicked an item you just create a checkBox in the createEditor method and use checkBox in setEditorData and setModelData.

HowTo draw border for QTableWidget row?

I'm trying to make a border for rows in QTableWidget with different ways, but all solutions don't respond my requirements. All that I want, is to draw a rectangle around a whole row. I had try QStyledItemDelegate class, but that is not my way, because delegates are used only for item[ row, column ], not for the whole rows or columns.
Here is wrong solution:
/// #brief Рисуем границу вокруг строки.
class DrawBorderDelegate : public QStyledItemDelegate
{
public:
DrawBorderDelegate( QObject* parent = 0 ) : QStyledItemDelegate( parent ) {}
void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
}; // DrawBorderDelegate
void DrawBorderDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
QStyleOptionViewItem opt = option;
painter->drawRect( opt.rect );
QStyledItemDelegate::paint( painter, opt, index );
}
And somewhere in code:
tableWidget->setItemDelegateForRow( row, new DrawBorderDelegate( this ) );
Thanks for help!
Your solution was not far wrong. You just need to be a bit more selective about which edges of the rectangle you draw:
void DrawBorderDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
const QRect rect( option.rect );
painter->drawLine( rect.topLeft(), rect.topRight() );
painter->drawLine( rect.bottomLeft(), rect.bottomRight() );
// Draw left edge of left-most cell
if ( index.column() == 0 )
painter->drawLine( rect.topLeft(), rect.bottomLeft() );
// Draw right edge of right-most cell
if ( index.column() == index.model()->columnCount() - 1 )
painter->drawLine( rect.topRight(), rect.bottomRight() );
QStyledItemDelegate::paint( painter, option, index );
}
Hope this helps!
#include <QTableWidget>
QTableWidget* table = new QTableWidget();
table->resize(400, 250);
table->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
table->setColumnCount(3);
table->setRowCount(2);
//Set Header Label Texts Here
table->verticalHeader ()->hide();
table->horizontalHeader()->hide();
table->setItem(0,0,new QTableWidgetItem("CELL 1"));
table->setItem(0,1,new QTableWidgetItem("CELL 2"));
table->setItem(0,2,new QTableWidgetItem("CELL 3"));
table->setItem(1,0,new QTableWidgetItem("CELL 4"));
table->setItem(1,1,new QTableWidgetItem("CELL 5"));
table->setItem(1,2,new QTableWidgetItem("CELL 6"));
table->setEditTriggers(QAbstractItemView::NoEditTriggers);
table->setFocusPolicy(Qt::NoFocus);
table->setSelectionMode(QAbstractItemView::NoSelection);
table-> setObjectName (QString :: fromUtf8 ("table_"));
table->show();
Stylesheet:
QTableWidget
{
background-color : none;
gridline-color: white; // this border for rows and columns
color:#ffffff;
}
QTableWidget#table_{
border:1px solid #ffffff; // this border for total table
}
sample output
Hope this simple way to helps!!!

Resources