Reputation: 21
I'm trying to create a function in a register and login form using QLineEdit
to show and hide password if click a QPushButton
. I'm a beginner in Python, I'm just trying to do it but it's very hard... My attempt is not good because if I click the eye button the password is shown, but if click again to hide it does not work.
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QPushButton, QLineEdit
import sys
import pymysql
pymysql.install_as_MySQLdb()
class MyWindow(QtWidgets.QMainWindow):
def __init__(self, maxWidth=None):
super(MyWindow, self).__init__()
uic.loadUi('MainWindow.ui', self)
self.eyepass_show()
self.eyepass_hide()
self.btn_show_pwd.clicked.connect(self.eyepass_hide)
self.btn_show_pwd.clicked.connect(self.eyepass_show)
def eyepass_show(self):
self.line_password.setEchoMode(QLineEdit.Normal)
print('show pass')
def eyepass_hide(self):
self.line_password.setEchoMode(QLineEdit.Password)
print('hide pass')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
is hiding password is show but if click again to hide not work
Upvotes: 1
Views: 3719
Reputation: 1
In case you need the same thing in several places, it is better to create a new QWidget with those features.
So you use "PasswordLineEdit" instead "QLineEdit" in passwords:
from PySide6.QtWidgets import QLineEdit, QApplication, QMainWindow, QVBoxLayout, QWidget
from PySide6.QtGui import QIcon, QAction
class PasswordLineEdit(QLineEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.setEchoMode(QLineEdit.Password)
self.iconShow = QIcon('icons/eye.png')
self.iconHide = QIcon('icons/eye_blind.png')
self.showPassAction = QAction(self.iconShow, 'Show password', self)
self.addAction(self.showPassAction, QLineEdit.TrailingPosition)
self.showPassAction.setCheckable(True)
self.showPassAction.toggled.connect(self.togglePasswordVisibility)
def togglePasswordVisibility(self, show):
if show:
self.setEchoMode(QLineEdit.Normal)
self.showPassAction.setIcon(self.iconHide)
else:
self.setEchoMode(QLineEdit.Password)
self.showPassAction.setIcon(self.iconShow)
if __name__ == "__main__":
import sys
# ------ usage:
class MyWindow(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout(self)
self.line_password = PasswordLineEdit() # <-
layout.addWidget(self.line_password)
# ------
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec())
Upvotes: 0
Reputation: 48454
Another possibility is to add a checkable QAction to the QLineEdit and connect to the toggled
(or triggered
) signal.
class MyWindow(QtWidgets.QMainWindow):
def __init__(self, maxWidth=None):
super(MyWindow, self).__init__()
uic.loadUi('MainWindow.ui', self)
icon = QtGui.QIcon('eye-icon.png')
self.showPassAction = QtWidgets.QAction(icon, 'Show password', self)
self.line_password.addAction(
self.showPassAction, QtWidgets.QLineEdit.TrailingPosition)
self.showPassAction.setCheckable(True)
self.showPassAction.toggled.connect(self.showPassword)
def showPassword(self, show):
self.line_password.setEchoMode(
QtWidgets.QLineEdit.Normal if show else QtWidgets.QLineEdit.Password)
If you want to show the password only when the mouse is pressed, then don't connect to the toggled
signal, but find the child QToolButton for that action and connect to the pressed
and released
instead. In this case, the action doesn't need to be checkable.
self.line_password.addAction(
self.showPassAction, QtWidgets.QLineEdit.TrailingPosition)
showPassButton = self.line_password.findChild(QtWidgets.QAbstractButton)
showPassButton.pressed.connect(lambda: self.showPassword(True))
showPassButton.released.connect(lambda: self.showPassword(False))
Upvotes: 1
Reputation: 5835
One of the great things about PyQt5 is that it will automatically connect signals to methods for you. If you have a button named <mybutton>
and a method in your app named on_<mybutton>_clicked
, the the loadUi will automatically connect. So the pattern is
on_<widget_name>_<signal>
If we apply this to your problem, you should make your show/hide button a toggle button. In Qt Designer, set the checkable property to True (or do btn_show_pwd.clicked.setChecked(True)
)
The code:
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QPushButton, QLineEdit
import sys
#import pymysql
#pymysql.install_as_MySQLdb()
class MyWindow(QtWidgets.QMainWindow):
def __init__(self, maxWidth=None):
super(MyWindow, self).__init__()
uic.loadUi('test1.ui', self)
self.line_password.setEchoMode(QLineEdit.Password)
def on_btn_show_pwd_toggled(self, checked):
if checked:
self.line_password.setEchoMode(QLineEdit.Password)
else:
self.line_password.setEchoMode(QLineEdit.Normal)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
Upvotes: -1
Reputation: 18456
Instead of creating two separate methods as eyepass_show
and eyepass_hide
, you can create a single function and toggle the visibility. Also, you are trying to connect the same signal twice to two different methods by self.btn_show_pwd.clicked.connect(self.eyepass_hide)
and self.btn_show_pwd.clicked.connect(self.eyepass_show)
Try something like this:
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QPushButton, QLineEdit
import sys
import pymysql
pymysql.install_as_MySQLdb()
class MyWindow(QtWidgets.QMainWindow):
def __init__(self, maxWidth=None):
super(MyWindow, self).__init__()
uic.loadUi('MainWindow.ui', self)
self.eyepass_show()
self.eyepass_hide()
self.btn_show_pwd.clicked.connect(self.toggleVisibility)
def toggleVisibility(self):
if self.line_password.echoMode()==QLineEdit.Normal:
self.line_password.setEchoMode(QLineEdit.Password)
else:
self.line_password.setEchoMode(QLineEdit.Normal)
# self.btn_show_pwd.clicked.connect(self.eyepass_hide)
# self.btn_show_pwd.clicked.connect(self.eyepass_show)
#
# def eyepass_show(self):
# self.line_password.setEchoMode(QLineEdit.Normal)
# print('show pass')
#
# def eyepass_hide(self):
# self.line_password.setEchoMode(QLineEdit.Password)
# print('hide pass')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
Upvotes: 1