在 QTreeView (Qt/PySide/PyQt) 中实现自动换行的委托? [英] Implementing a delegate for wordwrap in a QTreeView (Qt/PySide/PyQt)?

查看:172
本文介绍了在 QTreeView (Qt/PySide/PyQt) 中实现自动换行的委托?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有自定义委托的树视图,我正在尝试向其中添加自动换行功能.自动换行工作正常,但 sizeHint() 似乎不起作用,因此当文本换行时,相关行不会扩展以包含它.

I have a tree view with a custom delegate to which I am trying to add word wrap functionality. The word wrapping is working fine, but the sizeHint() seems to not work, so when the text wraps, the relevant row does not expand to include it.

我以为我在 sizeHint() 中通过返回 document.size().height() 来处理它.

I thought I was taking care of it in sizeHint() by returning document.size().height().

def sizeHint(self, option, index):
    text = index.model().data(index)
    document = QtGui.QTextDocument()
    document.setHtml(text) 
    document.setTextWidth(option.rect.width())  
    return QtCore.QSize(document.idealWidth(), document.size().height())    

但是,当我打印出document.size().height() 时,每个项目都是一样的.

However, when I print out document.size().height() it is the same for every item.

此外,即使我手动设置高度(例如,设置为 75)只是为了检查事情看起来是否合理,树看起来也像被火箭筒射中的金鱼(也就是说,这是一团糟):

Also, even if I manually set the height (say, to 75) just to check that things will look reasonable, the tree looks like a goldfish got shot by a bazooka (that is, it's a mess):

如您所见,每行中的文本在树中没有正确对齐.

As you can see, the text in each row is not aligned properly in the tree.

类似帖子

以前也出现过类似的问题,但没有解决我的问题(人们通常说要重新实现sizeHint(),这就是我正在尝试的):

Similar issues have come up before, but no solutions to my problem (people usually say to reimplement sizeHint(), and that's what I am trying):

QTreeWidget 根据内容设置每行的高度

QTreeView 自定义单行行高

http://www.qtcentre.org/threads/1289-QT4-QTreeView-and-rows-with-multiple-lines

SSCCE

import sys
from PySide import QtGui, QtCore

class SimpleTree(QtGui.QTreeView):
    def __init__(self, parent = None):    
        QtGui.QTreeView.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setGeometry(500,200, 400, 300)  
        self.setUniformRowHeights(False) #optimize: but for word wrap, we don't want this!
        print "uniform heights in tree?", self.uniformRowHeights()
        self.model = QtGui.QStandardItemModel()
        self.model.setHorizontalHeaderLabels(['Task', 'Description'])
        self.setModel(self.model)
        self.rootItem = self.model.invisibleRootItem()
        item0 = [QtGui.QStandardItem('Sneeze'), QtGui.QStandardItem('You have been blocked up')]
        item00 = [QtGui.QStandardItem('Tickle nose, this is a very long entry. Row should resize.'), QtGui.QStandardItem('Key first step')]
        item1 = [QtGui.QStandardItem('<b>Get a job</b>'), QtGui.QStandardItem('Do not blow it')]
        self.rootItem.appendRow(item0)
        item0[0].appendRow(item00) 
        self.rootItem.appendRow(item1)
        self.setColumnWidth(0,150)
        self.expandAll()
        self.setWordWrap(True)
        self.setItemDelegate(ItemWordWrap(self))

class ItemWordWrap(QtGui.QStyledItemDelegate):
    def __init__(self, parent=None):
        QtGui.QStyledItemDelegate.__init__(self, parent)
        self.parent = parent
    def paint(self, painter, option, index):
        text = index.model().data(index) 
        document = QtGui.QTextDocument() # #print "dir(document)", dir(document)
        document.setHtml(text)       
        document.setTextWidth(option.rect.width())  #keeps text from spilling over into adjacent rect
        painter.save() 
        painter.translate(option.rect.x(), option.rect.y()) 
        document.drawContents(painter)  #draw the document with the painter
        painter.restore()
    def sizeHint(self, option, index):
        #Size should depend on number of lines wrapped
        text = index.model().data(index)
        document = QtGui.QTextDocument()
        document.setHtml(text) 
        document.setTextWidth(option.rect.width())  
        return QtCore.QSize(document.idealWidth() + 10,  document.size().height())       

def main():
    app = QtGui.QApplication(sys.argv)
    myTree = SimpleTree()
    myTree.show()
    sys.exit(app.exec_())
    
if __name__ == "__main__":
    main()

推荐答案

该问题似乎源于将 option.rect.width() 的值传递给 QStyledItemDelegate 的事实.sizeHint() 是 -1.这显然是假的!

The issue seems to stem from the fact that the value for option.rect.width() passed into QStyledItemDelegate.sizeHint() is -1. This is obviously bogus!

我通过在 paint() 方法中存储模型中的宽度并从 sizeHint() 访问它来解决这个问题.

I've solved this by storing the width in the model from within the paint() method and accessing this from sizeHint().

因此在您的 paint() 方法中添加以下行:

So in your paint() method add the line:

index.model().setData(index, option.rect.width(), QtCore.Qt.UserRole+1)

并在您的 sizeHint() 方法中,将 document.setTextWidth(option.rect.width()) 替换为:

and in your sizeHint() method, replace document.setTextWidth(option.rect.width()) with:

width = index.model().data(index, QtCore.Qt.UserRole+1)
if not width:
    width = 20
document.setTextWidth(width)

这篇关于在 QTreeView (Qt/PySide/PyQt) 中实现自动换行的委托?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