如何去除QTreeView缩进

问题描述 投票:0回答:4

我希望在左侧有一个

QTreeView
without 缩进,并在每个嵌套级别上增加。我尝试设置
QTreeView::setIndentation(0)
。它按照我想要的方式删除了缩进,但它也隐藏了树箭头。


默认行为:

  • 有凹痕✗
  • 带箭头✔


setIndentation(0)
之后:

  • 无压痕✔
  • 没有箭头✗


期望的行为:

  • 无压痕✔
  • 带箭头✔


那么如何才能达到第三个例子所示的结果呢?有没有标准的方法来做到这一点,或者我将不得不重新实现

QTreeView::paintEvent()
QTreeView::drawBranches()
等?

qt qt5 qtreeview qtwidgets
4个回答
4
投票

为了解决这个问题,我使用委托来翻译项目的绘制,并绘制箭头。

#include <QtWidgets>

class BranchDelegate: public QStyledItemDelegate
{
public:
    using QStyledItemDelegate::QStyledItemDelegate;
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override{
        QStyleOptionViewItem opt(option);
        if(index.column() == 0)
            opt.rect.adjust(opt.rect.height(), 0, 0, 0);
        QStyledItemDelegate::paint(painter, opt, index);
        if(index.column() == 0){
            QStyleOptionViewItem branch;
            branch.rect = QRect(0, opt.rect.y(), opt.rect.height(), opt.rect.height());
            branch.state = option.state;
            const QWidget *widget = option.widget;
            QStyle *style = widget ? widget->style() : QApplication::style();
            style->drawPrimitive(QStyle::PE_IndicatorBranch, &branch, painter, widget);
        }
    }
};

class TreeView: public QTreeView
{
public:
    TreeView(QWidget *parent=nullptr):QTreeView(parent)
    {
        BranchDelegate *delegate = new BranchDelegate(this);
        setItemDelegate(delegate);
        setIndentation(0);
    }
protected:
    void mousePressEvent(QMouseEvent *event) override{
        QModelIndex index = indexAt(event->pos());
        bool last_state = isExpanded(index);
        QTreeView::mousePressEvent(event);
        if(index.isValid() && last_state == isExpanded(index))
            setExpanded(index, !last_state);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    TreeView w;
    QFileSystemModel model;
    model.setRootPath(QDir::rootPath());
    w.setModel(&model);
    w.setRootIndex(model.index(QDir::homePath()));
    /*for (int i = 1; i< model.columnCount() ; ++i) {
        w.hideColumn(i);
    }*/
    w.expandAll();
    w.resize(640, 480);
    w.show();
    return a.exec();
}

1
投票

ellyanesc 的答案有效,但行中的一个小细节是错误的:

branch.rect = QRect(0, opt.rect.y(), opt.rect.height(), opt.rect.height());

原因是因为当视图水平滚动时,

option.rect.x()
变为负数。如果
branch.rect.x()
为 0(如 ellyanesc 的答案),则分支指示器将始终显示,这也会在滚动过程中导致工件:

  • https://i.stack.imgur.com/O518A.png
  • https://i.stack.imgur.com/qYJMj.png

要解决此问题,请将上面的行替换为:

branch.rect = QRect(option.rect.x(), opt.rect.y(), opt.rect.height(), opt.rect.height());

(我只是在 ellyanesc 的答案中作为评论指出这一点,但我对此没有足够的声誉。)


0
投票
如果存在水平滚动,则 eyllanesc 会崩溃。通常,视图仅在单击分支指示器而不是索引时展开/折叠。

我的解决方案:仅更改具有父项但没有子项的索引的 Rect。也不要将缩进设置为 0。不需要子类化 QTreeView。

#include <QtWidgets> class BranchDelegate: public QStyledItemDelegate { public: mIndent = 50; using QStyledItemDelegate::QStyledItemDelegate; void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { QStyleOptionViewItem opt(option); if(index.parent().isValid && (!index.model() || !index.model()->index(0, 0, index).isValid())) { opt.rect.adjust(-mIndent, 0, 0, 0); } QStyledItemDelegate::paint(painter, opt, index); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); QTreeView apView; BranchDelegate* const apDelegate = new BranchDelegate(apView); apDelegate->mIndent = 50; apView->setIndentation(apDelegate->mIndent); apView->setItemDelegateForColumn(0, apDelegate); QFileSystemModel model; model.setRootPath(QDir::rootPath()); apView.setModel(&model); apView.setRootIndex(model.index(QDir::homePath())); /*for (int i = 1; i< model.columnCount() ; ++i) { apView.hideColumn(i); }*/ apView.expandAll(); apView.resize(640, 480); apView.show(); return a.exec(); }
    

0
投票
我带着同样的问题来到这里,我认为还有一个尚未提及的更简单的解决方案,即添加一个通过单击时切换扩展来模仿树扩展图标的按钮。

我是这样做的:

frame = ClickableFrame() # an implementation of QFrame that allows clicking toggle_tree = QPushButton() spacer = QSpacerItem(5, 1, QSizePolicy.Fixed, QSizePolicy.Fixed) label = QLabel(column) frame.setLayout(QHBoxLayout()) frame.setStyleSheet("background-color: transparent;") frame.clicked.connect( lambda: self.setExpanded(not self.isExpanded()) ) toggle_tree.clicked.connect( lambda: self.setExpanded(not self.isExpanded()) ) frame.layout().addWidget(toggle_tree) frame.layout().addItem(spacer) frame.layout().addWidget(label) frame.layout().addItem(QSpacerItem( 5, 1, QSizePolicy.Fixed, QSizePolicy.Fixed )) self.treeWidget().setItemWidget( self, 0, frame )
    
© www.soinside.com 2019 - 2024. All rights reserved.