Return value from button click

I struggled with returning a value from function which is invoked when I click button in PyQt. That’s how I’d like to put a value to the variable:

file_path = self.Button_open.clicked.connect(self.OpenTextFile)

Whole function looks like this:

def OpenTextFile(self):
    dialog = QtGui.QFileDialog()
    dialog.setWindowTitle("Choose a file to open")
    dialog.setFileMode(QtGui.QFileDialog.ExistingFile)
    dialog.setNameFilter("Text (*.txt);; All files (*.*)")
    dialog.setViewMode(QtGui.QFileDialog.Detail)

    filename = QtCore.QStringList()

    if(dialog.exec_()):
        file_name = dialog.selectedFiles()
    plain_text = open(file_name[0]).read()
    self.Editor.setPlainText(plain_text)
    return str(file_name[0])

Now, when I want to pass the file_path to the other function, python interpreter says

self.Button_save.clicked.connect(self.SaveTextFile(file_path))
TypeError: connect() slot argument should be a callable or a signal, not ‘NoneType’

Any thoughts how to make it work ?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Store the file_path in a class level variable and update that value in your button click method.

self.file_path = None
self.Button_open.clicked.connect(self.OpenTextFile)

And then,

def OpenTextFile(self):
    dialog = QtGui.QFileDialog()
    dialog.setWindowTitle("Choose a file to open")
    dialog.setFileMode(QtGui.QFileDialog.ExistingFile)
    dialog.setNameFilter("Text (*.txt);; All files (*.*)")
    dialog.setViewMode(QtGui.QFileDialog.Detail)

    filename = QtCore.QStringList()

    if(dialog.exec_()):
        file_name = dialog.selectedFiles()
    plain_text = open(file_name[0]).read()
    self.Editor.setPlainText(plain_text)
    self.file_path = str(file_name[0])

Also your

self.Button_save.clicked.connect(self.SaveTextFile(file_path))

should be

self.Button_save.clicked.connect(self.SaveTextFile)

and in your save click method

def SaveTextFile(self):
    save(self.file_path)     # Your code to save file

Method 2

Your code for getting the file path won’t work. The connect method does not call the connected function and will not assign its return value. Typically we might expect the connect to be done when the GUI is created, whereas the file_path variable should be assigned later when the open method is called. You don’t provide the code which spans the scope from the open method to the close method, but a possible solution would be to use a class level variable as suggested by Muhammad Tahir Butt.

However, the error you quote comes from this line of code:

self.Button_save.clicked.connect(self.SaveTextFile(file_path))

The problem here is that you are connecting the button click not to the function but to the result of calling the function. Python evaluates the argument before calling connect. That’s surely not what you want: your function returns None which causes the error.

There are other ways to do what you want, but the most direct fix is to create a partially evaluated function or a lambda expression which captures the value of file_path but does not yet perform the function. For example:

import functools

...

self.Button_save.clicked.connect(
        functools.partial(self.SaveTextFile,file_path))

This could fix your calling problem without changing the variables concerned.

However, note that this only works if file_path has the desired value at the time of calling the connect method. We can’t tell if that’s true in your code, but reading between the lines, probably not. So the accepted answer is probably more appropriate in your case.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x