9

QListViewがあり、カスタムペイントを使用したカスタムデリゲートを使用してアイテムを表示します。各アイテム(つまり、各リスト行)内に、ユーザーがクリックしていくつかの関数を呼び出すことができるいくつかの「ハイパーリンク」を表示できるようにしたいと思います。

私はすでに公式ドキュメント(例:モデル/ビュープログラミング)とかなりのグーグルをチェックしようとしましたが、これを達成する方法を理解することができませんでした。

私には2つのアイデアがあり、それぞれに独自の問題があります。

  • フラットなQPushButtonのように、子ウィジェットを使用してそれらを描画できます。次に、これらのウィジェットを配置して表示するにはどうすればよいですか?
  • それらをテキスト文字列として描画することもできます。次に、クリック可能にするにはどうすればよいですか?または、親QListViewでクリックイベントをキャプチャし、それらから座標を決定することはできますか?次に、これらのクリック可能な要素に座標を一致させ、それに応じて行動することができます。

私の最初のアプローチは、.setItemWidget()でQListWidgetを使用することでした。ここでは、レイアウトと子ウィジェットを備えた適切なウィジェットがありました。残念ながら、私のリストが数百または数千のアイテムに増えたとき、これは遅すぎました。そのため、デリゲートを使用してQListViewに変更しました。

4

1 に答える 1

3

私は解決策に近づいているようです。

デリゲートのをオーバーライドすることで、要素のクリックを受け取ることができます.editorEvent(event, model, option, index)event.type()次に、、からクリックされた行、およびからのindex.row()実際の座標を見つけることができます(イベントタイプがMouseButtonReleaseの場合、イベントはQMouseEventであるため)。event.x()event.y()

これらから、座標を画面上の要素に関連付け、それに応じて行動できると思います。

動作するコードができたら、この回答を更新します。

編集

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)
于 2012-02-24T14:56:35.917 に答える