Wyczyść wszystkie widżety w układzie w pyqt

Czy istnieje sposób na wyczyszczenie (usunięcie) wszystkich widżetów w układzie?

self.plot_layout = QtGui.QGridLayout()
self.plot_layout.setGeometry(QtCore.QRect(200,200,200,200))
self.root_layout.addLayout(self.plot_layout)
self.plot_layout.addWidget(MyWidget())

Teraz chcę zastąpić widget w {[1] } nowym widgetem. Czy istnieje łatwy sposób na wyczyszczenie wszystkich widżetów w plot_layout? Nie widzę takiej metody.

Author: eyllanesc, 2010-12-24

11 answers

Po wielu badaniach (a to zajęło sporo czasu, więc dodaję go tutaj dla przyszłych odniesień), w ten sposób znalazłem naprawdę jasne i Usuń widgety w układzie:

for i in reversed(range(layout.count())): 
    layout.itemAt(i).widget().setParent(None)

Co dokumentacja mówi o QWidget czy to:

Nowy widżet jest usuwany, gdy jego rodzic jest usuwany.

Ważna uwaga: musisz zapętlić do tyłu, ponieważ usuwanie rzeczy od początku zmienia elementy i zmienia kolejność elementów w układzie.

Aby sprawdzić i potwierdzić, że układ jest pusty:

for i in range(layout.count()): print i

Wydaje się, że jest na to inny sposób. Zamiast używać funkcji setParent, użyj funkcji deleteLater () w następujący sposób:
for i in reversed(range(layout.count())): 
    layout.itemAt(i).widget().deleteLater()

Dokumentacja mówi, że QObject.deleteLater (self)

Rozkłada ten obiekt do usunięcia.

Jednakże, jeśli uruchomisz kod testowy określony powyżej, wyświetli on pewne wartości. Oznacza to, że układ nadal zawiera elementy, w przeciwieństwie do kodu z setParent .

 99
Author: PALEN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-11 02:42:23

To może być trochę za późno, ale po prostu chciałem dodać to dla przyszłych odniesień:

def clearLayout(layout):
  while layout.count():
    child = layout.takeAt(0)
    if child.widget():
      child.widget().deleteLater()

Zaadaptowane z Qt docs http://doc.qt.io/qt-5/qlayout.html#takeAt. pamiętaj, że gdy usuwasz elementy potomne z układu za jakiś czas lub w pętli for, skutecznie modyfikujesz indeks # każdego elementu potomnego w układzie. Dlatego napotkasz problemy używając pętli for i in range().

 32
Author: Nadeem Douba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-11 12:21:23

Odpowiedź od PALEN działa dobrze, jeśli nie musisz dodawać nowych widżetów do układu.

for i in reversed(range(layout.count())): 
    layout.itemAt(i).widget().setParent(None)

Ale dostaniesz "Segmentation fault (core dumped)" w pewnym momencie, jeśli opróżnisz i wypełnisz układ wiele razy lub wieloma widżetami. Wygląda na to, że układ utrzymuje listę widżetów i że ta lista jest ograniczona pod względem rozmiaru.

Jeśli usuniesz widżety w ten sposób:

for i in reversed(range(layout.count())): 
    widgetToRemove = layout.itemAt(i).widget()
    # remove it from the layout list
    layout.removeWidget(widgetToRemove)
    # remove it from the gui
    widgetToRemove.setParent(None)
Nie dostaniesz tego problemu.
 24
Author: Blaa_Thor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-24 18:23:27

Tak czyszczę layout:

def clearLayout(layout):
    if layout is not None:
        while layout.count():
            child = layout.takeAt(0)
            if child.widget() is not None:
                child.widget().deleteLater()
            elif child.layout() is not None:
                clearLayout(child.layout())
 14
Author: user3369214,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-07 23:25:33

Możesz użyć close() Metody widget:

for i in range(layout.count()): layout.itemAt(i).widget().close()
 13
Author: Volodymyr Pavlenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-28 16:28:15

Używam:

    while layout.count() > 0: 
        layout.itemAt(0).setParent(None)
 7
Author: SoloPilot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-08 15:57:37

Moim rozwiązaniem tego problemu jest nadpisanie metody setLayout programu QWidget. Poniższy kod aktualizuje układ do nowego układu, który może lub nie może zawierać elementów, które są już wyświetlane. Możesz po prostu utworzyć nowy obiekt układu, dodać do niego cokolwiek chcesz, a następnie wywołać setLayout. Oczywiście możesz również po prostu zadzwonić do clearLayout, aby usunąć wszystko.

def setLayout(self, layout):
    self.clearLayout()
    QWidget.setLayout(self, layout)

def clearLayout(self):
    if self.layout() is not None:
        old_layout = self.layout()
        for i in reversed(range(old_layout.count())):
            old_layout.itemAt(i).widget().setParent(None)
        import sip
        sip.delete(old_layout)
 3
Author: joshua,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-19 00:38:06

From the docs:

Aby usunąć widżet z układu, wywołaj removeWidget(). Wywołanie QWidget.hide() na widżecie również skutecznie usuwa widżet z układu do momentu wywołania QWidget.show().

removeWidget jest dziedziczona z QLayout, dlatego nie jest wymieniona wśród metod QGridLayout.

 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-24 21:31:21

Kilka rozwiązań, jeśli zamieniasz się między znanymi widżetami za pomocą ułożonego widżetu i po prostu przerzucasz pokazany indeks może być o wiele łatwiejsze niż dodawanie i usuwanie pojedynczych widżetów z układu.

Jeśli chcesz zastąpić Wszystkie potomkami widżetu, to QObject funkcje findChildren powinny cię tam znaleźć np. Nie wiem, w jaki sposób funkcje szablonu są zawinięte w pyqt. Ale możesz również wyszukiwać widżety po nazwie, jeśli je znasz.

 1
Author: Harald Scheirich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-25 16:42:00

To mój pierwszy raz w rzeczywistości odpowiadając na pytanie przepełnienie stosu, ale zobaczyłem, że wszystkie odpowiedzi tutaj są nieco błędne. (tak, Wiem, że pytanie było, aby usunąć wszystkie widżety) problem z większością z nich jest to, że nie stanowią one zagnieżdżone układy, więc zrobiłem funkcję rekurencyjną, że biorąc pod uwagę układ będzie rekurencyjnie usunąć wszystko wewnątrz niego, i wszystkie układy wewnątrz niego. tutaj jest:

def clearLayout(layout):
print("-- -- input layout: "+str(layout))
for i in reversed(range(layout.count())):
    layoutItem = layout.itemAt(i)
    if layoutItem.widget() is not None:
        widgetToRemove = layoutItem.widget()
        print("found widget: " + str(widgetToRemove))
        widgetToRemove.setParent(None)
        layout.removeWidget(widgetToRemove)
    elif layoutItem.spacerItem() is not None:
        print("found spacer: " + str(layoutItem.spacerItem()))
    else:
        layoutToRemove = layout.itemAt(i)
        print("-- found Layout: "+str(layoutToRemove))
        clearLayout(layoutToRemove)

Mogłem nie uwzględnić wszystkich typów interfejsu użytkownika, nie jestem pewien. Hope this pomaga!

 1
Author: Arthur Fakhreddine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-05 03:09:12
        for i in reversed (range(layout.count())):
            layout.itemAt(i).widget().close()
            layout.takeAt(i)

Lub

        for i in range(layout.count()):
            layout.itemAt(0).widget().close()
            layout.takeAt(0)
 0
Author: borovsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-15 23:15:07