需要PyQt5 GUI结构建议

时间:2017-02-28 09:54:20

标签: python user-interface pyqt pyqt5

我正在为用户界面编写程序。我对Qt很新,但我喜欢使用它,特别感谢Qt设计师。该程序应如下所示:它有一个带有2个选项卡的主窗口。第一个选项卡是登录,带有用户/密码字段和两个按钮,"登录"和"退出"。 "退出"当然会退出应用程序,"登录"将尝试向服务器发送SOAP请求以进行登录。如果不成功,则会显示带有错误的弹出窗口。如果成功,将显示带有成功消息的弹出窗口,并且激活并显示Tab2,其中用户可以插入一些数据(使用组合框,其值取决于程序在连接到服务器后下载的某些表)。这是代码的修剪版本:

class Ui_PopupError(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(322, 101)
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(60, 20, 221, 16))
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(120, 60, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.retranslateUi(Dialog)
        self.pushButton.clicked.connect(Dialog.reject)
        QtCore.QMetaObject.connectSlotsByName(Dialog)
    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.label.setText(_translate("Dialog", "Wrong Username or Password. Try Again"))
        self.pushButton.setText(_translate("Dialog", "Ok"))
class Ui_PopupSuccess(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(322, 101)
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(60, 20, 221, 16))
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(120, 60, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.retranslateUi(Dialog)
        self.pushButton.clicked.connect(Dialog.accept)
        QtCore.QMetaObject.connectSlotsByName(Dialog)
    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.label.setText(_translate("Dialog", "Successfully connected."))
        self.pushButton.setText(_translate("Dialog", "Ok"))

class Ui_MainWindow(object):
    def LoginMacro(self):
        Username = self.Usernamefield.text()
        Password = self.Passwordfield.text()
        req = urllib.request.Request("server")
        body = SOAPBody
        response = urllib.request.urlopen(req, body)
        try:
            soup = BeautifulSoup(response.read(), 'html.parser')
            testo = soup.get_text().strip()
            tree = ET.fromstring(testo)
            sessionid = tree.attrib['sessionid']
            self.popup = QtWidgets.QDialog()
            self.popupui = Ui_PopupSuccess()
            self.popupui.setupUi(self.popup)
            self.popup.show()
            self.tabWidget.setCurrentIndex(1)
            self.Recap_Tab.setEnabled(True)
        except:
            self.popup = QtWidgets.QDialog()
            self.popupui = Ui_PopupError()
            self.popupui.setupUi(self.popup)
            self.popup.show()
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(798, 867)
        #MainWindow created with QT Designer (long code...)
        self.Exit.clicked.connect(MainWindow.close)
        self.Login.clicked.connect(self.LoginMacro)
        #This is an example of the value which should feed the combobox:
        self.Handling_Type.addItems(REF_UDF_VALUES['udf_reference_value'][REF_UDF_VALUES['udf_cd']=='Handling Type'])
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        #Retranslate created with Qt designer....(cut)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

我只是想问你这是否是正确的方法。特别是,我有一些问题需要理解在哪里放置代码来实现"真正的"事物(与服务器通信)。例如,我将登录代码放在MainWindow类中,但我不确定这是否有效,因为我需要从此代码中捕获jsessionid以便运行另一个下载表的代码。我应该把它放在哪里?如果我把它放在"尝试"部分代码然后告诉我,当它试图在主窗口中初始化组合框时,它无法找到引用表。我知道,我很乱! :)

谢谢你,对不起这个长期的问题感到抱歉!

1 个答案:

答案 0 :(得分:1)

与后端之间的通信应与GUI定义分开。我创建了一个名为API的单独类来处理请求/响应,并为我的API创建一个QMainWindow实例。这是一个示例,我们希望用一个用户列表填充QComboBox

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

        self.api = API()

        users = self.api.get_users()
        self.user_widget = self.ui.userCombo
        self.user_widget.setModel(UserListModel(users, self))

class API:
    def __init__(self):
        self.base_url = 'http://localhost:5000/api'
        self.users_url = '/users'
        self.timeout = 5

    def get_users(self):
        try:
            r = requests.get(self.base_url + self.users_url, timeout=self.timeout)
        except ConnectionError:
            print("Could not connect to API")
            return API.make_default_user_list()

        users = r.json(object_hook=API.api_hook_handler)

        return users

如您所见,MainWindow并不关心用户数据请求是成功还是失败。无论哪种方式,api.get_users()都会返回MainWindow可以使用的内容。