qt - 自定义绘制委托(delegate)中的可点击元素或子小部件

标签 qt qt4 pyside qlistview qitemdelegate

我有一个 QListView,我在其中使用带有自定义绘画的自定义委托(delegate)来显示项目。在每个项目(即每个列表行)中,我希望能够显示几个“超链接”,用户可以单击这些“超链接”,然后调用某些函数。

我已经尝试检查官方文档(例如 Model/View Programming )以及大量谷歌搜索,但无法弄清楚如何完成此操作。

我有两个想法,每个都有自己的问题:

  • 我可以使用子小部件(如扁平 QPushButton)来绘制它们。然后如何定位和显示这些小部件?
  • 我也可以将它们绘制为文本字符串。然后我如何使它们可点击?或者我可以捕获父 QListView 上的点击事件并以某种方式确定这些事件的坐标吗?然后我可以将坐标与这些可点击元素匹配并采取相应的行动。

  • 我最初的方法是将 QListWidget 与 .setItemWidget() 一起使用,其中我有一个带有布局和子小部件的适当小部件。不幸的是,当我的列表增长到数百或数千个项目时,这太慢了。这就是为什么我使用委托(delegate)更改为 QListView 的原因。

    最佳答案

    我似乎正在接近解决方案。

    我可以通过覆盖委托(delegate)的 .editorEvent(event, model, option, index) 来接收元素的点击。 .然后我可以找到 event.type() ,点击的行来自 index.row()以及来自 event.x() 的实际坐标和 event.y() (因为,如果事件类型是 MouseButtonRelease,那么事件就是 QMouseEvent)。

    从这些,我想我可以将坐标与屏幕上的元素相关联并采取相应的行动。

    一旦我有工作代码,我会更新这个答案。

    编辑

    一个简单的工作示例,使用 PySide:

    class MyModel(QtGui.QStandardItemModel):
      def __init__(self):
        super(MyModel, self).__init__()
        for i in range(10): self.appendRow(QtGui.QStandardItem("Row %d" % i))
    
    class MyDelegate(QtGui.QStyledItemDelegate):
      def __init__(self, parent=None):
        super(MyDelegate, self).__init__(parent)
        self.links = {}
    
      def makeLinkFunc(self, row, text):
        def linkFunc(): print("Clicked on %s in row %d" % (text, row))
        return linkFunc
    
      def paint(self, painter, option, index):
        painter.save()
        textHeight  = QtGui.QFontMetrics(painter.font()).height()
    
        painter.drawText(option.rect.x()+2, option.rect.y()+2+textHeight, index.data())
    
        rowLinks = {}
        for i in range(3):
          text = "Link %d" % (3-i)
          linkWidth = QtGui.QFontMetrics(font).width(text)
          x = option.rect.right() - (i+1) * (linkWidth + 10)
          painter.drawText(x, y, text)
          rect = QtCore.QRect(x, y - textHeight, linkWidth, textHeight)
          rowLinks[rect] = self.makeLinkFunc(index.row(), text)
    
        self.links[index.row()] = rowLinks
        painter.restore()
    
      def sizeHint(self, option, index):
        hint = super().sizeHint(option, index)
        hint.setHeight(30)
        return hint
    
      def editorEvent(self, event, model, option, index):
        if event.type() == QtCore.QEvent.MouseButtonRelease:
          for rect, link in self.links[index.row()].items():
            if rect.contains(event.pos()):
              link()
              return True
        return False
    
    listmodel = MyModel()
    listview = QtGui.QListView()
    listview.setModel(listmodel)
    listview.setItemDelegate(MyDelegate(parent=listview))
    listview.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
    

    关于qt - 自定义绘制委托(delegate)中的可点击元素或子小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9415030/

    相关文章:

    c++ - QPlainTextEdit dragEnterEvent 不接受文本/uri 列表 mime 类型

    c++ - QScintilla - 在自定义词法分析器中为单词添加颜色

    python - QTextEdit 在调整大小时不显示水平滚动条

    python - Pyside 改变 QIcon 中 SVG 的颜色或不透明度

    python - 如何为QTableWidget指定排序数据

    c++ - 为什么不能在main.cpp中编写QWidget类?

    c++ - 如何在 Qt C++ 中使用 Secure WebSocket 连接服务器

    validation - {[A-Z] [a-z][0-9]} 文本输入的 QLineEdit 验证

    python - QMediaPlayer setPlaybackRate > 1 会导致高音调音频

    Qt 4.8.5 QLabel setStylesheet 忽略继承的字体