Oualid Boukouja
Oualid Boukouja

Reputation: 21

If click Eyes icon Show/Hide password (QPushButton)

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

form password hide/show eye:
form password hide/show eye

is hiding password is show but if click again to hide not work

Upvotes: 1

Views: 3719

Answers (4)

WilberRojas
WilberRojas

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

musicamante
musicamante

Reputation: 48454

Another possibility is to add a checkable QAction to the QLineEdit and connect to the toggled (or triggered) signal.

password field with embedded button

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

bfris
bfris

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

ThePyGuy
ThePyGuy

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

Related Questions