How can I reuse my function without any error?

Question:

I want to make my lineEdits turn red if they are empty when I click submit button. After adding something back I want to make my lineEdit turn back to white. This is what I have right now

from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog
import sys, os
from PyQt5.uic import loadUi
from BlurWindow.blurWindow import blur

def input_validate(self,lineedit):
    if self.lineedit.text() == '':
      self.lineedit.setStyleSheet('''
      QLineEdit{font: 15pt "Yu Gothic"; border-style:none; border-bottom:1px solid rgba(255,0,0,0.6); color:white; 
      }
      QLineEdit:focus {
      background-color:rgba(255,255,255,0.5);
      } ''')
      return False
    else:
      self.lineedit.setStyleSheet('''
      QLineEdit{font: 15pt "Yu Gothic"; border-style:none; border-bottom:1px solid rgba(255,255,255,0.6); color:white; 
      }
      QLineEdit:focus {
      background-color:rgba(255,255,255,0.5);
      } ''')
      return True

class MainWindow(QMainWindow):
  def __init__(self):
    super(MainWindow, self).__init__()
    loadUi(r'D:WorkspaceQt Designerblur bgblurtest.ui',self)
    self.setAttribute(Qt.WA_TranslucentBackground)
    blur(self.winId())
    self.setStyleSheet("background-color: rgba(0, 0, 0, 0)")

    self.browse1.clicked.connect(self.browsefile1)
    self.browse2.clicked.connect(self.browsefile2)
    self.submit.clicked.connect(self.submit1)
    self.setAttribute(Qt.WA_TranslucentBackground)
    blur(self.winId())
    self.setStyleSheet("background-color: rgba(0, 0, 0, 0)")

  def browsefile1(self):
    fname=QFileDialog.getOpenFileName(self,'Open File',os.getcwd())
    self.lineEdit1.setText(fname[0])
  def browsefile2(self):
    fname=QFileDialog.getOpenFileName(self,'Open File',os.getcwd())
    self.lineEdit2.setText(fname[0])
  def submit1(self):
    if not input_validate(self.lineEdit1) or not input_validate(self.lineEdit2):
      return
    print("successs")

app=QApplication(sys.argv)
mw=MainWindow()
mw.show()
sys.exit(app.exec_())

First I tried seperating this input_validate as a class :

class input_validate(QMainWindow):
  def __init__(self):
    super().__init__()
    if self.lineEdit.text() == '':
      self.lineEdit.setStyleSheet('''
      QLineEdit{font: 15pt "Yu Gothic"; border-style:none; border-bottom:1px solid rgba(255,0,0,0.6); color:white; 
      }
      QLineEdit:focus {
      background-color:rgba(255,255,255,0.5);
      } ''')
      return False
    else:
      self.lineEdit.setStyleSheet('''
      QLineEdit{font: 15pt "Yu Gothic"; border-style:none; border-bottom:1px solid rgba(255,255,255,0.6); color:white; 
      }
      QLineEdit:focus {
      background-color:rgba(255,255,255,0.5);
      } ''')
      return True

The error I got was
if not input_validate(self.lineEdit1) or not input_validate(self.lineEdit2):
TypeError: input_validate.init() takes 1 positional argument but 2 were given

So then I tried putting it inside the MainWindow class itself but this time it says
if not input_validate(self.lineEdit1) or not input_validate(self.lineEdit2):
NameError: name ‘input_validate’ is not defined

So I put it outside the MainWindow class to make it global and the first code block is what I have.

Now my error is
if not input_validate(self.lineEdit1) or not input_validate(self.lineEdit2):
TypeError: input_validate() missing 1 required positional argument: ‘lineedit’

I don’t know how can I solve this now. The long way would be to define the input_validate with linedit1 and lineedit2 separately but I want to figure out how can I reuse that code.

Also I wanted to know if it is ok to inherit QMainWindow instead of QWidget. This is supposed to be a one window thing for now with this as the first window to appear, so I selected it as a main window. Max it will have is a success popup or error popup message on clicking submit (which I guess I have to implement using QMessageBox)

Asked By: jj4giya

||

Answers:

EDIT: Regarding the issue in comments:

class MainWindow(QMainWindow):
    ... #Other stuff

    #Here, if 'submit' is clicked, it will check both lineEdit1 and lineEdit2
    #self.input_validate(self.lineEdit1, self.lineEdit2)
    #EG: self.input_validate(self.a, self.b, ...)
    #No need to pass as list, just add commas with brackets
    self.submit.clicked.connect(lambda: self.input_validate(self.lineEdit1, self.lineEdit2)) #Triggers the function created below

    #If text is changed, no argument is passed so it defaults to check
    #only lineEdit1
    #If you do want to change both
    #self.lineEdit1.textChanged.connect(lambda: self.input_validate(self.lineEdit1, self.lineEdit2))
    self.lineEdit.textChanged.connect(self.input_validate) 
    #It triggers whenever the text is changed in the lineEdit even with using setText,
    #If you want to just check when the user changes it, you can use textEdited. 

    def input_validate(self, *args):

        #If args is empty (no argument is passed), it defaults to self.lineEdit1
        if not args: args = [self.lineEdit1]

        for x in args:
            if x.text() == '':
                ... #Set StyleSheet for Red
            else:
                ... #Set StyleSheet for White

You can add any number of lineEdit to change using the function. Just separate it with a comma.
self.input_validate(self.lineEdit1, self.lineEdit2, self.lineEdit3, ...).

Original answer:
Your approach is way off and can be a little complex than it may seem. You can simply define a function in MainWindow class for more simplicity and easier execution. In your first snippet of code, you have defined input_validate outside of the class.

class MainWindow(QMainWindow):
    ... #Other stuff

    self.submit.clicked.connect(self.input_validate) #Triggers the function created below
    
    self.lineEdit.textChanged.connect(self.input_validate) 
    #It triggers whenever the text is changed in the lineEdit even with using setText,
    #If you want to just check when the user changes it, you can use textEdited. 

    def input_validate(self):
        if self.lineEdit.text() == '':
            ... #Set StyleSheet for Red
        else:
            ... #Set StyleSheet for White

Also, the lineEdit will turn to color Red if the user clears it. If you don’t want it to happen you can add an argument in input_validate, and return the function if the argument is True so the function will not check for lineEdit.text().

And if you have to add parameters in connect, you have to use lambda, e.g.: self.lineEdit.textChanged.connect(lambda: input_validate()).

Answered By: Sam
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.