@Maxim045

С чем может быть связано нестабильное поведение QListWidget(Python3, PyQt5)?

В коде, который я оставлю ниже, есть три класса - ListWidget, Label и MyWindow. ListWidget создает резиновую ленту, а Label создает виджет QLabel с закругленным изображением. На эти классы не стоит обращать внимания, они точно правильно выполняют свои функции. Проблема(проблемы) в классе MyWindow.

  1. Тут я создаю кнопку simple_btn, которая потом попадает в вертикальный контейнер box2. Пока она не выполняет и не должна выполнять никаких функций.
  2. Создаю listWidget - копию класса ListWidget, который наполняю виджетами QLable(label1, label2, label3), полученными из класса Label.
  3. Создаю scrollArea(QScrollArea), но пока нигде не размещаю.
  4. Создаю QGridLayout - box1, куда первым виджетом(0, 0) добавляю listWidget.
  5. К виджетам label1 , label2 и label3 привязываю метод класса MyWindow - click()(при этом передаю этому методу аргумент num), который с помощью hide() скрывает listWidget и создает привязанный к scrollArea контейнер QGridLayout - box3, если он еще не был создан. box3 наполняется кнопками, число которых зависит от аргумента num. В вертикальный контейнер box2 попадает кнопка back_btn.
  6. К кнопке back_btn привязваю метод on_button. Этот метод должен удалять все виджеты контейнера box3, скрывать scrollArea с помощью hide() и делать обратно видимым listWidget с помощью show().

Суть проблемы:
Я нажал на один из QLabel'ов и с помощью кнопки back_btn вернулся к исходному положению виджетов. Если проделать это некоторое количество раз подряд, может возникнуть странный баг - виджеты внутри listWidget перестают менять свое пололожение в зависимости от размера окна. В этих двух предложениях мало конкретики, знаю, но, как я понял, нет конкретной комбинации, способной привести к багу, иногда он происходит сразу, иногда не происходит вообще. Баг появляется достаточно часто, не могу закрыть на это глаза. На другом компьютере происходит то же самое. Не могу себе представить причину, очень нужна помощь.
5e4bfa7bdb5e3715901932.png
5e4bfa86b36c6774570318.png
5e4bfa8fba0dc936406012.png
5e4bfa9ac2255479744624.png
Баг может случится при любом расположении виджетов:
5e4bfad1cf70b200131703.png
Вот код:
from PyQt5 import QtCore, QtWidgets, QtGui

class ListWidget(QtWidgets.QListWidget):
    def __init__(self, *args, **kwargs):
        super(ListWidget, self).__init__(*args, **kwargs)

        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)

        self.setEditTriggers(self.NoEditTriggers)
        self.setDefaultDropAction(QtCore.Qt.IgnoreAction)
        self.setSelectionMode(self.ContiguousSelection)

        self.setFlow(self.LeftToRight)
        self.setWrapping(True)
        self.setResizeMode(self.Adjust)

        self.setSpacing(10)

    def makeItem(self, lb):
        item = QtWidgets.QListWidgetItem(self)
        item.setSizeHint(QtCore.QSize(140, 140))
        self.setItemWidget(item, lb)

class Label(QtWidgets.QLabel):
    clicked = QtCore.pyqtSignal()

    def __init__(self, picture, *args, **kwargs):
        super(Label, self).__init__(*args, **kwargs)

        self.setMaximumSize(140, 140)
        self.setMinimumSize(140, 140)
        self.radius = 10 

        self.target = QtGui.QPixmap(self.size())  
        self.target.fill(QtCore.Qt.transparent)    

        p = QtGui.QPixmap(picture).scaled(140, 140, QtCore.Qt.KeepAspectRatioByExpanding, QtCore.Qt.SmoothTransformation)

        painter = QtGui.QPainter(self.target)
        painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
        painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing, True)
        painter.setRenderHint(QtGui.QPainter.SmoothPixmapTransform, True)

        path = QtGui.QPainterPath()
        path.addRoundedRect(0, 0, self.width(), self.height(), self.radius, self.radius)
        painter.setClipPath(path)
        painter.drawPixmap(0, 0, p)
        self.setPixmap(self.target)

    def mouseReleaseEvent(self, event):
        self.clicked.emit()

class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.scrollArea = QtWidgets.QScrollArea()
        self.content_widget = QtWidgets.QWidget()
        self.scrollArea.setWidget(self.content_widget)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)

        self.simple_btn = QtWidgets.QPushButton('Button')
        self.simple_btn.setFixedSize(100, 60)

        self.listWidget = ListWidget()

        self.label1 = Label('picture1.png')
        self.listWidget.makeItem(self.label1)
        self.label1.clicked.connect(lambda num=2: self.click(num))
        self.label2 = Label('picture1.png')
        self.listWidget.makeItem(self.label2)
        self.label2.clicked.connect(lambda num=3: self.click(num))
        self.label3 = Label('picture1.png')
        self.listWidget.makeItem(self.label3)
        self.label3.clicked.connect(lambda num=4: self.click(num))

        self.box2 = QtWidgets.QVBoxLayout()
        self.box2.addWidget(self.simple_btn)

        self.box1 = QtWidgets.QGridLayout()                                     
        self.box1.addWidget(self.listWidget, 0, 0)
        self.box1.setColumnStretch(0, 1)
        self.box1.addLayout(self.box2, 0, 1)
        self.setLayout(self.box1)

    def click(self, num):
        self.listWidget.hide()

        if not hasattr(self, 'box3'):
            self.box1.addWidget(self.scrollArea, 0, 0)
            self.box3 = QtWidgets.QGridLayout(self.content_widget)
        else:
            self.scrollArea.show()

        for n in range(1, num):
            btn = QtWidgets.QPushButton(f'Button{n}')
            self.box3.addWidget(btn, n-1, 0)

        self.back_btn = QtWidgets.QPushButton('Back', clicked=self.on_button) 
        self.back_btn.setFixedSize(100, 60)
        self.box2.addWidget(self.back_btn)

    def on_button(self):
        self.back_btn.deleteLater()
        col = 0
        for row in range(self.box3.rowCount()):
            if self.box3.itemAtPosition(row, col) is not None:
                w = self.box3.itemAtPosition(row, col).widget()
            w.deleteLater()
        self.scrollArea.hide()
        self.listWidget.show()

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle(' ')
    window.show()
    sys.exit(app.exec_())
  • Вопрос задан
  • 106 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы