Выбранный индекс QListView не обновляется при встраивании QWidget - PullRequest
0 голосов
/ 16 декабря 2018

Я встроил кнопку QPush в Qwidget в QListView: 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 () не возвращаетряд нажатой кнопки, при нажатии.Кажется, это работает только тогда, когда кнопка QPushbton встроена непосредственно в QListView: QPushbutton >> QListView.

У кого-нибудь есть идеи, как делегировать фокус кнопки в QListView?

1 Ответ

0 голосов
/ 16 декабря 2018

Когда вы нажимаете на кнопку, она не передается в QListView, потому что кнопка использует ее и не передает ее другим виджетам, поэтому, если вы хотите получить строку, она должна быть получена косвенно, возможное решение состоит в использованиигеометрии для него вы должны получить отправителя, в этом случае кнопку, а затем для ее перехода в глобальные позиции, а затем преобразовать ее в локальную позицию по отношению к окну просмотра 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_())

Или используя лямбда-метод:

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_())

В моем случае я предпочитаю использовать партиалы, так как вам не нужно писать много логики и она поточно-ориентирована.

...