Thanks for the answer Wysota. In the meantime, I have researched a bit more and implemented tree workable solutions which seem bit more simple. (Primarily because the number of columns should be changeable on the fly, and thereby the headers too.)
FIRST and SECOND:
Forget about QHeaderView, and use the main View. In Qt examples you can find how to lock rows/columns. So, the first way is the most simple one: just use the QAbstractItemView::setIndexWidget(). But this seems a convenience function, given the MVC/MVD paradigm. So in my second try I tried the same with the delegate:
#include <QtGui>
class HeaderObject
: public QWidget{public:
c->addItem("test");
c->addItem("test2");
l->addWidget(c);
l->addWidget(cb);
setLayout(l);
}
};
class HeaderDelegate : public QStyledItemDelegate{
public:
HeaderDelegate
(QWidget *parent
= 0) : QStyledItemDelegate
(parent
) { for(int i = 0; i < 5; i++){
headerSections.insert(i,new HeaderObject(qobject_cast<QTableView*>(parent)->viewport()));
headerSections[i]->hide();
}
}
if (index.row() == 0){
qDebug() << "QRect: " << option.rect;
headerSections[index.column()]->setGeometry(option.rect);
headerSections[index.column()]->show();
}
}
qDebug() << "Asking for SIZEHINT: " << headerSections[0]->sizeHint();
return headerSections[0]->sizeHint();
}
private:
QVector<
QPointer <HeaderObject> > headerSections;
};
public:
if (role
== Qt
::DisplayRole) return QVariant();
}
private:
};
int main(int argc, char *argv[])
{
CustomModel *model = new CustomModel;
view->setModel(model);
view->setItemDelegateForRow(0, new HeaderDelegate(view));
view->resizeColumnsToContents();
view->resizeRowsToContents();
view->show();
return a.exec();
}
#include <QtGui>
class HeaderObject : public QWidget{
public:
HeaderObject(QWidget *parent = 0) : QWidget(parent){
QComboBox *c = new QComboBox(this);
QCheckBox *cb = new QCheckBox(this);
c->addItem("test");
c->addItem("test2");
QGridLayout *l = new QGridLayout;
l->addWidget(c);
l->addWidget(cb);
setLayout(l);
}
};
class HeaderDelegate : public QStyledItemDelegate{
public:
HeaderDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {
for(int i = 0; i < 5; i++){
headerSections.insert(i,new HeaderObject(qobject_cast<QTableView*>(parent)->viewport()));
headerSections[i]->hide();
}
}
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
if (index.row() == 0){
qDebug() << "QRect: " << option.rect;
headerSections[index.column()]->setGeometry(option.rect);
headerSections[index.column()]->show();
}
}
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const {
qDebug() << "Asking for SIZEHINT: " << headerSections[0]->sizeHint();
return headerSections[0]->sizeHint();
}
private:
QVector< QPointer <HeaderObject> > headerSections;
};
class CustomModel : public QAbstractTableModel{
public:
CustomModel() : QAbstractTableModel(){}
int rowCount(const QModelIndex &parent = QModelIndex()) const{return 5;}
int columnCount(const QModelIndex &parent = QModelIndex()) const {return 5;}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const{
if (role == Qt::DisplayRole) return QVariant();
return QVariant();
}
private:
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CustomModel *model = new CustomModel;
QTableView *view = new QTableView();
view->setModel(model);
view->setItemDelegateForRow(0, new HeaderDelegate(view));
view->resizeColumnsToContents();
view->resizeRowsToContents();
view->show();
return a.exec();
}
To copy to clipboard, switch view to plain text mode
This surprisingly works very well. With some more tweaking it could be made nice. A proxy could be made to supply the widgets for the “headerâ€-row, thereby holding to the MVD paradigm. But then I thought, wouldn't something similar also be possible with the QHeaderView? That's my third try, and also where the problems started to pop up. Here is the code:
THIRD:
#include <QtGui>
class HeaderObject
: public QWidget{public:
c->addItem("test");
c->addItem("test2");
l->addWidget(c);
l->addWidget(cb);
setLayout(l);
}
};
public:
for(int i = 0; i<5; i++){
headerSections.insert(i,new HeaderObject(this));
headerSections[i]->hide();
}
setFont
(QFont("Helvetica [Cronyx]",
32));
setMinimumSectionSize(headerSections[0]->minimumSizeHint().width());
setDefaultSectionSize(headerSections[0]->minimumSizeHint().width());
}
protected:
void paintSection
(QPainter *painter,
const QRect &rect,
int logicalIndex
) const {
if (!rect.isValid())
return;
qDebug() << logicalIndex;
qDebug() << "QRect: " << rect << " AND OFFSET:" << offset();
headerSections[logicalIndex]->setGeometry(rect);
headerSections[logicalIndex]->show();
}
private:
QVector<
QPointer <HeaderObject> > headerSections;
};
public:
}
if (role
== Qt
::DisplayRole) return QVariant();
}
};
int main(int argc, char *argv[])
{
CustomModel *model = new CustomModel;
view->setModel(model);
view->setHorizontalHeader(new CustomHeader(view));
view->show();
return a.exec();
}
#include <QtGui>
class HeaderObject : public QWidget{
public:
HeaderObject(QWidget *parent = 0) : QWidget(parent){
QComboBox *c = new QComboBox(this);
QCheckBox *cb = new QCheckBox(this);
c->addItem("test");
c->addItem("test2");
QGridLayout *l = new QGridLayout;
l->addWidget(c);
l->addWidget(cb);
setLayout(l);
}
};
class CustomHeader : public QHeaderView{
public:
CustomHeader(QWidget *parent = 0):QHeaderView(Qt::Horizontal, parent){
for(int i = 0; i<5; i++){
headerSections.insert(i,new HeaderObject(this));
headerSections[i]->hide();
}
setFont(QFont("Helvetica [Cronyx]", 32));
setMinimumSectionSize(headerSections[0]->minimumSizeHint().width());
setDefaultSectionSize(headerSections[0]->minimumSizeHint().width());
}
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const {
if (!rect.isValid())
return;
qDebug() << logicalIndex;
qDebug() << "QRect: " << rect << " AND OFFSET:" << offset();
headerSections[logicalIndex]->setGeometry(rect);
headerSections[logicalIndex]->show();
}
private:
QVector< QPointer <HeaderObject> > headerSections;
};
class CustomModel : public QAbstractTableModel{
public:
CustomModel() : QAbstractTableModel(){
}
int rowCount(const QModelIndex &parent = QModelIndex()) const{return 5;}
int columnCount(const QModelIndex &parent = QModelIndex()) const {return 5;}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const{
if (role == Qt::DisplayRole) return QVariant();
return QVariant();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CustomModel *model = new CustomModel;
QTableView *view = new QTableView();
view->setModel(model);
view->setHorizontalHeader(new CustomHeader(view));
view->show();
return a.exec();
}
To copy to clipboard, switch view to plain text mode
The main problem here is the horizontal QHeaderViews height. Guess what, you can not adjust it. Notice the setFont(). Up till now, that's the only way I have found to adjust the QHeaderView's height. I have tried setGeometry on both QHeaderView and it's viewport(), but none work. For some reason (which I can't figure out from the sourcecode) it always reverts to size 100x30. Only by explicitly catching viewport resize events did I manage to get the widgets to the required size (without the QFont hack), but the header remained the same size (so the widgets overlapped with the columns). This still seems to me the desirable way to go, but I do not see how to adjust the height. Any suggestions? You can also criticize my whole approach.
Bookmarks