как правильно удалить qwidgets и обновить/перезагрузить этот виджет

Попытка удалить qwidget и заменить его другим qwidget, а затем перезагрузить макет, частью которого является qwidget

Я уже пробовал метод update и removeWidget, хотя мог бы использовать его неправильно

from PyQt5.Qt import *
import sys

validUser = False
app = None

class App(QMainWindow):
    def __init__(self):
        super().__init__()
        screen = app.primaryScreen().size()
        self.title = 'Restaurant Application'
        width = screen.width()
        height = screen.height()
        self.left = 0
        self.top = 0
        self.width = width
        self.height = height
        self.setMouseTracking(True)
        self.table_widget = MyTableWidget(self)
        self.setCentralWidget(self.table_widget)
        self.initUI()

        self.show()

    def initUI(self):
        # window
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        # statusbar
        self.statusBar().showMessage('Welcome to el restaurante')

    def mousePressEvent(self, event):
        print('Mouse coords: ( %d : %d )' % (event.x(), event.y()))


class MyTableWidget(QWidget):

    def __init__(self, parent):
        super(QWidget, self).__init__(parent)
        self.layout = QVBoxLayout(self)

        # Initialize tab screen
        self.tabs = QTabWidget()
        self.login = QWidget()
        self.menu = QWidget()
        self.checkOut = QWidget()
        self.tabs.resize(500, 200)

        # Add tabs
        self.tabs.addTab(self.login, "Login")
        self.tabs.addTab(self.menu, "Menu")
        self.tabs.addTab(self.checkOut, "Check out")

        # Create login tab
        self.login.layout = QVBoxLayout(self)
        self.menu.layout = QVBoxLayout(self)

        # login text
        self.loginPrompt = QLabel("Please provide a valid login")
        self.loginPrompt.setFixedSize(315,30)
        self.loginPromptFont = QFont("Times", 27, QFont.Bold)
        self.loginPrompt.setFont(self.loginPromptFont)
        self.login.layout.addWidget(self.loginPrompt)
        self.login.setLayout(self.login.layout)

        # Create textbox
        self.loginTextbox = QLineEdit(self)
        self.loginTextbox.returnPressed.connect(self.on_click_login)
        self.loginTextbox.setFixedSize(170,20)

        # Create a button in the window
        self.loginButton = QPushButton('Login button', self)
        self.loginButton.clicked.connect(self.on_click_login)
        self.loginButton.setFixedSize(100,40)
        self.login.layout.addWidget(self.loginTextbox,alignment=Qt.AlignCenter)
        self.login.layout.addWidget(self.loginButton,alignment=Qt.AlignCenter)


        #widget code i use to decide which widget to add
        self.menuInvalidUserLogin = QLabel("Please login in to view")
        self.menuValidUserLogin = QLabel("Here's the menu")

        if(validUser):
            self.menu.layout.addWidget(self.menuValidUserLogin)
        else:
            self.menu.layout.addWidget(self.menuInvalidUserLogin)
        self.menu.setLayout(self.menu.layout)

        # Add tabs to widget
        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)

    def on_click_login(self):
        global validUser
        global app
        textboxValue = self.loginTextbox.text()
        if(textboxValue.lower() == 'pass'):
            validUser=True
            #the solutions i have been trying
            self.menu.layout.removeWidget(self.menuInvalidUserLogin)
            self.layout.removeWidget(self.menuInvalidUserLogin)
            self.menu.layout.update()

            QMessageBox.question(self, 'Response', "Login successful: Welcome", QMessageBox.Ok,QMessageBox.Ok)
        else:
            validUser=False
            QMessageBox.question(self, 'Response', "Login unsuccessful: EXPLAIN YOURSELF", QMessageBox.Ok,QMessageBox.Ok)
        self.loginTextbox.setText("")

app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())

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


person Shahroz Imtiaz    schedule 31.07.2019    source источник


Ответы (1)


Это то, что вы ожидали?

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

from PyQt5 import QtWidgets, QtCore, QtGui
import sys

class App(QtWidgets.QMainWindow):
    def __init__(self):
        super(App,self).__init__()
        app = QtWidgets.QApplication.instance()
        screen = app.primaryScreen().size()
        self.title = 'Restaurant Application'
        width = screen.width()
        height = screen.height()
        self.left = 0
        self.top = 0
        self.width = width
        self.height = height
        self.setMouseTracking(True)
        self.table_widget = MyTableWidget(self)
        self.setCentralWidget(self.table_widget)
        self.initUI()
        self.show()

    def initUI(self):
        # window
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        # statusbar
        self.statusBar().showMessage('Welcome to el restaurante')

    def mousePressEvent(self, event):
        print('Mouse coords: ( %d : %d )' % (event.x(), event.y()))


