I am trying to create a PyQt application that displays a push button and label inside each cell. When the button is pressed I need to be able to access its coordinates in the QTableWidget to act accordingly, so I am just printing the coordinates using the onClick() Signal below.
I found some related posts, but they were in C++ so it was difficult to understand:
- How to show the row where QPushButton is clicked in QTableWidget
- Catch button clicked in a Qtablewidget cell
I created a custom button class to store the row and column as properties when it is created. I think there is an issue with references vs instances when passing the CustomButton instance into the PyQt Signal (aka function) because when pressing the button only the last CustomButton instance is referenced no matter which button is pressed, but I can't figure it out. In my code below, it prints (2, 2) for all buttons pressed, despite printing the correct coords upon initial creation.
I'm still a Python novice at best, so I would appreciate any critiques even if they are not related to the problem at hand.
from PyQt6.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QHBoxLayout, QVBoxLayout, QHeaderView, QPushButton, QScrollArea, QLabel, QMainWindow
from PyQt6.QtCore import Qt, QSize
import sys
class CustomButton(QPushButton):
def __init__(self, text, row, col, parent=None):
super(QPushButton, self).__init__(parent, text=text)
self.row = row
self.col = col
def get_coords(self):
return (self.row, self.col)
class ButtonLabelWidget(QWidget):
def __init__(self, btn_name, label_name, row, col, parent=None):
super(ButtonLabelWidget, self).__init__(parent)
self.layout = QHBoxLayout()
# add button and label
self.btn = CustomButton(btn_name, row, col)
self.btn.setMaximumSize(45,24)
self.btn.setMinimumSize(45,24)
self.layout.addWidget(self.btn)
self.layout.addWidget(QLabel(label_name))
self.setLayout(self.layout)
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('Grid')
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.load_table()
self.show()
def load_table(self):
row, col = 3, 3
if not hasattr(self, 'table'):
self.table = QTableWidget()
self.layout.addWidget(self.table)
self.table.setRowCount(row)
self.table.setColumnCount(col)
for r in range(row):
for c in range(col):
cell_widget = ButtonLabelWidget('Click', f'({r},{c})', c, r, parent=self)
print(f'isinstance ButtonLabelWidget = {isinstance(cell_widget, ButtonLabelWidget)}')
print(f'isinstance btn = {isinstance(cell_widget.btn, CustomButton)}')
print(f'coords = {cell_widget.btn.get_coords()}')
cell_widget.btn.clicked.connect(lambda: self.onClick(cell_widget.btn))
self.table.setCellWidget(r, c, cell_widget)
def onClick(self, btn):
print(btn.get_coords())
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())