0

So the gist is that upon running the main window, the only thin that should pop up is a login dialog box. After pressing the button to login, this dialog box should disappear, and in its place should appear the main window. So far, I've gotten the dialog box to appear, but pressing the button does nothing. The main window never shows up.

I've looked at answers from other places, but they don't seem to be working for me. Please bear with me, as I have very limited GUI experience, and I'm using Qt Designer to make things a little smoother for me. I'm sure it's obvious to some of you what I'm doing wrong, but I'm not sure what to make of some of this code.

Also, I am using simple test examples just to get the hang of it before making anything actually meaningful.

Here is the code for the dialog:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'TestDia.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Dialog(QtGui.QDialog):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(400, 300)
        Dialog.setModal(True)
        self.pushButton = QtGui.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(150, 140, 75, 23))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))
        self.pushButton.clicked.connect(lambda : self.accept())

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))
        self.pushButton.setText(_translate("Dialog", "PushButton", None))


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    Dialog = QtGui.QDialog()
    ui = Ui_Dialog()
    ui.setupUi(Dialog)
    Dialog.show()
    sys.exit(app.exec_())

And here is the code for the main window:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'MainTest.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui
from TestDia import Ui_Dialog

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(800, 600)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.label = QtGui.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(225, 170, 211, 191))
        self.label.setObjectName(_fromUtf8("label"))
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.label.setText(_translate("MainWindow", "Congraltuatonis!", None))


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)

    Dialog = QtGui.QDialog()
    dia = Ui_Dialog()
    dia.setupUi(Dialog)
    Dialog.show()
    sys.exit(app.exec_())

    if dia.exec_() ==  QtGui.QDialog.Accepted:
        MainWindow = QtGui.QMainWindow()
        ui = Ui_MainWindow()
        ui.setupUi(MainWindow)
        MainWindow.show()
        sys.exit(app.exec_())

Thanks in advance

Brandon Copeland
  • 125
  • 1
  • 2
  • 9

1 Answers1

1

The way I've solved this problem in the past is to put a function call in the main window's __init__ that displays a login dialog box (this way, the box can be skipped if credentials are stored in a configuration file, for example). When the user successfully fills out the dialog box, it allows the main window's __init__ to complete, which then allows it to be shown.

The designer files are Ui_MainWindow.py and Ui_LoginDialog.py and are generated from pyuic4.

MainWindow.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>50</x>
      <y>30</y>
      <width>411</width>
      <height>16</height>
     </rect>
    </property>
    <property name="text">
     <string>Hello World!</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>50</x>
      <y>80</y>
      <width>75</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>Push Me</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

LoginDialog.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>login_dialog</class>
 <widget class="QDialog" name="login_dialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>346</width>
    <height>132</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <widget class="QDialogButtonBox" name="buttonBox">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>90</y>
     <width>321</width>
     <height>32</height>
    </rect>
   </property>
   <property name="orientation">
    <enum>Qt::Horizontal</enum>
   </property>
   <property name="standardButtons">
    <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
   </property>
  </widget>
  <widget class="QLineEdit" name="username_LE">
   <property name="geometry">
    <rect>
     <x>128</x>
     <y>24</y>
     <width>133</width>
     <height>20</height>
    </rect>
   </property>
  </widget>
  <widget class="QLabel" name="label_2">
   <property name="geometry">
    <rect>
     <x>70</x>
     <y>50</y>
     <width>52</width>
     <height>20</height>
    </rect>
   </property>
   <property name="text">
    <string>Password:</string>
   </property>
  </widget>
  <widget class="QLabel" name="label_1">
   <property name="geometry">
    <rect>
     <x>70</x>
     <y>24</y>
     <width>52</width>
     <height>20</height>
    </rect>
   </property>
   <property name="text">
    <string>Username:</string>
   </property>
  </widget>
  <widget class="QLineEdit" name="password_LE">
   <property name="geometry">
    <rect>
     <x>128</x>
     <y>50</y>
     <width>133</width>
     <height>20</height>
    </rect>
   </property>
   <property name="echoMode">
    <enum>QLineEdit::Password</enum>
   </property>
  </widget>
 </widget>
 <tabstops>
  <tabstop>buttonBox</tabstop>
 </tabstops>
 <resources/>
 <connections>
  <connection>
   <sender>buttonBox</sender>
   <signal>accepted()</signal>
   <receiver>login_dialog</receiver>
   <slot>accept()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>248</x>
     <y>254</y>
    </hint>
    <hint type="destinationlabel">
     <x>157</x>
     <y>274</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>buttonBox</sender>
   <signal>rejected()</signal>
   <receiver>login_dialog</receiver>
   <slot>reject()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>316</x>
     <y>260</y>
    </hint>
    <hint type="destinationlabel">
     <x>286</x>
     <y>274</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>

