Добавление / удаление виджетов QSlider на PyQt5

Я хочу динамически изменять количество ползунков в окне приложения в зависимости от количества отмеченных элементов в QStandardItemModel состав.

В моем окне приложения есть экземпляр QVBoxLayout называется sliders, который я обновляю при нажатии кнопки:

сначала удаляем все ползунки в итоге там:

self.sliders.removeWidget(slider)

И затем создание нового набора.

Соответствующий код:

def create_sliders(self):
    if len(self.sliders_list):
        for sl in self.sliders_list:
            self.sliders.removeWidget(sl)
    self.sliders_list = []
    for index in range(self.model.rowCount()):
        if self.model.item(index).checkState():
            slid = QSlider(Qt.Horizontal)
            self.sliders.addWidget(slid)
            self.sliders_list.append(slid)

Кажется, что принцип работает, но то, что происходит, странно, поскольку удаленные ползунки на самом деле не исчезают, а потому, что они "отключены" от основного макета.

После создания ползунки сохраняют свою позицию среди других элементов, пока я изменяю размер главного окна. Однако после удаления они занимают фиксированное положение и могут, например, исчезнуть, если я уменьшу размер окна. К сожалению, у меня возникают трудности при связывании изображений (он говорит, что формат не поддерживается, когда я пытаюсь связать с монтажной панели), поэтому я надеюсь, что этого описания достаточно, чтобы осветить проблему.

Нужно ли удалять ползунки, используя другую процедуру?

РЕДАКТИРОВАТЬ

Спасибо @eyllansec за его ответ, он сокращает кучу других ответов по теме, которые я не смог найти, так как не знал метод deleteLater() что является ключом, чтобы избавиться от виджетов внутри QLayout,

Я отмечаю его как выбранный (эй, это единственный, и он работает, в конце концов!), Однако я хочу предложить свой собственный код, который также работает с минимальными изменениями по сравнению с тем, что я предлагал в начале.

Ключевым моментом здесь является то, что я использовал метод QLayout.removeWidget(QWidget) о котором я ошибочно думал, это было бы.. ээ.. Убрать виджет! Но на самом деле он делает (если я правильно понял) удалить его из экземпляра макета.

Вот почему он все еще висел в моем окне, хотя казалось, что он отключен

Ручная ссылка

Кроме того, предлагаемый код является гораздо более общим, чем то, что мне нужно, так как это рекурсия содержимого макета, которая в принципе может быть и другой QLayout объекты или QWidgets (или даже Qspacer) и быть организованы в иерархию (т.е. QWidgetQLayout в пределах QLayout и так далее).

проверьте этот другой ответ

Оттуда, использование рекурсии и серии if-then строит.

Мой случай гораздо проще, так как я использую это QVLayout экземпляр просто разместить мой QSliders и это будет все. Итак, я придерживаюсь своего списка на данный момент, так как мне не нравится формализм QLayout.TakeAt(n) и мне это не нужно Я был рад, что ссылки, которые я строю в списке, абсолютно хороши для работы.

В конце концов, это немного измененный код, который работает для меня в этом случае:

def create_sliders(self):
    if len(self.sliders_list):
        for sl in self.sliders_list:
            sl.deleteLater()
    self.sliders_list = []
    for index in range(self.model.rowCount()):
        if self.model.item(index).checkState():
            slid = QSlider(Qt.Horizontal)
            self.sliders.addWidget(slid)
            self.sliders_list.append(slid)

1 ответ

Решение

Нет необходимости сохранять слайдеры в списке, доступ к ним можно получить через макет, в котором они содержатся. Я реализовал функцию, которая удаляет элементы в макете. Решение заключается в следующем:

def create_sliders(self):
    self.clearLayout(self.sliders)

    for index in range(self.model.rowCount()):
        if self.model.item(index).checkState():
            slid = QSlider(Qt.Horizontal)
            self.sliders.addWidget(slid)

def clearLayout(self, layout):
    if layout:
        while layout.count():
            item = layout.takeAt(0)
            widget = item.widget()
            if widget:
                widget.deleteLater()
            else :
                self.clearLayout(item.layout())
            layout.removeItem(item)
Другие вопросы по тегам