宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离...

学习于: 学点编程吧:PyQt5图形界面编程(目录)

最终界面如下:

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第1张图片

然后是代码:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox, QLineEdit, QLabel

class Example(QWidget):

    def __init__(self):

        super().__init__()
        self.initUI()

    def initUI(self):

        self.setGeometry(300, 300, 400, 300)
        self.bt1 = QPushButton('登录', self)
        self.bt1.setGeometry(115, 150, 70 ,30)
        self.bt1.clicked.connect(self.showMessage)  # 相当于就是建立了一个click的处理事件
        
        self.usr = QLabel("用户:", self)   # 这里的好像都需要把self作为第二个参数传进去才能显示出来
        self.usr.setGeometry(50, 50, 30, 30)
        self.pwd = QLabel("密码:", self)
        self.pwd.setGeometry(50, 80, 30, 30)

        self.text1 = QLineEdit(self)#没有self的话连框都出不来
        self.text1.selectAll()
        self.text1.setFocus()
        self.text1.setGeometry(80, 50, 150 ,30)
        
        self.text2 = QLineEdit( self)
        self.text2.selectAll()
        self.text2.setFocus()
        self.text2.setGeometry(80, 80, 150 ,30)
        self.text2.setEchoMode(QLineEdit.Password)

        self.show()    

    def showMessage(self):
        acount = self.text1.text()  #这里text应该不需要转为字符串吧,返回的应该就是一个字符串。
        password= self.text2.text()
        print(acount)
        print(password)
        if len(password) == 0:
            QMessageBox.warning(self, "警告", "密码为空")
        else:
            QMessageBox.warning(self, "警告", "密码长度低于6位")
        
        if acount == "jackhe"  and  password == "123456" :
            QMessageBox.about(self, '','登录成功')
        else:
            QMessageBox.about(self, '','登录失败!') 
        
    def closeEvent(self, event):

        reply = QMessageBox.question(self, '确认', '确认退出吗', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()        
        else:
            event.ignore()

if __name__ == '__main__':

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

先讲我写完之后的第一感受吧:

感觉这个很捞,因为我发现从知乎上复制下来的不知道为啥会有缩进错误,然后干脆自己重写了一遍,或者是回退到上一行,有分号的enter一下就好。对我这个python小白来说,python的缩进真的恶心,压根看不出来哪里缩进不对,各种报indent。。Java的括号多舒服啊! 然后是忽然记起来python的变量不需要声明,直接使用就行,我第一反应就是去找哪里声明的,,尴尬。还有就是它不会自己自动导包,你需要啥包得自己去import,尴尬。还有就是里面的self的使用泛滥得不是你所能想象,调用方法必须来一个self,使用变量可以来个self。

然后回到我们得代码中来,看看怎么写这个登录界面吧。

(下面的构造函数是我从Java里引入的概念,感觉也是这个概念,大家自行理解)

先看第一步:

if __name__ == '__main__':

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

这个就不多解释了,前面文章中已经讲过了,中间是创建对象,创建对象就默认调用构造函数,构造函数中就创建UI。然后就进行应用程序的主循环。

然后看主要代码:

def __init__(self):

        super().__init__()
        self.initUI()

构造函数调用创建UI的方法。

        self.setGeometry(300, 300, 400, 300)
        self.bt1 = QPushButton('登录', self)
        self.bt1.setGeometry(115, 150, 70 ,30)
        self.bt1.clicked.connect(self.showMessage)  # 相当于就是建立了一个click的处理事件
        
        self.usr = QLabel("用户:", self)   # 这里的好像都需要把self作为第二个参数传进去才能显示出来
        self.usr.setGeometry(50, 50, 30, 30)
        self.pwd = QLabel("密码:", self)
        self.pwd.setGeometry(50, 80, 30, 30)

        self.text1 = QLineEdit(self)#没有self的话连框都出不来
        self.text1.selectAll()
        self.text1.setFocus()
        self.text1.setGeometry(80, 50, 150 ,30)
        
        self.text2 = QLineEdit( self)
        self.text2.selectAll()
        self.text2.setFocus()
        self.text2.setGeometry(80, 80, 150 ,30)
        self.text2.setEchoMode(QLineEdit.Password)

setGeometry(x,y,width,height) 前两个参数是窗口的x和y位置;第三个是宽度;第四个是窗口的高度。也就是它在一个方法中组合了resize()和move()方法。 这里注意啊!往右是x,往下是y。别搞错了。

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第2张图片

self.setGeometry设置的是整个窗体相对显示器的位置。后面的self.usr,pwd ,text1之类的都是相对于窗体的左上角的位置。这个就是确定相对位置的方法,感觉很麻烦。 pyqt5还有另外一种布局方式,可以参考 :学点编程吧:PyQt5系列教程(6):布局 ,和Java的布局差不多吧。

然后这里也是使用了几个组件,感觉很简单,就不讲了,我都是 学点编程吧:PyQt5图形界面编程(目录) 这里一搜,然后一看就用就完事了。

这里注意: 密码框是要在输入的时候不显示出输入的字符, 它本质还是QLineEdit,只是设置了 self.text2.setEchoMode(QLineEdit.Password) 这个属性而已。

然后其它的就没什么了,来到最关键的事件监听和处理上来,也就是:

self.bt1.clicked.connect(self.showMessage)

这段代码,bt1是一个button对象,clickd是这个button对象拥有的一个事件,也就是按一下会产生的影响,connect就是把这个影响传递到showMessage这个方法中。 这个是我最简单的理解方式了,我写过Java界面,安卓界面,前端,所以理解这个比较快。 学点编程吧:PyQt5系列教程(5):事件与信号处理 这里写得就非常系统具体,大家可以学习一波。 我想着值得注意的是 :

keyPressEvent(self, e)    按键时的监听,也就是监听你按下键盘的什么键。
mouseMoveEvent(self, event)   移动鼠标时的监听,比如获取鼠标当前所在所在位置信息
paintEvent(self, event)   重绘方法,这个我暂时理解位Java的重绘,也就是比如窗体的刷新,放大缩小等改变所导致的界面重绘(具体的话后面使用到再细说)
sender()获取事件发送者的信息,从而根据源来判断反应。
s = Signal()
s.showmouse.connect(某个方法)  :鼠标点击后运行的方法

感觉还是挺简单的,封装得比Java还好。调用起来贼方便。

然后最后看我们得事件处理方法:

def showMessage(self):
        acount = self.text1.text()  #这里text应该不需要转为字符串吧,返回的应该就是一个字符串。
        password= self.text2.text()
        print(acount)
        print(password)
        if len(password) == 0:
            QMessageBox.warning(self, "警告", "密码为空")
        else:
            QMessageBox.warning(self, "警告", "密码长度低于6位")
        
        if acount == "jackhe"  and  password == "123456" :
            QMessageBox.about(self, '','登录成功')
        else:
            QMessageBox.about(self, '','登录失败!') 
        
    def closeEvent(self, event):

        reply = QMessageBox.question(self, '确认', '确认退出吗', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()        
        else:
            event.ignore()

showMessage是点击按钮后的反应:获取输入文本,进行相应的逻辑处理。

closeEvent是重写了方法,代表的是点击最右上角的 x 后的事件,也就是关闭窗口的事件。

不由得感叹这个有点PyQt5有点牛逼啊!

然后接下来,我们QT designer结合eric6再来重做一遍这个功能。

先是新建一个project,然后在选择存储路径的时候,每个项目都单独分出一个文件夹

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第3张图片

ok后进入forms界面:

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第4张图片

然后右键空白处,选择new form.

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第5张图片


然后选择个基本类型为main windows. 后ok。运行QT designer如下

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第6张图片

注意红色标记部分。

然后开始创建我们的登录界面。然后就是把左边的小部件拖拽过来就ok(左键按住拖拽)。如下图,找不到的部件可以直接在左上角的搜索框进行搜索。

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第7张图片

然后注意啦,此时我们输入密码是不会隐藏字符的,所以需要把这个edit line的属性echo mode设置为password,如下图(因此后面有类似的都可以用这样的方法进行修改。),此后再输入字符即会变成隐藏字符。

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第8张图片

怎么样,是不是感觉这个搞界面简单多了,而且好看多了。关键是不用自己去尝试慢慢修改每个组件的大小和位置了。这个就很舒服。 注意,此时在QTdesigner这里一定要点击保存!ctrl+S,以后每次修改界面都要进行保存,然后重新进行后面的编译!

然后这个时候我们回到 eric6 ,点击form界面

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第9张图片

然后右键编译 compile all forms

然后进入左边的sources界面:可以发现多了一份py代码,可以进入代码按住F2运行,然后直接点击ok即可

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第10张图片

运行效果如下:

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第11张图片

也就是说,到这里为止,我们已经把界面做完了,但是里面的逻辑功能啥的都没有。所以,接下来我们要编写逻辑部分代码。

此时我们回到eric6中,进入form界面,右键ui文件,选择 generate dialog code, 然后new,选择类名和文件名。

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第12张图片

OK之后,然后把下面的click加上。

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第13张图片

然后ok。然后进入source界面:你会发现你多了一个action.py文件,如下图:

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第14张图片

这个文件是导入了你刚才的界面模块,然后我们在这里写我们的逻辑代码。刚生成的逻辑代码如下:

from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QMainWindow

from .Ui_login import Ui_MainWindow


class Action(QMainWindow, Ui_MainWindow):
    """
    Class documentation goes here.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(Action, self).__init__(parent)
        self.setupUi(self)
    
    @pyqtSlot()
    def on_pushButton_clicked(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        raise NotImplementedError

我们现在要修改这个代码变成我们想要的逻辑功能,我们在这个文件里导入了前面的main windows,所以我们是要在这个文件里运行,所以我们先加上

if __name__ == "__main__":

然后从这里开始。如下图:警告的意思就是我们没导入相应的包。import进来即可。

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第15张图片

然后到主逻辑:其实就是把我们之前写的showMessage的东西迁移过来。不过此时要注意名字的改变。

报错1:

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第16张图片

原因:导入包不成功 解决方案:删除from后的那一点

报错2:

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第17张图片

原因:没有导入sys包 解决方案:import sys

最后在action.py中 F2后如下:

宽度发生变化事件监听_PyQt5(3) :实现登录 事件监听处理 程序逻辑功能和界面分离..._第18张图片

完整代码如下: 先是UI_login.py

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

# Form implementation generated from reading ui file 'D:UsersDELLeric6workdirectoryqt3loginlogin.ui'
#
# Created by: PyQt5 UI code generator 5.6
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralWidget = QtWidgets.QWidget(MainWindow)
        self.centralWidget.setObjectName("centralWidget")
        self.lineEdit = QtWidgets.QLineEdit(self.centralWidget)
        self.lineEdit.setGeometry(QtCore.QRect(260, 160, 113, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.lineEdit_2 = QtWidgets.QLineEdit(self.centralWidget)
        self.lineEdit_2.setGeometry(QtCore.QRect(260, 190, 113, 20))
        self.lineEdit_2.setEchoMode(QtWidgets.QLineEdit.Password)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.label = QtWidgets.QLabel(self.centralWidget)
        self.label.setGeometry(QtCore.QRect(230, 160, 31, 21))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralWidget)
        self.label_2.setGeometry(QtCore.QRect(230, 190, 54, 21))
        self.label_2.setObjectName("label_2")
        self.pushButton = QtWidgets.QPushButton(self.centralWidget)
        self.pushButton.setGeometry(QtCore.QRect(260, 230, 75, 23))
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralWidget)

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

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "账号"))
        self.label_2.setText(_translate("MainWindow", "密码"))
        self.pushButton.setText(_translate("MainWindow", "登录"))


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_())

然后是action.py:

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

"""
Module implementing Action.
"""
import sys
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import *

from Ui_login import Ui_MainWindow


class Action(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Action, self).__init__(parent)
        self.setupUi(self)
        self.show()
    @pyqtSlot()
    def on_pushButton_clicked(self):
        acount = self.lineEdit.text()  #这里text应该不需要转为字符串吧,返回的应该就是一个字符串。
        password= self.lineEdit_2.text()
        print(acount)
        print(password)
        if len(password) == 0:
            QMessageBox.warning(self, "警告", "密码为空")
        else:
            QMessageBox.warning(self, "警告", "密码长度低于6位")
        
        if acount == "jackhe"  and  password == "123456" :
            QMessageBox.about(self, '','登录成功')
        else:
            QMessageBox.about(self, '','登录失败!') 
    def closeEvent(self, event):

        reply = QMessageBox.question(self, '确认', '确认退出吗', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()        
        else:
            event.ignore()
if __name__ == "__main__":
    app = QApplication(sys.argv)
    action = Action()
    sys.exit(app.exec_())

这里的closeEven是我另外加的,按理说应该可以在创建action.py哪里进行选择的。这里忘记了。所以直接自己重写了一个。

这样,我们就实现了界面和逻辑处理的分离。 虽然看起来代码挺多的,但是我们实际写的代码只是逻辑处理部分。

然后我们来分析一下这个自动生成的代码:

首先是UI_login.py:

因为我们运行的是action.py,所以这里的main部分就不用看了。

首先是setupUI,这里就是把整个界面搭建起来,retranslateUi就是把lable和button的文字输入进去。这里是一个界面和文字的分离。

然后看我们重点的action.py。

class Action(QMainWindow, Ui_MainWindow): 这里也就是说它继承了前面的UI_mainwindow这个类,所以这里也就是说这个action类拥有了父类的界面,然后self.show就直接显示出来了。 也就是说,这个实际上是把界面设计放在父类当中,然后把逻辑处理放在子类当中。 然后子类拥有父类的各种属性,比如edit line,label之类的,可以自由操作这些东西。然后运行起来就ok了。

嗯,感觉差不多就是这样了。不得不说这个设计得还是很精妙的。

没错,今天就先到这里了。

这里有很多思想都是我从Java这边借鉴过来的,不一定对,所以欢迎交流讨论。

你可能感兴趣的:(宽度发生变化事件监听)