PyQt5系列教程(12):構建我們自己的密碼輸入框

上期我們學習了消息對話框(QMessageBox),這次我們自己構建一個對話框。

還記得我們第一次學習輸入對話框的時候嗎?

QInputDialog.getText(self, 修改姓名, 請輸入姓名:)n

當時我就在想,能不能改成密碼輸入的框呢,改造後的效果如下:

我們實現了三種密碼輸入框的方式:

  1. 輸入的密碼不可見;
  2. 輸入的密碼可見,但是滑鼠點擊其他控制項後,密碼不可見;
  3. 輸入的密碼不可見,同時為了更加的安全,屏蔽了滑鼠右鍵、禁用複製、粘貼快捷鍵、滑鼠在密碼框中不可移動,不可全選。就類似我們在輸入QQ密碼的時候一樣。

因為採用了自定義對話框方式,我們將自定義對話框和主程序分別放在兩個py文件中,分別取名為:PasswdDialog.py和main.py。由於代碼較多,我們將主要的代碼進行展示並講解,全部的代碼,可以關注微信公眾號:發送pyqt512,獲取。

重點講解自定義對話框的構建。

from PyQt5.QtWidgets import QDialog, QApplication, QLineEdit, QLabel, QPushButton, QHBoxLayout, QVBoxLayout, QMessageBoxnfrom PyQt5.QtCore import Qt, QEvent, QRegExpnfrom PyQt5.QtGui import QKeyEvent, QKeySequence, QRegExpValidatornnclass PasswdDialog(QDialog):n def __init__(self):n super().__init__()n self.initUI() nn def initUI(self):n self.resize(350,100)n self.setWindowTitle("密碼輸入框")nn self.lb = QLabel("請輸入密碼:",self)nn self.edit = QLineEdit(self)n self.edit.installEventFilter(self)nn self.bt1 = QPushButton("確定",self)n self.bt2 = QPushButton("取消",self)n n #怎麼布局在布局篇介紹過,這裡代碼省略...nn self.edit.setContextMenuPolicy(Qt.NoContextMenu)n self.edit.setPlaceholderText("密碼6-15位,只能有數字和字母,必須以字母開頭")n self.edit.setEchoMode(QLineEdit.Password)nn regx = QRegExp("^[a-zA-Z][0-9A-Za-z]{14}$")n validator = QRegExpValidator(regx, self.edit)n self.edit.setValidator(validator)nn self.bt1.clicked.connect(self.Ok)n self.bt2.clicked.connect(self.Cancel)nn object = QObject()n def eventFilter(self, object, event):n if object == self.edit:n if event.type() == QEvent.MouseMove or event.type() == QEvent.MouseButtonDblClick:n return Truen elif event.type() == QEvent.KeyPress:n key = QKeyEvent(event)n if key.matches(QKeySequence.SelectAll) or key.matches(QKeySequence.Copy) or key.matches(QKeySequence.Paste):n return Truen return QDialog.eventFilter(self, object, event)n n def Ok(self):n self.text = self.edit.text()n if len(self.text) == 0:n QMessageBox.warning(self, "警告", "密碼為空")n elif len(self.text) < 6:n QMessageBox.warning(self, "警告", "密碼長度低於6位")n else:n self.done(1) # 結束對話框返回1nn def Cancel(self):n self.done(0) # 結束對話框返回0n

其實大家從這段代碼中我們可以看出,本質上就是QDialog的繼承,加上自己希望的界面和實現的功能。因此QDialog所有的屬性,我們自定義對話框PasswdDialog都會有,這樣能夠省掉我們不少的時間來。這個也就是面向對象編程的魅力所在了。

from PyQt5.QtCore import Qt, QEvent, QRegExpnfrom PyQt5.QtGui import QKeyEvent, QKeySequence, QRegExpValidatorn

這裡我們導入的類有很多新的面孔,例如:QEvent、QRegExp、QKeyEvent、QKeySequence、QRegExpValidator,這裡我們不做講解,在後面具體的代碼我們在一一學習。

