gpt4 book ai didi

python - 嵌入 QWidget 时 QListView 选定索引未更新

转载 作者:行者123 更新时间:2023-12-01 08:34:10 26 4
gpt4 key购买 nike

我在 QListView 的 Qwidget 中嵌入了 QPushbutton:QPushbutton >> QWidget >> QListView

list_widget = QWidget()
list_widget.layout(QHBoxLayout())
btn = QPushButton()
btn.pressed.connect(clicked)
list_widget.layout().addWidget(QPushButton())
list_view.setIndexWidget(self.list_model.index(row, 0), list_widget)

def clicked():
row = list_view.selectedIndexes()

现在的问题是 list_view.selectedIndexes() 在按下时不会返回按下按钮的行。这似乎只有当 QPushbutton 直接嵌入到 QListView 中时才有效:QPushbutton >> QListView。

有人知道如何将按钮的焦点委托(delegate)给 QListView 吗?

最佳答案

当您单击按钮时,它不会传输到 QListView,因为按钮会消耗它并且不会将其传输到其他小部件,因此如果您想获取该行,则必须间接获取它,一个可能的解决方案是使用对于它的几何形状,您必须获取发送者(在本例中为按钮),然后将其左上角转换为全局位置,然后将其转换为相对于 QListView 视口(viewport)的本地位置,使用该位置与方法 indexAt( ) 你得到了 QModelIndex。

from PyQt5 import QtCore, QtGui, QtWidgets

class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.list_model = QtGui.QStandardItemModel(200, 1)
self.list_view = QtWidgets.QListView()
self.list_view.setModel(self.list_model)
self.setCentralWidget(self.list_view)

for row in range(self.list_model.rowCount()):
list_widget = QtWidgets.QWidget()
hlay = QtWidgets.QHBoxLayout(list_widget)
btn = QtWidgets.QPushButton(str(row))
btn.pressed.connect(self.clicked)
hlay.addWidget(btn)
hlay.setContentsMargins(0, 0, 0, 0)
self.list_view.setIndexWidget(self.list_model.index(row, 0), list_widget)

@QtCore.pyqtSlot()
def clicked(self):
btn = self.sender()
gp = btn.mapToGlobal(QtCore.QPoint())
lp = self.list_view.viewport().mapFromGlobal(gp)
ix = self.list_view.indexAt(lp)
print("row", ix.row())

if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

另一种更简单的方法是使用 functools.partial() 将行作为参数传递:

from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets

class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.list_model = QtGui.QStandardItemModel(200, 1)
self.list_view = QtWidgets.QListView()
self.list_view.setModel(self.list_model)
self.setCentralWidget(self.list_view)

for row in range(self.list_model.rowCount()):
list_widget = QtWidgets.QWidget()
hlay = QtWidgets.QHBoxLayout(list_widget)
btn = QtWidgets.QPushButton(str(row))
btn.pressed.connect(partial(self.clicked, row))
hlay.addWidget(btn)
hlay.setContentsMargins(0, 0, 0, 0)
self.list_view.setIndexWidget(self.list_model.index(row, 0), list_widget)

@QtCore.pyqtSlot(int)
def clicked(self, row):
print(row)

if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

或者使用 lambda 方法:

from PyQt5 import QtCore, QtGui, QtWidgets

class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.list_model = QtGui.QStandardItemModel(200, 1)
self.list_view = QtWidgets.QListView()
self.list_view.setModel(self.list_model)
self.setCentralWidget(self.list_view)

for row in range(self.list_model.rowCount()):
list_widget = QtWidgets.QWidget()
hlay = QtWidgets.QHBoxLayout(list_widget)
btn = QtWidgets.QPushButton(str(row))
btn.pressed.connect(lambda *args, row=row: self.clicked(row))
hlay.addWidget(btn)
hlay.setContentsMargins(0, 0, 0, 0)
self.list_view.setIndexWidget(self.list_model.index(row, 0), list_widget)

@QtCore.pyqtSlot(int)
def clicked(self, row):
print(row)

if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
<小时/>

就我而言,我更喜欢使用部分,因为您不需要编写大量逻辑并且它是线程安全的。

关于python - 嵌入 QWidget 时 QListView 选定索引未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53804021/

26 4 0
文章推荐: android-emulator - adb 重启不起作用
文章推荐: ruby-on-rails - 为什么 `button tag` 不会显示对话框进行确认?
文章推荐: python - 键盘无法访问元素
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com