3

我有一个自定义QTreeWidget子类,用于显示曲目名称/等。在我的 MIDI 编辑器项目(https://github.com/waddlesplash/ragingmidi)中。我想向此树小部件添加另一列,但一个小部件占据整个列,而不是每个项目的小部件。

这是可能的还是我必须找出其他解决方案?

编辑:我正在尝试完成这样的事情:http ://www.anvilstudio.com/compose.jpg - 查看标题视图中的最后一个“列”(“L/R 平衡”之后的第三个)显示所有行/notes (这是完全自定义的,无论如何都是用 VB.NET 和封闭源代码编写的)。

编辑 2:您看不到它,但最后一列滚动而其他列在上图中滚动。在他们的方法中,您必须使用鼠标滚动。我想要一个滚动条。

4

3 回答 3

2

查看 Qt 文档,似乎有几个选项可以实现这一点,但是在您决定哪种方法最适合您的需求之前,需要解决一些重要因素。

  1. 此自定义树列中显示的内容是静态的还是动态的?
  2. 从 QTreeWidget 到自定义树列是否存在一对一的行映射?

如果您的自定义树列内容是静态的并且存在一对一的 rows 映射,则使用QTreeWidget::setItemWidget ( QTreeWidgetItem * item, int column, QWidget * widget )函数就足够了。

但是,如果您的自定义树列的内容是动态的,或者没有一对一的行映射,这将需要更复杂的方法。

如 QTreeWidget 文档中所述;“如果要显示自定义动态内容或实现自定义编辑器小部件,请使用 QTreeView 和子类 QItemDelegate。”

QItemDelegate 及其子类为插入到 Qt 项目视图(如 QTreeView、QListView、QTableView 等)的项目执行所有绘图工具。这实质上允许您控制插入到 QTreeView 类中的任何项目的所有绘图操作,除了能够跨多行扩展内容之外,还允许您绘制动态内容。

为 QListWidget 实现了类似的方法后,我建议使用QStyledItemDelegate代替QItemDelegate,因为它允许您更轻松地将此小部件与应用程序的样式布局集成。由于您没有详细说明此自定义 QWidget 的确切用途,您可能还需要QItemEditorCreatorQItemEditorCreatorBaseQItemEditorFactory提供的附加工具。如果可以的话,我会发布我在这里开发的类似小部件,但遗憾的是它是专有软件套件的一部分。

于 2013-03-15T18:35:08.263 回答
0

这并不完全漂亮,因为当自定义小部件位于最右边的列并且该列变窄时会出现问题,但这是一个开始:

#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"
于 2013-03-15T20:34:33.690 回答
0

一周后我想到的是劫持 H 滚动条QTreeWidget,然后让滚动条只滚动最后一列。因为现在,当窗口为 620x670 像素时,所有的列都适合,谁还有这么小的屏幕?

除非有人对为什么这是一个坏主意有更好的解决方案或反对意见,否则这就是我要做的方式。

于 2013-03-18T20:47:10.073 回答