For my text editor I'm trying to implement a QMenu
to quickly create a table with a size of up to 10 columns and 8 rows (lines). It looks and works similar to what you have in Word or Google Docs like this:
(https://i.stack.imgur.com/IxbPf.png)
In my application it looks like this: (https://i.stack.imgur.com/ciH7o.png)
You have a QGridLayout
of 10x8 buttons. If you hover over a button its background colour and the button colour of all buttons with a lower column and row number will change their background colour to indicate the size of the table.
I use an enterEvent
to emit a signal to the parent QWidgetAction
with the grid coordinates, and every button that has the same or lower coordinates that the hovered button's coordinates have the property, "hovered" changed. In the corresponding stylesheet this property should change the background colour but that doesn't happen.
I've looked over the code several times but I really can't see the problem why the buttons' background colour doesn't change so I would appreciate if someone has an answer.
Here is the code of the QMenu
, the QWidgetAction
with the button grid and the special QPushButton
"GridButton":
class TableMenu(QtWidgets.QMenu):
tableSize = QtCore.pyqtSignal(int, int)
def __init__(self, parent=None) -> None:
super().__init__(parent)
self.setUI()
def setUI(self) -> None:
self.AC_TableGrid = TableGrid(self)
self.AC_TableGrid.tableSize.connect(self.emitTableSize)
self.addAction(self.AC_TableGrid)
@QtCore.pyqtSlot(int, int)
def emitTableSize(self, line: int, column: int) -> None:
self.tableSize.emit(line, column)
class TableGrid(QtWidgets.QWidgetAction):
tableSize = QtCore.pyqtSignal(int, int)
def __init__(self, parent=None) -> None:
super().__init__(parent)
self.setUI()
def setUI(self) -> None:
self.Grid = QtWidgets.QWidget()
self.ButtonLayout = QtWidgets.QGridLayout(self.Grid)
self.ButtonLayout.setHorizontalSpacing(2)
self.ButtonLayout.setVerticalSpacing(2)
for iline in range(8):
for icolumn in range(10):
button = GridButton()
button.line = iline+1
button.column = icolumn+1
button.entered.connect(self.setMarkedButtons)
button.sizeSet.connect(self.getTableSize)
self.ButtonLayout.addWidget(button, iline, icolumn)
self.Grid.setLayout(self.ButtonLayout)
self.setDefaultWidget(self.Grid)
@QtCore.pyqtSlot(int, int)
def setMarkedButtons(self, line: int, column: int) -> None:
for i in range(self.ButtonLayout.count()):
button = self.ButtonLayout.itemAt(i).widget()
if button.column <= column and button.line <= line:
print(button, button.line, button.column)
if button.property("hovered"):
button.setProperty("hovered", False)
else:
button.setProperty("hovered", True)
else:
button.setProperty("hovered", False)
button.style().polish(button)
@QtCore.pyqtSlot(int, int)
def getTableSize(self, line: int, column: int) -> None:
self.tableSize.emit(line, column)
class GridButton(QtWidgets.QPushButton):
entered = QtCore.pyqtSignal(int, int)
sizeSet = QtCore.pyqtSignal(int, int)
def __init__(self, parent=None) -> None:
super().__init__(parent)
self.setStyleSheet(fromStyle("GridButton")) # A convenient function to quickly load a stylesheet.
self.setProperty("hovered", False)
self.setFixedSize(15, 15)
self.connectSignals()
self.line: int
self.column: int
def connectSignals(self) -> None:
self.clicked.connect(self.emitCoordinates)
def emitCoordinates(self) -> None:
self.sizeSet.emit(self.line, self.column)
def enterEvent(self, event: QtGui.QEnterEvent) -> None:
self.entered.emit(self.line, self.column)
print("Entered!")
return super().enterEvent(event)
def leaveEvent(self, a0: QtCore.QEvent) -> None:
# This is the property to change the background colour
self.setProperty("hovered", False)
self.style().polish(self)
return super().leaveEvent(a0)
Here is the stylesheet "GridButton.qss":
QPushButton {
background-color: white;
border: 1px solid black;
border-radius: 4px;
}
QPushButton [hovered='true'] {
background-color: #75b4ec;
}
I've also tried similar functions that update the appearance like unpolish()
or update()
but they didn't work either.
The convenient function I created myself, fromStyle()
, also works perfectly fine. I checked it. So this should not be the problem.