class MyTableWidget(QtWidgets.QWidget):

    def __init__(self, parent):
        super(MyTableWidget, self).__init__(parent)
        self.layout = QtWidgets.QVBoxLayout()
        self.validUser = False

        # Initialize tab screen
        self.tabs = QtWidgets.QTabWidget()
        self.login = QtWidgets.QWidget()
        self.menu = QtWidgets.QWidget()
        self.checkOut = QtWidgets.QWidget()
        self.tabs.resize(500, 200)

        # Add tabs
        self.tabs.addTab(self.login, "Login")
        self.tabs.addTab(self.menu, "Menu")
        self.tabs.addTab(self.checkOut, "Check out")

        # Create login tab
        self.login.layout = QtWidgets.QVBoxLayout()
        self.menu.layout = QtWidgets.QVBoxLayout()

        # login text
        self.loginPrompt = QtWidgets.QLabel("Please provide a valid login")
        self.loginPrompt.setFixedSize(315,30)
        self.loginPromptFont = QtGui.QFont("Times", 27, QtGui.QFont.Bold)
        self.loginPrompt.setFont(self.loginPromptFont)
        self.login.layout.addWidget(self.loginPrompt)
        self.login.setLayout(self.login.layout)

        # Create textbox
        self.loginTextbox = QtWidgets.QLineEdit()
        self.loginTextbox.returnPressed.connect(self.on_click_login)
        self.loginTextbox.setFixedSize(170,20)

        # Create a button in the window
        self.loginButton = QtWidgets.QPushButton('Login button')
        self.loginButton.clicked.connect(self.on_click_login)
        self.loginButton.setFixedSize(100,40)
        self.login.layout.addWidget(self.loginTextbox,alignment=QtCore.Qt.AlignCenter)
        self.login.layout.addWidget(self.loginButton,alignment=QtCore.Qt.AlignCenter)


        #widget code i use to decide which widget to add
        self.menuInvalidUserLogin = QtWidgets.QLabel("Please login in to view")
        self.menuValidUserLogin = QtWidgets.QLabel("Here's the menu")

        if(self.validUser):
            self.menu.layout.addWidget(self.menuValidUserLogin)
        else:
            self.menu.layout.addWidget(self.menuInvalidUserLogin)
        self.menu.setLayout(self.menu.layout)

        # Add tabs to widget
        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)

    def on_click_login(self):
        textboxValue = self.loginTextbox.text()
        if(textboxValue.lower() == 'pass'):
            self.validUser=True
            for i in reversed(range(self.menu.layout.count())): 
                widgetToRemove = self.menu.layout.itemAt(i).widget()
                self.menu.layout.removeWidget(widgetToRemove)
                widgetToRemove.deleteLater()
            self.menu.layout.addWidget(self.menuValidUserLogin)
            QtWidgets.QMessageBox.question(self, 'Response', "Login successful: Welcome", QtWidgets.QMessageBox.Ok,QtWidgets.QMessageBox.Ok)
            self.tabs.setCurrentIndex(1)
        else:
            self.validUser=False
            QtWidgets.QMessageBox.question(self, 'Response', "Login unsuccessful: EXPLAIN YOURSELF", QtWidgets.QMessageBox.Ok,QtWidgets.QMessageBox.Ok)
        self.loginTextbox.setText("")

def main():        
    app = QtWidgets.QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

person Drees    schedule 31.07.2019
comment
да, это сработало! не могли бы вы объяснить, что код делает с setParent(None)? Откуда код знает, что нужно вызывать метод, используемый для вкладки меню, без метода update(). Вы знаете, почему метод removeWidget не работал? И я также получаю эти предупреждения о QLayout: Попытка добавить QLayout в MyTableWidget , у которого уже есть макет - person Shahroz Imtiaz; 31.07.2019
comment
@ShahrozImtiaz Я обновил код, чтобы удалить виджет из списка макетов, а также графический интерфейс. Технически вы не удаляете объект, вы просто устанавливаете его как виджет верхнего уровня. Обновленный код по-прежнему выдает вам предупреждения о QLayout? Кроме того, где он выдает эту ошибку? - person Drees; 31.07.2019
comment
@ShahrozImtiaz removeWidget просто удаляет виджет из макета, но на самом деле не удаляет объект, он делает его там, где макет больше не может его использовать, но объект все еще там. - person Drees; 31.07.2019
comment
@ShahrozImtiaz, если мой ответ решил ваш вопрос, проголосуйте и отметьте его как решенный. - person Drees; 31.07.2019
comment
да, предупреждение выводится на консоль, поэтому я не знаю, где/что его вызывает - person Shahroz Imtiaz; 31.07.2019
comment
@Shahroz Imtiaz - это предупреждение, происходящее с тем же кодом, что и я, или вы добавили к нему, что именно вы делаете для создания предупреждения? - person Drees; 31.07.2019
comment
@ShahrozImtiaz Я обновил код, чтобы удалить родительские виджеты (макеты, метки, кнопки). Когда вы добавляете виджет в макет, он автоматически устанавливает родителя для любого виджета, который его удерживает. Нет необходимости явно указывать виджету родителя. Я предпочитаю предоставлять классы (QtCore, QtWidgets, QtGui) явно, а не просто импортировать все, так как это повышает читабельность. Попробуйте и дайте мне знать, если это все еще выдает предупреждение. - person Drees; 31.07.2019