這次講解不全按照代碼的順序,按照難度由淺入深的順序講解。

基礎部分

self.edit.setContextMenuPolicy(Qt.NoContextMenu)nself.edit.setPlaceholderText("密碼6-15位,只能有數字和字母,必須以字母開頭")nself.edit.setEchoMode(QLineEdit.Password)n

這個三個語句是給密碼輸入框增加一些屬性。

self.edit.setContextMenuPolicy(Qt.NoContextMenu)n

這個語句設置QLineEdit對象的上下文菜單的策略。如果不寫這句話,我們在密碼輸入框中單擊右鍵是這樣的:

大家可以看到出現複製、粘貼等菜單,這樣對於密碼的輸入是不安全的。所以我們在此設置了Qt.NoContextMenu,即不允許出現上下文菜單。

self.edit.setPlaceholderText("密碼6-15位,只能有數字和字母,必須以字母開頭")n

只要行編輯為空,設置此屬性將使行編輯顯示為灰色的佔位符文本。默認情況下,此屬性包含一個空字元串。效果是這樣:

這是非常好的使用方法,可以在用戶輸入密碼前看到一些小提示信息,但是又不影響使用,非常棒這個方法。

self.edit.setEchoMode(QLineEdit.Password)n

這條語句設置了如何限定輸入框中顯示其包含信息的方式,這裡設置的是:密碼方式,即輸入的時候呈現出原點出來。像這樣:

當然我們還可以設置其他的方式如下:

最後一種的樣式是這樣的,我們一起來看一下。

我們可以根據自己的需要酌情選用合適方式。

正則表達式

regx = QRegExp("^[a-zA-Z][0-9A-Za-z]{14}$")nvalidator = QRegExpValidator(regx, self.edit)nself.edit.setValidator(validator)n

這三段代碼大體意思就是說,運用正則表達式限定密碼輸入框字元接收的條件:

  1. 長度不能超過15位;
  2. 字母開頭;
  3. 後面跟著的字元只能是字母或者數字。

這三段代碼涉及到的:QRegExp、QRegExpValidator引入方式如下:

from PyQt5.QtCore import QRegExpnfrom PyQt5.QtGui import QRegExpValidatorn

QRegExp類使用正則表達式提供模式匹配。正則表達式是用於匹配文本中的子字元串的模式。

名詞解釋:

正則表達式,又稱規則表達式,英文名為Regular Expression,在代碼中常簡寫為regex、regexp或RE,是計算機科學的一個概念。正則表通常被用來檢索、替換那些符合某個模式(規則)的文本。

正則表達式是對字元串(包括普通字元(例如,a 到 z 之間的字母)和特殊字元(稱為「元字元」))操作的一種邏輯公式,就是用事先定義好的一些特定字元、及這些特定字元的組合,組成一個「規則字元串」,這個「規則字元串」用來表達對字元串的一種過濾邏輯。正則表達式是一種文本模式,模式描述在搜索文本時要匹配的一個或多個字元串。(來源:百度百科)

regx = QRegExp("^[a-zA-Z][0-9A-Za-z]{14}$")n

為給定的模式字元串構造一個正則表達式對象。

validator = QRegExpValidator(regx, self.edit)n

構造一個驗證器,該父對象接受與正則表達式匹配的所有字元串。這裡的父對象就是QLineEdit對象了。匹配是針對整個字元串; 例如:如果正則表達式是[A-Fa-f0-9]+將被視為^[A-Fa-f0-9]+$。

self.edit.setValidator(validator)n

將密碼輸入框設置為僅接受符合驗證器條件的輸入。 這允許您對可能輸入的文本設置任何約束條件。因此我們這裡設置的就是符合上面描述的三種約束條件。

事件過濾器

