QLineEdit
控件是一个单行文本输入框,它继承自QWidget
,是一个纯文本的输入框,接收键盘的输入,可显示为明文(如QQ登录框中的账号框)或者是密文(如QQ登录框中的密码框)。
创建单行文本框:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210,110)
#创建一个单行文本框
le = QLineEdit(w)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
由于是单行文本框,所以无法换行,如果内容过多,则会滚动显示。构造函数也可以使创建文本框时,默认显示一行文字:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210,110)
#创建一个单行文本框
le = QLineEdit("单行文本框",w)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
QLineEidt 显示文本可以用户主动输入,也可以由程序设置显示的内容。
API | 含义 |
---|---|
setText() | 设置文本 |
insert(newText) | 插入文本 |
text() | 获取文本内容 |
displayText() | 获取文本显示的内容 |
其中,如果程序设置了密文显示,text()
将获取到用户输入的真实值,而displayText()
将获取到星号。
程序示例了insert(newText)
的使用:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210,110)
le = QLineEdit(w) #创建一个当行文本框
le.setText("一个单行文本框") #设置文本为:一个单行文本框
le.insert(" 123") #在光标处插入:123
print(le.text()) #获取并打印输入文本框
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
第12行:插入了字符“123”,该函数在光标处插入字符串
第13行:获取并打印了文本框的内容
注:使用 setText("") 或清空函数(详见后文)可以清楚文本框。
显示模式决定了输入框文本的显示情况,可以是明文,密文,或者是完全不显示等。
相关API:
API | 含义 |
---|---|
setEchoMode(QLineEdit_EchoMode) | 设置显示模式 |
echoMode() | 获取文本框输入模式 |
其参数是一个枚举值
QLineEdit_EchoMode | 含义 |
---|---|
Normal | 普通模式,显示输入的值 |
NoEcho | 不输出 |
Password | 密文显示,显示都是星号 |
PasswordEchoOnEdit | 输入时候显示,结束后密文 |
其中,NoEcho是安全性最高的,无论用户输入什么,都不显示,与密文Password
相比,它连位数都是保密的。Unbuntu终端密码就是类似这种想过,初次使用很容易误以为程序不响应。
程序示例输出模式的设置和获取:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210,110)
le0 = QLineEdit(w)
le0.setEchoMode(QLineEdit.PasswordEchoOnEdit) #设置显示模式:输入时明文,完毕后密文
le1 = QLineEdit(w)
le1.move(0,30)
le1.setEchoMode(QLineEdit.Password) #设置显示模式:密文输入
# 打印模式
print(le0.echoMode())
print(le1.echoMode())
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
因为第1个输入框设置了PasswordEchoOnEdit
,所以当光标离开以后,明文就变成了密文。
占位提示文本框时在文本框内显示提示文本,但是和显示文本不同,当获取焦点并输入文字以后,占位文本将被取消。
相关API
函数 | 含义 |
---|---|
setPlaceholderText(notice_str) | 设置占位文本 |
placeholderText() | 获取占位文本 |
占位文本示例:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210,110)
le0 = QLineEdit(w)
le0.setEchoMode(QLineEdit.PasswordEchoOnEdit) #设置显示模式:输入时明文,完毕后密文
le0.setPlaceholderText("请输入文字") #设置占位文本
print(le0.placeholderText()) #获取占位文本
w.show()
if __name__ == '__main__':
运行:
注意到,这里占位文本和普通文本是不同的,此处使用获取占用文本的函数才可以获取到占位文本。
单行文本可以通过函数设置清空文本按钮。
函数 | 含义 |
---|---|
setClearButtonEnabled(bool) | 使/失能 清空按钮 |
isClearButtonEnabled() | 查看清空按钮状态 |
示例:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210,110)
le0 = QLineEdit(w)
le0.setEchoMode(QLineEdit.PasswordEchoOnEdit) #设置显示模式:输入时明文,完毕后密文
le0.setText("12345") #设置文本
le0.setClearButtonEnabled(True) #使能情况按键
print(le0.isClearButtonEnabled()) #打印按钮状态
print(le0.placeholderText()) #获取占位文本
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
当按钮被按下时,文本会被清空,注意到,这里只有存在文本时,按钮才会被显示。
添加操作行为可以在单行文本框内添加一个行为,即提供一个按钮,通常这个按钮用来设置文本的显示形式,添加行为使用addAction()
方法:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210,110)
le0 = QLineEdit(w)
# 添加行为
action = QAction(le0)
action.setIcon(QIcon("eye_on")) #设置行为的图标
le0.addAction(action, QLineEdit.TrailingPosition) #在单行文本框尾部添加该行为
print(le0.isClearButtonEnabled()) #打印按钮状态
print(le0.placeholderText()) #获取占位文本
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
这个action也可以添加在文本框的尾部,但是必须指定位置,否则不会显示。
上文的Aciton只是图标,可通过其信号来triggered
添加动作:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210,110)
le0 = QLineEdit(w)
# 定义槽函数
def slot():
if le0.echoMode() == QLineEdit.Normal:
action.setIcon(QIcon("eye_hidden"))
le0.setEchoMode(QLineEdit.PasswordEchoOnEdit)
else:
action.setIcon(QIcon("eye_on"))
le0.setEchoMode(QLineEdit.Normal)
# 添加行为
action = QAction(le0)
action.setIcon(QIcon("eye_on")) #设置行为的图标
action.triggered.connect(slot) #连接槽函数
le0.addAction(action, QLineEdit.TrailingPosition) #在单行文本框尾部添加该行为
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
第14~20行:定义槽函数,当Action被点击时,该函数被触发。函数根据当前文本框的显示模式,切换图标和显示的模式。
第25行:该信号还有一个参数,表示按键是否被选中,所以也可以使用这个参数来判断,但是次数的Action默认是不能被选中的,所以需要设置按键可被选中状态,该参数才有意义。
自动补全指的是如果历史记录有过匹配的账号,将弹出提醒。可以运用于登录框中,用户经常需要输入自己的账号,如果曾经登录过,那么输入第一个字母时,就可以补全账号。程序也可以设置默认的候选对象。默认的候选词通过setCompleter()
来设置。
示例:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210,110)
le0 = QLineEdit(w)
completer = QCompleter(["Yonas", "Yun", "Luo", "Cat", "Dog", "Water"]) #设置候选词
le0.setCompleter(completer) #添加候选词
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行后输入Y:
注意到,这里是大小写敏感的,用户可以通过鼠标点击和键盘方向按键来选择。
输入限制是通过程序来对输入的文本进行限制,如只读,长度,内容类型等。
相关API | 含义 |
---|---|
setMaxLength(int) | 这是最大长度 |
maxLength() | 获取最长度 |
setReadOnly(bool) | 设置只读 |
isReadOnly() | 获取知否只读 |
setValidator(QValidator) | 设置验证器 |
setInputMask(mask_str) | 掩码验证 |
hasAcceptableInput() | 文本是否通过验证 |
示例:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210,110)
le0 = QLineEdit(w)
le0.setText("Read Only")
le0.setReadOnly(True)
le0.setMaxLength(5)
w.show()
if __name__ == '__main__':.
sys.exit(app.exec_())
运行:
由于设置了只读,它看起来就像一个标签(Label),由于我们还设置了最大长度为5,所以程序设置了“Read Only”但是只显示了“Read ”
可以通过设置验证器(QValidator
)来验证文本是否合法,通常,一些网站要求密码有一定的格式,如长度不能过短,需要特殊符号等 。QValidator
是一个虚拟的类,不能被直接实例化,需用用户自定义子类方可使用。
以下程序示例了一个验证器的使用,但是它并不是真实的验证器,因为它并没有校验规则:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210, 110)
# 子类化 QValidator
class AgeVadidator(QValidator):
def validate(self,input_str,pos_int):
print(input_str,pos_int)
return(QValidator.Acceptable, input_str, pos_int) #返回验证结果
le0 = QLineEdit(w)
vadidator = AgeVadidator() #创建验证器
le0.setValidator(vadidator) #添加验证器
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
当程序输入文本以后,每一次文本的改变,都会触发一次validate()
函数,该函数打印了文本和光标所在的位置。validate()
返回3个值,第1个为验证的状态,第2个为文本的值,第3个为光标所在位置。它传入了2个参数,分别为输入的文本和光标的位置。
注意到,返回的文本这里直接返回输入的文本,如果你对这参数做了修改,QLineEidt的文本也将随着修改,返回的光标位置同样有影响。
验证器(validate()
函数)返回值有3种状态:
状态 | 含义 |
---|---|
QValidator.Acceptable | 验证通过,输入的文本给予显示 |
QValidator.Intermediate | 不确定,输入的文本给予显示 |
QValidator.Invalid | 验证不通过,输入的文本不显示 |
需要Intermediate中间状态的原因数,有时候无法确定输入的字符是否是有效的,比如我们想要用户输入18-180的值,当用户第一个字符输入“9”时,但是光标位离开编辑框,此时validate()
函数就需要返回这值。
fixup()
是修复函数,是文本输入完毕后调用的函数,此时程序可以最后判断值是否合理,如果不合理,是显示空字符串(清空)或者是默认设置一个值。注意到:validate()
是当文本变化一次,就调用一次,而fixup()
是文本输入结束(比如焦点切换到其他输入框中)且本文不符合要求,才调用。
接下来我们对程序进一步补充, 让校验器能对数据进行判断,规定用户只能输入:18-180 的数值
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210, 110)
# 子类化 QValidator
class AgeVadidator(QValidator):
#定义校验函数
def validate(self,input_str,pos_int):
# 判定字符串是否是 数字
try: #捕获异常
if 18 <= int(input_str) <= 180:
return (QValidator.Acceptable, input_str, pos_int) #返回验证结果:正确
elif 1 <= int(input_str) <= 17:
return (QValidator.Intermediate, input_str, pos_int) #返回验证结果:无法确定
else:
return (QValidator.Invalid, input_str, pos_int) #返回验证结果:无效
except: #异常处理
if len(input_str) == 0:
return (QValidator.Intermediate, input_str, pos_int)
return (QValidator.Invalid, input_str, pos_int) #返回验证结果:无效
#定义修复模式
def fixup(self, p_str):
print(p_str)
try:
if int(p_str) <18:
return "18"
except:
return "18"
le0 = QLineEdit(w)
vadidator = AgeVadidator() #创建验证器
le0.setValidator(vadidator) #添加验证器
le1 = QLineEdit(w)
le1.move(0,30)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:略
第15行:捕获一个异常,因为程序使用了int(input_str)
将输入的字符串转为数值,如果是英文字母,中文则会出错,测试需要捕获这个异常,显然的,只要是非法输入,直接返回QValidator.Invalid
,所以输入字母或是中文等非数值字符串,是不被显示的。
第24~25行:if len(input_str) == 0:
作用是避免输入框无法清除的情况,因为如果用户删除了最后一个字符(或是一次性全删除),那么会返回一个空的字符串,自然int(input_str)
要出现异常,此时捕获到异常则不能按普通非法文本那么处理——非法文本的处理是不给予显示,这会导致用户无法删除字符串。
第27行:定一个了fixup()
,它同样需要捕获异常,虽然用户无法输入非数字字符串,但是输入框可能是空的,如果空,同样int(p_str)要产生异常。这里程序的设定是,如果输入一个小于18的数字,则返回一个“18”,这样如果用户输入17,然后点击其他文本框,程序就会将文本设置为“18”。注意,测试过程中发现这里返回""
(空字符串)并不能清空文本,如果你需要用户输入错误时候清空,可以使用setText("")
函数来清空文本框。
上文通过了自定义验证器的方式来实现程序对文本的验证,而对于常用的验证,系统以及为开发者提供了子类:
子类 | 含义 |
---|---|
QIntValidator(bottom, top, parent) | 限制整型数据范围 |
QDoubleValidator | 浮点类型数据限制范围(目前测试无效) |
QRegExpValidator | 通过正则表达式限定 |
使用QIntValidator
函数定义一个整形范文验证器:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210, 110)
le0 = QLineEdit(w)
vadidator = QIntValidator(65, 180) #创建整形数据区间验证器
le0.setValidator(vadidator) # 添加验证器
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
虽然程序设置了(65-180)但是当用户输入60以后结束输入(比如将焦点移动到另一个输入框),程序默认是没响应的。所以它看起来只限制了最大值。那么如需要处理小于最小值的数值输入,需要重写该子类的方法:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210, 110)
class MyAgeVadidator(QIntValidator):
def fixup(self,p_str):
if len(p_str) == 0 or int(p_str) < 65:
le0.setText("") #清空输入框
le0 = QLineEdit(w)
vadidator = MyAgeVadidator(65,180) #创建整形数据区间验证器
le0.setValidator(vadidator) #添加验证器
le1 = QLineEdit(w)
le1.move(0,30)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
只需重写fixup
函数即可,这里的处理与之前稍微不同,当出现小于最小值的数字,自己清空编辑框。
运行:略
这里的掩码指在文本框实现不同的位置输入不同的格式文本。例如IP地址输入框:xxxx-xxxx-xxxx-xxxx
以下程序功能实现:总共输入5位,左边两位必须是大写字母,右边两位必须是数字:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210, 110)
le0 = QLineEdit(w)
le0.setInputMask(">AA-99;#") #设置掩码格式
le1 = QLineEdit(w)
le1.move(0,30)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
第12行:表明了一种规则,其中,“>”表示该处字母为大写,“AA”表示接下来的两位为字母,“-”为风格号,“99”表示这两位为数字,“;”表示规则已经结束,“#”号为占位符号。
这些符号需要通过官方文档来查明其含义:掩码字符含义
相关API | 含义 |
---|---|
isModified() | 是否被编辑 |
setModified() | 设置编辑状态 |
当文本框文本有改动以后,更新状态就为True
,所以当处理完编辑状态以后,需要程序主动清楚编辑的标志位。以下程序创建了一个按钮,如果文本框的文字有改变,按下按钮后打印新的文本,如果不改变则不打印。
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210, 110)
le0 = QLineEdit(w)
btn = QPushButton("是否编辑", w)
btn.move(0,60)
def slot():
print(le0.isModified())
if(le0.isModified()):
print("新文本为",le0.text())
le0.setModified(False)
btn.clicked.connect(slot)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
第15行:定义了一个按键的槽函数,将新文本打印出来以后,就将编辑状态改为False
,这样就能实现按下按键,打印修改过的文本,反之则不打印。
默认情况下,光标至于文本最后,随着文本删减而移动。光标也可以通过程序来控制。
相关API | 含义 |
---|---|
cursorBackward(bool mark,int steps = 1) | 回退steps个位置,即向左移动多少字符 |
cursorForward(bool mark,int steps = 1) | 前进steps个位置,即向右移动多少字符 |
cursorWordBackward(bool mark) | 是否带选中,即光标“路过”的字符都被选中状态] |
home(bool) | 移动到首行(参数表示是否选中) |
end(bool) | 移动到尾行(参数表示是否选中) |
setCursorPosition(int) | 设置光标位置 |
cursorPosition() | 获取光标位置 |
cursorPositionAt(const QPoint& pos) | 获取指定坐标(相对文本)对应的光标位置 |
以下程序示例了,当按键按下时候,光标左移2个字符并选中的功能:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(210, 110)
le0 = QLineEdit(w)
btn = QPushButton("按钮", w)
btn.move(0,60)
def slot():
le0.cursorBackward(True, 2)
btn.clicked.connect(slot)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
文本边框可通过setTextMargins(int left, int top, int right, int bottom)
函数设置:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(300, 300)
le0 = QLineEdit(w)
le0.resize(100,100)
le0.move(100,100)
le0.setTextMargins(30,30,20,20)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
系统提供了水平和垂直方向对齐设置,可通过setAlignment()
来设置:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(300, 300)
le0 = QLineEdit(w)
le0.resize(100,100)
le0.move(100,100)
le0.setAlignment(Qt.AlignRight) #设置右对齐
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
对齐 | 参数 |
---|---|
水平方向 | Qt.AlignLeft |
Qt.AlignRight | |
Qt.AlignHCenter | |
Qt.AlignJustify | |
垂直 | Qt.AlignTop |
Qt.AlignBottom | |
Qt.AlignVCenter | |
Qt.AlignBaseline | |
中心垂直 | Qt.AlignCenter |
文本有一些常用的操作,如复制,粘贴,撤销,重做,删除等,这些在QLineEdit
的邮件菜单已经提供给用户,也可以通过程序设置。下表列出了常用操作的一些API函数:
相关API | |
---|---|
backspace() | 删除右侧一个字符或选中的所有字符 |
del_() | 删除左侧一个字符或选中的所有字符 |
clear() | 清空 |
copy() | 复制 |
cut() | 剪贴 |
paste() | 粘贴 |
undo() | 撤销 |
setDragEnabled(bool) | 设置文本是否可以拖拽 |
setSelection(start_pos, length) | 选中指定区间的文本 |
selectAll() | 选择所有文本 |
deselect() | 取消已选择的文本 |
hasSelectedText() | 是否选中了文本 |
selectedText() -> str | 获取选中的文本 |
selectionStart() -> int | 选中开始的位置 |
selectionEnd() -> int | 选中结束的位置 |
selectionLength() -> int | 选中的长度 |
以下程序使能了第一个文本框内文字的拖拽功能:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(200, 100)
le0 = QLineEdit(w)
le1 = QLineEdit(w)
le1.move(0,30)
le0.setDragEnabled(True) #使能拖拽功能
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
QLineEdit默认是不能拖拽的,所以程序只使能第一个文本框的情况下,只有第一个文本框可以拖拽文字。
如果使用按钮来编辑文本框,需要注意一种情况:当用户点击按钮的时候,文本框会失去光标。比如,当你设置按钮的功能为[删除选中文字]时候,由于点击按钮时候,会失去焦点,此时文本框会取消选择的文字,接着按钮去删除文字,就会出现非预期的效果。
相关信号 | 含义 |
---|---|
textEdited( text) | 文本被[用户]编辑时发出信号 |
textChanged(text) | 文本框文本改变时发出信号 |
returnPressed() | 用户按下回车时发出信号 |
editingFinished() | 结束编辑时发出信号 |
cursorPositionChanged(int oldPos,int newPos) | 光标位置改变时发出信号 |
selectionChanged() | 选择的文本发送改变时候发出信号 |
textEdited( text)
和 textChanged(text)
不同点是,前者强调了用户编辑,只要文本框被用户编辑,就会发射信号,而后者无论是程序改变还是用户编辑,只要文本发送改变,就会发射信号。
当编辑框失去焦点时,就认为结束的编辑,此时会发射editingFinished()
信号。
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QLineEdit")
w.resize(200, 100)
le0 = QLineEdit(w)
le0.setText("信号测试")
le1 = QLineEdit(w)
le1.move(0,30)
def change_slot(text):
print("文本被改变了",text)
def edit_slot(text):
print("文本被编辑了", text)
def finsh_slot():
print("结束编辑了")
le0.textChanged.connect(change_slot)
le0.textEdited.connect(edit_slot)
le0.editingFinished.connect(finsh_slot)
w.show()