waddlesplash
waddlesplash

Reputation: 773

Can you set a QWidget to take up an entire column of a QTreeWidget?

I have a custom QTreeWidget subclass that I'm using to display track names/etc. in my MIDI editor project (https://github.com/waddlesplash/ragingmidi). I'd like to add another column to this tree widget, but with one widget taking up the whole column and not per-item widgets.

Is this possible or will I have to figure out some other solution?

EDIT: I'm trying to accomplish something like this: http://www.anvilstudio.com/compose.jpg - see the last "column" in the header view (3rd after "L/R Balance") showing all the lines/notes (which is entirely custom, and written in VB.NET and closed-source anyway).

EDIT 2: You can't see it, but the last column scrolls without the other columns scrolling in the above picture. In their method, you have to scroll using the mouse. I want a scrollbar.

Upvotes: 3

Views: 2017

Answers (3)

waddlesplash
waddlesplash

Reputation: 773

The though that has come to my mind after a week is to hijack the H-scrollbar for the QTreeWidget, and then make that scrollbar scroll only the final column. Because right now, all the columns fit when the window is 620x670px, and who has a screen that small anymore?

Unless anyone has a better solution or objections as to why this is a bad idea, this is the way I'm going to do it.

Upvotes: 0

Tilman Vogel
Tilman Vogel

Reputation: 9773

This is not completely pretty, because it got it's problems when the custom widget is in the right-most column and the column is made narrow, but it's a start:

#include <QtGui>

class TreeWidget : public QTreeWidget
{
    Q_OBJECT
public:
    TreeWidget();

    QRect columnRect(int column) const;

private slots:
    void repositionColumnWidget();

private:
    QPushButton * mColumnWidget;
};

TreeWidget::TreeWidget()
    : mColumnWidget(new QPushButton("Custom Column Button", viewport()))
{
    const int COLUMN_COUNT = 6;
    setColumnCount(COLUMN_COUNT);
    for (int row = 0; row < 400; ++row)
    {
        QStringList columns;
        for (int column = 0; column < COLUMN_COUNT; ++column)
        {
            columns << QString("row %1, column %2").arg(row + 1).arg(column + 1);
        }
        addTopLevelItem(new QTreeWidgetItem(columns));
    }
    for (int column = 0; column < COLUMN_COUNT; ++column)
    {
        resizeColumnToContents(column);
    }
    repositionColumnWidget();
    mColumnWidget->show();
    connect(header(), SIGNAL(sectionResized(int,int,int)), this, SLOT(repositionColumnWidget()));
    connect(header(), SIGNAL(sectionMoved(int,int,int)), this, SLOT(repositionColumnWidget()));
    connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(repositionColumnWidget()));
    connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(repositionColumnWidget()));
}

QRect TreeWidget::columnRect(int column) const
{
    int itemCount = topLevelItemCount();
    if (!itemCount)
    {
        return QRect();
    }
    int columnX = header()->sectionViewportPosition(column);
    int columnY = visualItemRect(topLevelItem(0)).top();
    int columnWidth = header()->sectionSize(column);
    int columnHeight = visualItemRect(topLevelItem(itemCount-1)).bottom() - columnY + 1;

    return QRect(columnX, columnY, columnWidth, columnHeight);
}

void TreeWidget::repositionColumnWidget()
{
    mColumnWidget->setGeometry(columnRect(3));
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    a.setQuitOnLastWindowClosed(true);

    TreeWidget treeWidget;

    treeWidget.resize(800, 600);
    treeWidget.show();

    return a.exec();
}

#include "main.moc"

Upvotes: 0

Sir Digby Chicken Caesar
Sir Digby Chicken Caesar

Reputation: 3123

Looking at the Qt documentation, there seems to be a few options to accomplish this, however there are a few important factors to address before you can decide what approach best suits your needs.

  1. Is the content being displayed in this custom tree column static or dynamic?
  2. Is there a one to one mapping of rows from your QTreeWidget to your custom tree column?

If your custom tree column content IS static and there IS a one to one mapping of rows , use of the QTreeWidget::setItemWidget ( QTreeWidgetItem * item, int column, QWidget * widget ) function should suffice.

However, if the content of your custom tree column is dynamic OR there is not a one to one mapping of rows, this will require a more complex approach.

As described in the documentation for QTreeWidget; "If you want to display custom dynamic content or implement a custom editor widget, use QTreeView and subclass QItemDelegate. "

QItemDelegate, and its sub classes, perform all drawing facilities for items inserted into Qt item views (like QTreeView, QListView, QTableView, etc..). This essentially allows you to control ALL drawing operations for any item inserted into a QTreeView class, letting you draw dynamic content in addition to being able to extend content across multiple rows.

Having implemented a similar approach for a QListWidget, I recommend using QStyledItemDelegate in lieu of QItemDelegate as it allows you to more easily integrate this widget with your application's style layout. As you did not detail the exact use of this custom QWidget, you also might need the additional facilities provided by QItemEditorCreator, QItemEditorCreatorBase and QItemEditorFactory. I would post the similar widget I developed here if I could, but sadly it is part of a proprietary software suite.

Upvotes: 2

Related Questions