Issue
I have a central widget(self.widget) and inside it a QHBoxLayout(self.box)
And I have placed three buttons inside this layout
What I want is to print the button index by clicking on each button
For example, when I click on button 3, the index of this button will be printed
But when I click on one of the buttons, none is returned for me
and index -1 is returned
Because the button becomes none, it naturally gets the wrong index
Note that I know that I can find the clicked button in other ways
But I want to find the clicked button using self.widget.childAt(e.pos())
Where is the problem?
code:
from PyQt6.QtWidgets import *
from PyQt6.QtCore import *
from PyQt6.QtGui import *
class CustomPushButton(QPushButton):
signal = pyqtSignal(QEvent)
def __init__(self, name):
super().__init__(name)
def mousePressEvent(self, event):
self.signal.emit(event)
class main(QMainWindow):
def __init__(self):
super().__init__()
self.box = QHBoxLayout()
self.widget = QWidget()
self.widget.setLayout(self.box)
self.button = CustomPushButton('button1')
self.button2 = CustomPushButton('button2')
self.button3 = CustomPushButton('button3')
self.box.addWidget(self.button)
self.box.addWidget(self.button2)
self.box.addWidget(self.button3)
self.button.signal.connect(self.findIndex)
self.button2.signal.connect(self.findIndex)
self.button3.signal.connect(self.findIndex)
self.setCentralWidget(self.widget)
self.show()
def findIndex(self,e):
button = self.widget.childAt(e.pos())
print(button)
print('button',self.box.indexOf(button))
app = QApplication([])
m = main()
m.show()
app.exec()
Solution
Each widget has it's own local coordinate system, and the QMouseEvent.pos()
method returns a QPoint
in that widgets local coordinate system. However the QWidget.childAt()
method expects the parameter to be in it's own coordinate system.
So when you send the event generated by the button and then apply its position to the parent widgets coordinate system, it is unlikely that the button will be found at those coordinates.
What you can do instead is map the coordinates to the buttons parent using the mapToParent
method, prior to emitting the signal, and sending the QPoint
result for the mapped position as the signal parameter.
For example:
from PyQt6.QtWidgets import *
from PyQt6.QtCore import *
from PyQt6.QtGui import *
class CustomPushButton(QPushButton):
signal = pyqtSignal(QPoint)
def __init__(self, name):
super().__init__(name)
def mousePressEvent(self, event):
self.signal.emit(self.mapToParent(event.pos()))
class main(QMainWindow):
def __init__(self):
super().__init__()
self.box = QHBoxLayout()
self.widget = QWidget()
self.widget.setLayout(self.box)
self.button = CustomPushButton('button1')
self.button2 = CustomPushButton('button2')
self.button3 = CustomPushButton('button3')
self.box.addWidget(self.button)
self.box.addWidget(self.button2)
self.box.addWidget(self.button3)
self.button.signal.connect(self.findIndex)
self.button2.signal.connect(self.findIndex)
self.button3.signal.connect(self.findIndex)
self.setCentralWidget(self.widget)
def findIndex(self,e):
button = self.widget.childAt(e)
print(button)
print('button',self.box.indexOf(button))
app = QApplication([])
m = main()
m.show()
app.exec()
After applying the above changes, after pushing each button the terminal output looks like:
<__main__.CustomPushButton object at 0x000001FEFF4CA440>
button 0
<__main__.CustomPushButton object at 0x000001FEFF4CA4D0>
button 1
<__main__.CustomPushButton object at 0x000001FEFF4CA560>
button 2
P.S. You are also calling show()
twice. once inside the constructor and again in afterwards toward the bottom, which is unnecessary.
Answered By - Alexander
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.