Search code examples
pythonpyqt5qwidgetqmainwindow

python - pyqt5: error in show two form, name 'Window' is not defined


Welcome..

i have two form: Form1=>Window & form2 =>MainWindow

The problem occurs after pressing the exit button in the main window. Where it is supposed to return to the login window again.

form1 (Window for Login) code:

import sys
from PyQt5.QtWidgets import *
from form2 import *
class Window(QWidget):
    right_uname = "admin"
    right_pword = "password"

    def __init__(self):
        super().__init__()

        self.init_ui()

    def init_ui(self):
        self.lbl_intro = QLabel('Welcome, please login')
        self.lbl_enter_username = QLabel('Username:')
        self.lbl_enter_password = QLabel('Password:')
        self.txt_enter_username = QLineEdit()
        self.txt_enter_password = QLineEdit()
        self.cb_login = QCheckBox('Stay logged in?')
        self.btn_login = QPushButton('Login')


        self.grid = QGridLayout()
        self.grid.setSpacing(5)

        self.grid.addWidget(self.lbl_intro, 1, 1)

        self.grid.addWidget(self.lbl_enter_username, 2, 0)
        self.grid.addWidget(self.txt_enter_username, 2, 1)

        self.grid.addWidget(self.lbl_enter_password, 3, 0)
        self.grid.addWidget(self.txt_enter_password, 3, 1)

        self.grid.addWidget(self.cb_login, 4, 1)
        self.grid.addWidget(self.btn_login, 5, 1)


        self.v_box = QVBoxLayout()
        self.v_box.addStretch(0)
        self.v_box.addLayout(self.grid)
        self.v_box.addStretch(0)

        self.h_box = QHBoxLayout()
        self.h_box.addStretch(0)
        self.h_box.addLayout(self.v_box)
        self.h_box.addStretch(0)

        self.setLayout(self.h_box)

        self.btn_login.clicked.connect(lambda: self.btn_login_clk(self.txt_enter_username, self.txt_enter_password, self.cb_login.isChecked(), self.lbl_intro))


        self.setWindowTitle('Login test')

        self.show()

    def btn_login_clk(self, username, password, cb, intro):
        if username.text() == self.right_uname and password.text() == self.right_pword:
            if cb:
                intro.setText('Welcome,' + ' ' + self.right_uname + ' ' + 'cb ticked')
            else:
                self.mw = MainWindow()
                self.hide()
                self.mw.show()
        else:
            intro.setText('Wrong username or password')
            self.clear_box()

    def clear_box(self):
        self.txt_enter_username.clear()
        self.txt_enter_password.clear()
        self.txt_enter_username.setFocus()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    a_window = Window()
    sys.exit(app.exec())

from2 (MainWindow) code:

from form1 import *
class MainWindow(Window):


    def __init__(self):
        super().__init__()

        self.init_ui()

    def init_ui(self):
        self.lbl_intro = QLabel('Main Window')
        self.lbl_user_logged = QLabel('Welcome,' + ' ' + self.right_uname)
        self.lbl_append = QLabel('Write something')
        self.txt_write_box = QLineEdit()
        self.btn_append = QPushButton('Append')
        self.btn_logout = QPushButton('Logout')

        layout = QVBoxLayout()
        layout.addWidget(self.lbl_intro)
        layout.addWidget(self.lbl_user_logged)
        layout.addWidget(self.lbl_append)
        layout.addWidget(self.txt_write_box)
        layout.addWidget(self.btn_append)
        layout.addWidget(self.btn_logout)

        self.setLayout(layout)
        self.setWindowTitle('Main')

        self.btn_append.clicked.connect(self.append_clk)
        self.btn_logout.clicked.connect(self.logout_action)

        self.show()

    def append_clk(self):
        self.appendee = open('text.txt', 'a')
        self.appendee.write('hry')
        self.appendee.close()

    def logout_action(self):
        self.close()
        a_window = Window(self)
        a_window.show()
        a_window.clear_box()

When running: name 'Window' is not defined


Solution

  • It looks like some sort of circular import problem to me, but I cannot replicate it though. Which version of Python are you using?

    Anyway, firstly I would try changing form1 so that that import is local right before using MainWindow, to see if that solves the problem. I.e. removing the from form2 import * line at the top of form1 and changing your btn_login_clk method to this:

    def btn_login_clk(self, username, password, cb, intro):
        if username.text() == self.right_uname and password.text() == self.right_pword:
            if cb:
                intro.setText('Welcome,' + ' ' + self.right_uname + ' ' + 'cb ticked')
            else:
                from form2 import MainWindow  # local import
                self.mw = MainWindow()
                self.hide()
                self.mw.show()
        else:
            intro.setText('Wrong username or password')
            self.clear_box()
    

    On a slightly unrelated topic, I see that, when closing your MainWindow (i.e. logging out), you create a Window with the parent set to the MainWindow which you just closed. This will probably caluse the new window to be killed even before it appears (in my case, nothing appears and python exits with code 1), so the self argument should probably be removed:

    def logout_action(self):
        self.close()
        a_window = Window()  # no 'self' argument
        a_window.show()
        a_window.clear_box()