object = QObject()n def eventFilter(self, object, event):n if object == self.edit:n if event.type() == QEvent.MouseMove or event.type() == QEvent.MouseButtonDblClick:n return Truen elif event.type() == QEvent.KeyPress:n key = QKeyEvent(event)n if key.matches(QKeySequence.SelectAll) or key.matches(QKeySequence.Copy) or key.matches(QKeySequence.Paste):n return Truen return QDialog.eventFilter(self, object, event)n

事件過濾器可是一個非常重要的概念。根據Qt的官方文檔,如果對象被安裝已監視對象的事件過濾器,則過濾事件。如果要過濾事件,需重新實現此函數時,若停止進一步處理,返回true; 否則返回false。

如果一個對象安裝多個事件過濾器,那麼,最後安裝的過濾器首先被激活。

警告:如果在eventFilter()函數中刪除接收對象,一定要返回true。如果返回false,Qt給已刪除的對象發送事件,程序就會掛了。

注意,過濾器對象必須和被觀察者對象處於同一線程。如果過濾器對象在不同的線程,這個函數什麼都不做。如果在調用這個函數之後,過濾器對象或被觀察者對象被移動到不同的線程,事件過濾器將不會被調用,直到兩個對象再處於相同的線程中。

本例中明確需要監測的對象,即對誰進行監測。是密碼輸入框,或者是這個主窗口,因為它們擁有一些共同的事件,如果不明確,不知道要過濾誰的事件。本例中為其安裝事件過濾器如下:

self.edit.installEventFilter(self)n

然後進行事件判斷與轉換:滑鼠移動對應的事件類型為QEvent.MouseMove,滑鼠雙擊對應的事件類型為QEvent.MouseButtonDblClick,全選、複製、粘貼對應的事件類型為 QEvent.KeyPress,當接收到這些事件時,需要被過濾掉,所以返回true。

注意:return QDialog.eventFilter(self,object,event)這句代碼很關鍵,這裡的意思是繼續傳遞該事件到被觀察者,由其本身調用相應的事件。

if object == self.edit: n if event.type() == QEvent.MouseMove or event.type() == QEvent.MouseButtonDblClick:n return Truen elif event.type() == QEvent.KeyPress:n key = QKeyEvent(event)n if key.matches(QKeySequence.SelectAll) or key.matches(QKeySequence.Copy) or key.matches(QKeySequence.Paste):n return Truen

這裡是對事件的判斷。其中QKeyEvent類描述了一個關鍵事件。當按下或釋放按鍵時,主要事件將發送到具有鍵盤輸入焦點的小部件。然後運用matches方法匹配具體的按鍵。例如:QKeySequence.SelectAll表示全選,QKeySequence.Copy表示複製,QKeySequence.Paste表示粘貼。當然還有其它的按鍵組合。詳見:QKeySequence Class

其它

def Ok(self):n self.text = self.edit.text()n if len(self.text) == 0:n QMessageBox.warning(self, "警告", "密碼為空")n elif len(self.text) < 6:n QMessageBox.warning(self, "警告", "密碼長度低於6位")n else:n self.done(1) # 結束對話框返回1nndef Cancel(self):n self.done(0) # 結束對話框返回0n

這個語句比較簡單,就是判斷輸入框的上用戶點了的按鈕,是確定還是取消;如果按了確定鍵看長度是否符合要求否則給予警告。最後使用done語句關閉對話框並將其結果設置為一個整數。如果此對話框顯示為exec(),那麼done()會導致本地事件循環完成,exec()返回該整數。

最後

本次重點介紹了我們自定義對話框:密碼輸入框的編寫,主程序main.py因為比較簡單,這裡就不做講解,可以自己下載源碼看一下。

ok,今天就到這裡,我們下期還會再談一次對話框,本身對話框內容就比較多,會多分幾期講解。

如果你想要本次教程中的相關源碼,請關注微信公眾號:學點編程吧,發送pyqt512,會自動得到相應的百度網盤下載鏈接。

更多的PyQt5的文章,請在微信公眾號:我的指南→技術文章→PyQt查找。。


推薦閱讀:

TAG:Python | Python教程 | PyQt |