This question already has answers here:
Python: Pass extra arguments to callable
(2 answers)
Closed 1 year ago.
I am overriding the QWidget.mousePressEvent like this:
widget = QtWidgets.QWidget()
widget.mousePressEvent = my_function
def my_function(QMouseEvent):
print('Mouse Pressed')
But my question is, how do I now pass it a variable? I need something like this:
for index in range(10):
widget = QtWidgets.QWidget()
widget.mousePressEvent = my_function(index)
def my_function(QMouseEvent, index):
print(index)
Use functools.partial
from functools import partial
def my_function(index, QMouseEvent):
print(index)
for index in range(10):
widget = QtWidgets.QWidget()
widget.mousePressEvent = partial(my_function, index)
Or use lambda
widget.mousePressEvent = lambda: event, index=index: my_function(index, event)
Notice that optional lambda argument used for capturing index by value.
Related
This question already has answers here:
Return value from button click
(2 answers)
PySide: Returning a value from a slot
(3 answers)
Closed 1 year ago.
I cannot figure out, how I'm able to get variable (dictionary) out from the class.
When the button "ETSI" is clicked, the code will get all inputs from the GUI window (type fields and checkboxes) that the user provided and creates a dictionary out of that data.
The problem is that I cannot figure out how to return that dictionary, from the class.
CODE:
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5 import uic
import sys
class UI(QWidget):
def __init__(self):
super().__init__()
# --- Init window ------#
uic.loadUi("DesignerWindow/window.ui", self)
# --- Button action ------#
button = self.findChild(QPushButton, 'etsiButton')
# ---- Define action for the button ---#
button.clicked.connect(self.clicked_btn)
def clicked_btn(self):
resultList = {}
# Sijainti
sijaintiInput = self.sijaintiInput.text()
if sijaintiInput != "":
resultList ["sijainti"] = sijaintiInput
# Hinta
hintaInputMin = self.hintaInputMin.text()
if hintaInputMin != "":
resultList ["hintaMin"] = hintaInputMin
hintaInputMax = self.hintaInputMax.text()
if hintaInputMax != "":
resultList ["hintaMax"] = hintaInputMax
# Asuintilojen pinta-ala
atpInputMin = self.atpInputMin.text()
if atpInputMin != "":
resultList ["atpMin"] = atpInputMin
return resultList
# Execute
app = QApplication([])
window = UI()
window.show()
sys.exit(app.exec_())
This question already has answers here:
Creating PyQt5 buttons in a loop: all buttons trigger the same callback
(1 answer)
Connecting slots and signals in PyQt4 in a loop
(3 answers)
Closed 2 years ago.
class MainMenu(QWidget):
def __init__(self):
# QWiget constructor
super().__init__()
self.initUI()
def initUI(self):
self.buttons = (QPushButton('Uebergang'), QPushButton('Scherung'), QPushButton('Wippe'))
self.layout = QVBoxLayout()
for button in self.buttons:
self.layout.addWidget(button)
func = lambda : self.openMenu(button.text())
button.clicked.connect(func)
self.setLayout(self.layout)
self.show()
def openMenu(self, Menu):
print(Menu)
When I click on any of the three buttons it always prints "Wippe". I don't understand why. I know this question has been answered before but the answers didn't solve my problem.
I have all this labels declared in a initUi
They are constructed like that:
ligne_1_left_cord = 300
self.label_ligne_1_1 = QtWidgets.QLabel(self)
pic_signe_tab =QPixmap('img/tab.png')
self.label_ligne_1_1.setPixmap(pic_signe_tab)
self.label_ligne_1_1.move(ligne_1_left_cord,300)
self.label_ligne_1_1.mousePressEvent = self.label_click
self.label_ligne_1_2 = QtWidgets.QLabel(self)
self.label_ligne_1_2.setPixmap(pic_signe_tab)
self.label_ligne_1_2.move( ligne_1_left_cord +85,300)
When I click label_ligne_1_1 the function label_click does this:
def label_click(self,event):
signe_pixmap = QPixmap('img/tabx.png')
self.label_ligne_1_1.setPixmap(signe_pixmap)
Is there anyway I could pass a variable when I'm calling label_click in order to bind it to all labels and use the same function?
Something like this?:
def label_click(name_of_the_lable):
name_of_the_lable.setPixmap(x)
Meaning of course that no matter on what square you click, the pixmap will change and an X will appear
Overriding functions in that way is not suggested, especially for what are considered protected functions in Qt, which is the case of any *Event() function of QObjects and QWidgets.
Also, in your case you're just overwriting the method with the same signature, which would never allow you to get the source of the function call.
A possible solution would be to use a lambda with the source as a keyword argument:
self.label_ligne_1_1.mousePressEvent = lambda ev, label=self.label_ligne_1_1: self.label_click(label)
But I wouldn't suggest you to do that.
A better approach, instead, would be to install an event filter on each label, and then set the pixmap each time a mouse press event is captured:
class Squares(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QGridLayout(self)
layout.setSpacing(0)
for row in range(4):
for col in range(4):
square = QtWidgets.QLabel()
square.setPixmap(QtGui.QPixmap('tab.png'))
layout.addWidget(square, row, col)
setattr(self, 'label_ligne_{}_{}'.format(row + 1, col + 1), square)
square.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QtCore.QEvent.MouseButtonPress:
source.setPixmap(QtGui.QPixmap('tabx.png'))
return super().eventFilter(source, event)
This question already has answers here:
Lambda in a loop [duplicate]
(4 answers)
Connecting slots and signals in PyQt4 in a loop
(3 answers)
Using lambda expression to connect slots in pyqt
(4 answers)
Closed 3 years ago.
I want to create multiple buttons by a for loop.
Pressing on the buttons call same function but transfer a different parameters.
def someFunction(self):
buttons = [None] * 8
for i in range(8):
buttons[i] = QPushButton(self)
buttons[i].clicked.connect(self.function(i))
def function(self, i):
print(i)
I expect the output of buttons[i] to be i but the output always 7
Try it:
from PyQt5.QtWidgets import *
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.layout = QVBoxLayout(self)
self.someFunction()
def someFunction(self):
# buttons = [None] * 8
for i in range(8):
button = QPushButton("Button {}".format(i), self)
button.clicked.connect(lambda ch, i=i: self.function(i)) # < ---
self.layout.addWidget(button)
def function(self, i):
print(i)
if __name__ == '__main__':
app = QApplication([])
mainapp = MainWindow()
mainapp.show()
app.exec_()
This question already has answers here:
Creating functions (or lambdas) in a loop (or comprehension)
(6 answers)
Closed 6 months ago.
I'm trying to create a simple keyboard from list of QtGui.QPushButton objects.
class XKeyboard(QtGui.QWidget):
'''Special virtual keyboard for any language.'''
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.MainLayout = QtGui.QVBoxLayout()
self.TextEntry = QtGui.QTextEdit()
self.Keyboard = QtGui.QVBoxLayout()
self.MainLayout.addWidget(self.TextEntry)
self.MainLayout.addLayout(self.Keyboard)
self.setLayout(self.MainLayout)
def addRow(self, keys):
layout = QtGui.QHBoxLayout()
buttons = [QtGui.QPushButton(unicode(key)) for key in keys]
for button in buttons:
key = keys[buttons.index(button)]
layout.addWidget(button)
button.clicked.connect(
lambda key: self.keyClick(key))
self.keyClick(key)
self.Keyboard.addLayout(layout)
def keyClick(self, key):
self.TextEntry.insertPlainText(key)
The problem is that lambda returns False instead of key. What am I doing wrong?
That lambda :
lambda key: self.keyClick(key)
is equivalent to this:
def dummy(key):
self.keyClick(key)
So, basically you are accepting a parameter from clicked signal, which returns checked state of the button and it is False since you don't have a check-able button, and passing it to the keyClick method. keyClick method does not receive the key parameter in the for loop.
Possible solution would be writing your lambda accepting two parameters one with the default value of your intended value:
lambda checked, key=key: self.keyClick(key)
Why you need to do key=key is a whole different subject. This particular answer (along with the other answers) from a related subject might shed some light on it.
The right way to do this is to use a QButtonGroup, which is designed for precisely this situation.
Here's one way to re-write your example to use it:
class XKeyboard(QtGui.QWidget):
'''Special virtual keyboard for any language.'''
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.MainLayout = QtGui.QVBoxLayout()
self.TextEntry = QtGui.QTextEdit()
self.Keyboard = QtGui.QVBoxLayout()
self.MainLayout.addWidget(self.TextEntry)
self.MainLayout.addLayout(self.Keyboard)
self.setLayout(self.MainLayout)
self.buttonGroup = QtGui.QButtonGroup(self)
self.buttonGroup.buttonClicked[int].connect(self.keyClick)
def addRow(self, keys):
layout = QtGui.QHBoxLayout()
for key in keys:
key = unicode(key)
button = QtGui.QPushButton(key)
self.buttonGroup.addButton(button, ord(key))
layout.addWidget(button)
self.Keyboard.addLayout(layout)
def keyClick(self, key):
self.TextEntry.insertPlainText(unichr(key))