5

I know how to set text labels into row or column headers. But I want to do something like this:

https://i.stack.imgur.com/eMM6U.jpg

I don't find any info on how to do the thing inside the red circumference. I'm starting to believe this can't be done with QTableWidget.

Thanks ;)

Jorge C
  • 53
  • 4

2 Answers2

2

I think that it is impossible with standard headers (QHeaderView) because of:

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.

So you need forgot about it and disable it, you should implement your own headers(set your color, your text and so on), but I of course will help with meaning/title. I achieved this with next item delegate:

.h:

#ifndef ITEMDELEGATEPAINT_H
#define ITEMDELEGATEPAINT_H

#include <QStyledItemDelegate>

class ItemDelegatePaint : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit ItemDelegatePaint(QObject *parent = 0);
    ItemDelegatePaint(const QString &txt, QObject *parent = 0);


protected:
    void paint( QPainter *painter,
                const QStyleOptionViewItem &option,
                const QModelIndex &index ) const;
    QSize sizeHint( const QStyleOptionViewItem &option,
                    const QModelIndex &index ) const;
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget * editor, const QModelIndex & index) const;
    void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const;
    void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const;

signals:

public slots:

};

#endif // ITEMDELEGATEPAINT_H

But all these method is not very useful here, you can implement it yourself with some specific actions, I will show you main method - paint()

void ItemDelegatePaint::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if(index.row() == 0 && index.column() == 0)
    {
        QRect source1 = QRect(option.rect.topLeft(),option.rect.size()/2);
        QRect source2 = QRect(option.rect.topLeft(),option.rect.size()/2);

        painter->drawLine(option.rect.topLeft(),option.rect.bottomRight());

        source1.moveTopLeft(source1.topLeft() += QPoint(source1.size().width(),0));
        painter->drawText(source1,"agent reagent");

        source2.moveBottomLeft(source2.bottomLeft() += QPoint(0,source2.size().height()));
        painter->drawText(source2,"hallide ion");
    }

    else
    {
        QStyledItemDelegate::paint(painter,option,index);
    } 
}

This code shows main idea and it is not final version, but you should do all these specific things by yourself. Of course this approach is not very easy, you can just create picture and set it to cell, but in this case picture will not be good scalable. My code works normal if user will resize some headers. To prove, see screenshots with different sizes.

enter image description here

enter image description here

Jablonski
  • 18,083
  • 2
  • 46
  • 47
  • Thanks ;). I thought there could be some trivial way to do it with the standard header that i'm not aware. I understood your roundabout to the problem. Now I'm thinking if it is worth writing so much code to construct my own headers just to show that simple header's meaning. – Jorge C Feb 26 '15 at 11:25
  • this solution for QTableView works in QTableWidget too: http://stackoverflow.com/questions/22635867/is-it-possible-to-set-the-text-of-the-qtableview-corner-button – a_manthey_67 Feb 26 '15 at 11:44
1

if text elements as shown here

textelements in cornerButton

are sufficient, it can be done with standard header and the solution from the link i posted in my comment:

from PyQt5 import QtCore, QtWidgets

class MyTableWidget(QtWidgets.QTableWidget):
    def __init__(self, parent = None):
        QtWidgets.QTableWidget.__init__(self, parent)
        self.setRowCount(4)
        self.setColumnCount(5)
        self.items = []
        self.items.append(['white ppt','no reaction', 'no reaction', 'no reaction', 'no reaction'])
        self.items.append(['no reaction','white ppt', 'dissolves', 'dissolves', 'no reaction'])
        self.items.append(['no reaction','pale yellow\nprecipitate', 'dissolves\npartly', 'dissolves', 'no reaction'])
        self.items.append(['no reaction','yellow ppt', 'does not\ndissolve', 'does not\ndissolve', 'turns\nblue'])
        self.horizontalHeader().setFixedHeight(90)
        self.verticalHeader().setFixedWidth(120)
        self.hh = ['Ca(NO\u2083)\u2082', 'AgNO\u2083','AgNO\u2083\n+\nNH\u2083','AgNO\u2083\n+\nNa\u2083S\u2082O\u2083','Starch\n+\nNaOCl']
        self.vh = ['NaF', 'NaCl', 'NaBr or KBR', 'NaJ']

        self.addItems()
        self.addHeaderItems()
        # text in cornerButton
        btnTxt = '{: >15}\n{: >19}\n{:<}\n{:<}'.format('reagent', '\u21D2','halide', 'ion \u21D3')

        # add cornerbutton from http://stackoverflow.com/questions/22635867/is-it-possible-to-set-the-text-of-the-qtableview-corner-button
        btn = self.findChild(QtWidgets.QAbstractButton)
        btn.setText(btnTxt)
        btn.installEventFilter(self)

        opt = QtWidgets.QStyleOptionHeader()
        opt.text = btn.text()    
        # end cornerbutton 

    def addItems(self):  
        for r in range(0,len(self.items)):
            for c in range(0,len(self.items[r])):
                item = QtWidgets.QTableWidgetItem()
                item.setText(self.items[r][c])
                self.setItem(r,c,item)

    def addHeaderItems(self):
        for i in range(0,len(self.hh)):
            item = QtWidgets.QTableWidgetItem()
            item.setText(self.hh[i])
            self.setHorizontalHeaderItem(i,item)
            self.setColumnWidth(i,150)
        for i in range(0,len(self.vh)):
            item = QtWidgets.QTableWidgetItem()
            item.setText(self.vh[i])
            self.setVerticalHeaderItem(i,item)
            self.setRowHeight(i,60)

        # eventfilter from http://stackoverflow.com/questions/22635867/is-it-possible-to-set-the-text-of-the-qtableview-corner-button
    def eventFilter(self, obj, event):
        if event.type() != QtCore.QEvent.Paint or not isinstance(
            obj, QtWidgets.QAbstractButton):
            return False

        # Paint by hand (borrowed from QTableCornerButton)
        opt = QtWidgets.QStyleOptionHeader()
        opt.initFrom(obj)
        styleState = QtWidgets.QStyle.State_None
        if obj.isEnabled():
            styleState |= QtWidgets.QStyle.State_Enabled
        if obj.isActiveWindow():
            styleState |= QtWidgets.QStyle.State_Active
        if obj.isDown():
            styleState |= QtWidgets.QStyle.State_Sunken
        opt.state = styleState
        opt.rect = obj.rect()
        # This line is the only difference to QTableCornerButton
        opt.text = obj.text()
        opt.position = QtWidgets.QStyleOptionHeader.OnlyOneSection
        painter = QtWidgets.QStylePainter(obj)
        painter.drawControl(QtWidgets.QStyle.CE_Header, opt)

        return True

if painter.drawControl()-method is replaced by any other painter.draw...()-method arbitrary elements incl. graphics can be drawn on cornerButton.

a_manthey_67
  • 4,046
  • 1
  • 17
  • 28
  • Thank you for your answer. I understood what you said but for my work i think this solution is a bit overkill and for now I'm going another way. – Jorge C Mar 01 '15 at 22:56
  • ok. I enjoyed to follow up your question and added how to draw the diagonal line. – a_manthey_67 Mar 02 '15 at 21:00