Reputation: 81
I have what I hope to be a simple question. I would like to have a table, where upon clicking a cell its background gets colored, and upon clicking again - uncolored (back to white). The idea identical to a checkbox, but I don't want a checkbox in my cell (unless it takes up the space of the entire cell and colors itself instead of checking). I'm stuck on how to check the color of a cell's background? If I wanted another cell to get the same color for example, I thought of taking the background color from the colored cell and just use it to another cell. I'm stuck. I've tried color(), brushStyle() and maybe more (possibly incorrectly). I'm sure it's an easy one for you guys :)
EDIT Sure, sorry. I mean a QTableWidget, like so:
table = QtGui.QTableWidget()
table.setRowCount(3)
table.setColumnCount(3)
I would like to get, say, the color of the first cell. I tried using:
table.setItem(0, 0, QtGui.QTableWidgetItem())
bg = table.item(0, 0).background().color()
print ("R: " + str(bg.red()) + "; G: " + str(bg.green()) + " ; B: " + str(bg.blue()))
I was expecting to get 255 on all RGB values, since I believe the default background to be white. Is the default color white or is there NO color by default? I get all zeros with this code. I just want to be able to make a statement:
if (cell is colored)
set cell background to white (default)
else
set color to cell background
EDIT 2: Okay so, I managed to create a solution of my own. Posting it here for anybody in need, although I believe the solution to be not great and possibly not working for other uses than mine.
def clickTable(row, column):
if table.item(row, column) == None:
item1 = QtGui.QTableWidgetItem()
item1.setBackground(QtGui.QColor(100,100,150))
table.setItem(row, column ,item1)
else:
table.takeItem(row, column)
The code responds to:
table.cellClicked.connect(clickTable)
I'm aware that takeItem might make this code useless for most people, but worked for me.
Upvotes: 1
Views: 2636
Reputation: 37569
For changing colors of background and text in individual cells, I've always had to use QItemDelegates
, as the normal methods of palettes and stylesheets don't seem to provide methods to style individual cells.
Essentially, you can define custom data roles (ItemBackgroundColorRole
in this case) and set data for these custom roles on items in your table widget. The QItemDelegate
is responsible for painting your table widget, and we can override the paint
method to check for these custom data roles and change the colors that the painter uses.
class MyDelegate(QItemDelegate):
ItemBackgroundColorRole = Qt.UserRole + 1
def __init__(self, parent, table):
super(MyDelegate, self).__init__(parent)
self.table = table
def paint(self, painter, option, index):
painter.save()
item = self.table.itemFromIndex(index)
if item:
bg_color = item.data(MyDelegate.ItemBackgroundColorRole)
if bg_color:
# These two roles (Window, Base) both style different aspects of the "background"
# Try with one or both to see which works for you
option.palette.setColor(QPalette.Window, bg_color)
option.palette.setColor(QPalette.Base, bg_color)
super(MyDelegate, self).paint(painter, option, index)
painter.restore()
table = QtGui.QTableWidget()
delegate = MyDelegate(None, table)
table.setItemDelegate(delegate)
item = QTableWidgetItem()
item.setData(MyDelegate.ItemBackgroundColorRole, QColor(Qt.red))
# To clear the color and go back to default
item.setData(MyDelegate.ItemBackgroundColorRole, None)
To trigger this on cell click, connect to the QTableWidget cellClicked
signal.
table.cellClicked.connect(handle_click)
def handle_click(row, column):
item = table.item(row, column)
bg_color = item.data(MyDelegate.ItemBackgroundColorRole)
color = None if bg_color else QColor(Qt.red)
item.setData(MyDelegate.ItemBackgroundColorRole, color)
Upvotes: 2