Chr*_*oph 3 python model-view-controller pyqt pyqt5
我正在用 Python 创建我的第一个应用程序。目前我正在使用 PyQt5 和 MVC 模式实现第一个视图。因此,我创建了一个“主”类,它通过创建一个新的控制器对象来启动控制器(我学习的第一种编程语言是 Java,所以也许这不是必需的?)。在这个控制器对象 init 方法中,我创建了第一个视图。视图类本身会创建一个新的QWidget. 后QWidget创建所述控制器被调用的视图的方法(QWidget)。此方法应显示登录屏幕。为了显示登录屏幕,创建了一个新类(登录)。该类属于该类型QVBoxLayout并已添加到主视图 ( QWidget)。这种组合会导致一个应用程序显示一个带有登录信息的窗口。这意味着主类 -> 控制器 ->QWidget) -> 登录 ( QVBoxLayout)。
在这里我有以下问题:创建主窗口(QWidget)并使用方法将内部布局添加到窗口(使用其他文件/类)是否正确?还是应该将所有内容写在一个类中?
现在我达到了正确显示我的布局和窗口的地步。缺少的是模型以及模型的调用方式。我搜索了如何检查按钮是否被按下。我发现button.clicked.connect(callfunction). 这似乎是正确的方法,但如何从控制器调用此函数?以便控制器创建应用程序窗口并在此窗口内显示登录信息。然后控制器监听并等待按钮被按下。然后输入将被转发到模型,并在模型中检查凭据。这是我尝试听按钮的控制器的源代码:
class Controller(object):
def __init__(self):
# Applikation starten und Login anzeigen
app = QApplication(sys.argv)
widget = View()
widget.showLogin(0, "")
widget.loginButton.clicked.connect(self.loginPressed())
sys.exit(app.exec_())
def loginPressed(self):
widget.showLogin(1, "err1")
Run Code Online (Sandbox Code Playgroud)
我的登录类的代码:
def __init__(self):
super().__init__()
# Zum vertikalen zentrieren des Inhalts
self.addStretch()
# Label (Bild) erstellen und zum Layout hinzufügen
label = QLabel()
pixmap = QPixmap(pathLogo)
label.setPixmap(pixmap.scaledToWidth(logoWidth, Qt.SmoothTransformation))
label.setAlignment(Qt.AlignCenter)
self.addWidget(label)
# Label für den Nutzername
usernameLabel = QLabel("Username")
usernameLabel.setAlignment(Qt.AlignCenter)
usernameLabel.setStyleSheet("QLabel {color: #ffffff; font-size: 14px; font-weight:bold; "
"margin:50px, 0, 5px, 0 ;}")
self.addWidget(usernameLabel)
# Eingabefeld für den Nutzername
uihbox = QHBoxLayout()
uihbox.addStretch()
usernameInput = QLineEdit()
usernameInput.setFixedWidth(150)
usernameInput.setStyleSheet(
"QLineEdit {border-radius: 5px; padding: 4px; line-height:12px; padding-left: 5px;}")
uihbox.addWidget(usernameInput)
uihbox.addStretch()
self.addLayout(uihbox)
# Label für das Passwort
passwortLabel = QLabel("Passwort")
passwortLabel.setAlignment(Qt.AlignCenter)
passwortLabel.setStyleSheet("QLabel {color: #ffffff; font-size: 14px; font-weight:bold; "
"margin:15px, 0, 5px, 0 ;}")
self.addWidget(passwortLabel)
# Eingabefeld für den Nutzername
pihbox = QHBoxLayout()
pihbox.addStretch()
passwordInput = QLineEdit()
passwordInput.setFixedWidth(150)
passwordInput.setEchoMode(QLineEdit.Password)
passwordInput.setStyleSheet(
"QLineEdit {border-radius: 5px; padding: 4px; line-height:12px; padding-left: 5px;}")
pihbox.addWidget(passwordInput)
pihbox.addStretch()
self.addLayout(pihbox)
# Button erstellen
bihbox = QHBoxLayout()
bihbox.addStretch()
loginButton = QPushButton("Login")
loginButton.setStyleSheet("QPushButton {margin: 25px, 0, 0, 0; border-radius:5px; border: 1px solid white; "
"padding-right: 15px; padding-left: 15px; padding-top: 5px; padding-bottom:5px;"
"color:white; font-weight:bold; font-size: 14px;}")
loginButton.setCursor(QCursor(Qt.PointingHandCursor))
bihbox.addWidget(loginButton)
bihbox.addStretch()
self.addLayout(bihbox)
# Zum vertikalen zentrieren des Inhalts
self.addStretch()
def showError(self, errCode):
errMsg = QLabel(err1)
errMsg.setAlignment(Qt.AlignCenter)
errMsg.setStyleSheet("QLabel {color:red;}")
self.addWidget(errMsg)
self.addStretch()
Run Code Online (Sandbox Code Playgroud)
而我的 View 类:
class View(QWidget):
# Methode um das Fenster der Applikation zu initialisieren
def __init__(self):
super().__init__()
# Breite und Höhe setzen
self.resize(initWidth, initHeight)
# Titel und Icon setzen
self.setWindowTitle(appTitle)
self.setWindowIcon(QIcon(pathFavicon))
# Hintergrund mit der bgColor füllen
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), QColor(bgColor))
self.setPalette(p)
# Anzeigen des Fensters
self.show()
# Methode, um Login zu zeigen
def showLogin(self, err, errcode):
# Laden des Inhalts mittels Login
if (err != 0):
vbox = Login()
vbox.showError(errcode)
if (err == 0):
vbox = Login()
self.setLayout(vbox)
Run Code Online (Sandbox Code Playgroud)
进一步的问题:
QVBoxLayout使用错误代码调用登录以在视图底部显示错误。我还没有找到从控制器类动态更改视图的方法。我能想象到的唯一解决方案是QWidget使用添加的错误消息“重新绘制” 的内容。这是正确的解决方案吗?提前致谢!
这个想法不是类的数量,而是每个类的任务是什么。
那么你认为你的类实现了上述内容吗?
在下面的示例中,我展示了如何重新分配这些任务,我的示例不符合@101指出的所有经典 MCV 规则,因为 GUI 具有内部事件处理程序。
import sys
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets
class Model:
def __init__(self):
self.username = ""
self.password = ""
def verify_password(self):
return self.username == "USER" and self.password == "PASS"
class View(QtWidgets.QWidget):
verifySignal = QtCore.pyqtSignal()
def __init__(self):
super(View, self).__init__()
self.username = ""
self.password = ""
self.initUi()
def initUi(self):
lay = QtWidgets.QVBoxLayout(self)
title = QtWidgets.QLabel("<b>LOGIN</b>")
lay.addWidget(title, alignment=QtCore.Qt.AlignHCenter)
fwidget = QtWidgets.QWidget()
flay = QtWidgets.QFormLayout(fwidget)
self.usernameInput = QtWidgets.QLineEdit()
self.usernameInput.textChanged.connect(partial(setattr, self, "username"))
self.passwordInput = QtWidgets.QLineEdit(echoMode=QtWidgets.QLineEdit.Password)
self.passwordInput.textChanged.connect(partial(setattr, self, "password"))
self.loginButton = QtWidgets.QPushButton("Login")
self.loginButton.clicked.connect(self.verifySignal)
flay.addRow("Username: ", self.usernameInput)
flay.addRow("Password: ", self.passwordInput)
flay.addRow(self.loginButton)
lay.addWidget(fwidget, alignment=QtCore.Qt.AlignHCenter)
lay.addStretch()
def clear(self):
self.usernameInput.clear()
self.passwordInput.clear()
def showMessage(self):
messageBox = QtWidgets.QMessageBox(self)
messageBox.setText("your credentials are valid\n Welcome")
messageBox.exec_()
self.close()
def showError(self):
messageBox = QtWidgets.QMessageBox(self)
messageBox.setText("your credentials are not valid\nTry again...")
messageBox.setIcon(QtWidgets.QMessageBox.Critical)
messageBox.exec_()
class Controller:
def __init__(self):
self._app = QtWidgets.QApplication(sys.argv)
self._model = Model()
self._view = View()
self.init()
def init(self):
self._view.verifySignal.connect(self.verify_credentials)
def verify_credentials(self):
self._model.username = self._view.username
self._model.password = self._view.password
self._view.clear()
if self._model.verify_password():
self._view.showMessage()
else:
self._view.showError()
def run(self):
self._view.show()
return self._app.exec_()
if __name__ == '__main__':
c = Controller()
sys.exit(c.run())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4460 次 |
| 最近记录: |