Reputation: 81
In my PyQt5 program, I have tabs and use one function for creating the same tab multiple times. In PyQt, to run code when a button is clicked you need to connect it to another function. In the createATab function, I have a QLineEdit which needs to be edited when a button is clicked. Here's an example of what I am trying to do:
class Example(QWidget, QWindow):
def __init__(self):
super().__init__()
self.initUI()
def runThisWhenButtonClicked(self):
getText = editThisLine.text()
editThisLine.clear() # edits variable in other function except other function is run multiple times
def addTheTab(self, username):
addingTab = QWidget()
aButton = QPushButton("Stuff")
editThisLine = QLineEdit()
aButton.clicked.connect(self.runThisWhenButtonClicked)
tabGrid = QGridLayout(addingTab)
tabGrid.addWidget(editThisLine, 3, 1, 4, 2)
tabGrid.addWidget(aButton, 3, 3, 4, 3)
tab_widget.addTab(addingTab, str(username))
def initUI(self):
global tab_widget
tab_widget = QTabWidget()
listwidget = QListWidget()
listwidget.itemDoubleClicked.connect(self.addTheTab)
splitterrr = QSplitter()
splitterrr.addWidget(listwidget)
splitterrr.addWidget(tab_widget)
QListWidgetItem("Test1", listwidget)
QListWidgetItem("Test2", listwidget)
mainLayout = QHBoxLayout()
mainLayout.addWidget(splitterrr)
self.setLayout(mainLayout)
self.setGeometry(300, 300, 300, 300)
self.setWindowTitle('Test')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
How do I pass a variable by reference?
I have read through this and although it does explain a lot, it doesn't explain how to solve this issue.
This explains how you are only passing the function, not calling it. So, passing variables to the runThisWhenButtonClicked function is not possible.
Upvotes: 1
Views: 1620
Reputation: 120638
The concept you are missing is closure. A closure wraps up a scope with a function, so that code in the function can access variables within that associated scope. The simplest way to utilise closures when connecting signals is with a lambda
(although some people prefer to use functools.partial).
In your example, this would mean connecting the signal like this:
aButton.clicked.connect(lambda: self.runThisWhenButtonClicked(editThisLine))
...
def runThisWhenButtonClicked(self, editThisLine):
print(editThisLine.text())
However, I think this may be "papering over the cracks" in your code, and is possibly not the best solution. A better solution would be to make proper use of the namespaces that classes provide. The addTheTab
and runThisWhenButtonClicked
should be refactored into a Tab
class which has all its child widgets as attributes:
class Tab(QWidget):
def __init__(self, parent=None):
super(Tab, self).__init__(parent)
self.editThisLine = QLineEdit()
self.aButton = QPushButton("Stuff")
self.aButton.clicked.connect(self.runThisWhenButtonClicked)
...
def runThisWhenButtonClicked(self):
print(self.editThisLine.text())
This would completely eliminate the need for closures in your example.
Upvotes: 1