LoginDialog.py:

from PyQt4.QtGui import QDialog
from Ui_LoginDialog import Ui_login_dialog

class LoginDialog(QDialog):       
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_login_dialog()
        self.ui.setupUi(self)

    def get_username(self):
        return self.ui.username_LE.text()

    def get_password(self):
        return self.ui.password_LE.text()

    def is_valid(self):
        # determine if username and password combination are valid
        return True

MainWindow.py:

from PyQt4.QtGui import QMainWindow
from Ui_MainWindow import Ui_MainWindow
from LoginDialog import LoginDialog
from LoginError import LoginError

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Show login dialog before anything else
        self._show_login_dialog()

        # Finish initializing the GUI
        self.ui.label.setText('Hello {}!'.format(self.user))
        self.ui.pushButton.clicked.connect(self._button_pushed)

    def _show_login_dialog(self):
        ld = LoginDialog(self)
        if ld.exec_() and ld.is_valid(): # If user pressed OK and entered a valid info
            self.user = ld.get_username()
        else:
            #User either cancelled the login dialog or didn't enter valid info
            raise LoginError

    def _button_pushed(self):
        self.ui.label.setText('{}, you pressed the button!'.format(self.user))

LoginError.py:

class LoginError(Exception):
    pass

main.py:

import sys
from PyQt4.QtGui import QApplication
from MainWindow import MainWindow
from LoginError import LoginError

if __name__ == '__main__':
    app = QApplication(sys.argv)

    try:
        main = MainWindow()
        main.show()
    except LoginError:
        # do something if the user can't log in
        sys.exit()

    sys.exit(app.exec_())
dbc
  • 677
  • 8
  • 21
  • I don't think I realized it until now, but I'm not supposed to be editing the pyuic-generated code, am I? I take it I'm supposed to make "driver" classes for the GUI classes? – Brandon Copeland Mar 04 '16 at 19:33
  • Correct--if you try to edit the pyuic-generated code, it will be overwritten the next time you run pyuic. – dbc Mar 04 '16 at 19:42
  • Also, I showed all of the custom (or "driver") classes in one file, but I prefer to put each class in its own file for code maintainability and readability. – dbc Mar 04 '16 at 19:43
  • I've been looking over the code and fiddling with it, but I'm still not quite getting it. I don't see anywhere in the code where the dialog box is supposed to show up. I managed to get both of them to show up at once, but I can't seem to get it to where only the dialog box shows at first. Also, are you sure I shouldn't edit the GUI code? In order to get the button in the dialog to do anything, don't I have to assign it a callback within the code? – Brandon Copeland Mar 04 '16 at 20:20
  • The result of `exec_()` on a QDialog object lets you know if the user pressed OK or Cancel. I've edited my example to be fully working, and it shows how you would link a button up to an action, as well. – dbc Mar 04 '16 at 23:04
  • I tested your code and it works just fine. Thank you for your contribution. I'll be sure to read it over and more of the documentation until I get it down. – Brandon Copeland Mar 05 '16 at 18:17