我已经在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。
有谁知道如何将按钮的焦点委托给QListView?
最佳答案
当您单击该按钮时,该按钮不会传输到QListView,因为该按钮会消耗它,并且不会将其传输到其他小部件,因此,如果要获取该行,则必须间接获取该行,一种可能的解决方案是为其使用几何您必须获取sender(在这种情况下为按钮),然后将其左上角设置为全局位置,然后将其转换为相对于QListView视口的本地位置,并使用该位置和方法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_())
就我而言,我更喜欢使用partials,因为您不需要编写很多逻辑,而且它是线程安全的。
关于python - 嵌入QWidget时未更新QListView Selected Index,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53804021/