drmacro
31st August 2017, 18:37
I'm using a delegate to display the data in a table.
The goal is to display an indicator with some text.
And that part works. But, I can't seem to figure out how to get the column width to resize to fit the painted cell width. (If I expand the width of the column, the complete string is there)
It appears that it is sizing the columns based on the with of the header data, not the cell data.
(I've "translated" this from an example in C++, and between my level of QT expertise and the translating...I probably have missed something obvious. :p )
The main window starts:
class TDDlg(QtWidgets.QMainWindow):
#CueFileUpdate_sig = pyqtSignal()
def __init__(self, parent=None):
super(TDDlg, self).__init__(parent)
self.setupUi(self)
self.tableheader_horz = self.get_header_horz()
self.tableheader_vert = []
#self.tableView.doubleClicked.connect(self.on_tabl e_dblclick)
#self.tableView.clicked.connect(self.on_table_clic k)
self.tabledata = []
self.get_table_data()
self.leveldata = []
self.get_level_data()
self.tablemodel = MyTableModel(self.tabledata, self.leveldata, self.tableheader_horz, self.tableheader_vert, self)
self.tableView.setModel(self.tablemodel)
#self.tableView.setItemDelegateForColumn(3, CellDelegate())
self.tableView.setItemDelegate(CellDelegate())
self.tableView.setSelectionMode(QAbstractItemView. SingleSelection)
self.tableView.setSelectionBehavior(QAbstractItemV iew.SelectItems)
self.tableView.resizeColumnsToContents()
i = self.tableView.model().index(0, 0)
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.tableView = QtWidgets.QTableView(self.centralwidget)
self.tableView.setObjectName("tableView")
self.gridLayout.addWidget(self.tableView, 0, 0, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 28))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.toolBar = QtWidgets.QToolBar(MainWindow)
self.toolBar.setObjectName("toolBar")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
And the model and the delegate:
class MyTableModel(QtCore.QAbstractTableModel):
def __init__(self, datain, leveldata, headerdata_horz, headerdata_vert, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent)
self.arraydata = datain
self.leveldata = leveldata
self.headerdata_horz = headerdata_horz
self.headerdata_vert = headerdata_vert
def rowCount(self, parent):
if parent.isValid():
return 0
return len(self.arraydata)
def columnCount(self, parent):
if parent.isValid():
return 0
else:
if self.arraydata:
return len(self.arraydata[0])
else:
return 0
def data(self, index, role): # Return data from the model
if not index.isValid():
logging.info('Invalid index in MyModel>data')
retval = QtCore.QVariant()
elif role == QtCore.Qt.BackgroundRole:
cell_contents = self.arraydata[index.row()][index.column()]
if cell_contents[-1] == '0':
retval = QtCore.QVariant()
else:
retval = QBrush(Qt.red)
elif role == QtCore.Qt.DisplayRole:
retval = QtCore.QVariant(self.arraydata[index.row()][index.column()])
else:
retval = QtCore.QVariant()
return retval
def setData(self, index, value, role): # Set data in the model
if role == QtCore.Qt.EditRole and index.isValid():
print(index.row())
self.arraydata[index.row()][index.column()] = value
print('Return from rowCount: {0}'.format(self.rowCount(index)))
self.dataChanged.emit(index, index, [QtCore.Qt.DisplayRole])
return True
return False
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
if col < len(self.headerdata_horz):
return QtCore.QVariant(self.headerdata_horz[col])
else:
return QtCore.QVariant('')
elif orientation == QtCore.Qt.Vertical and role == QtCore.Qt.DisplayRole:
if col < len(self.headerdata_vert):
return QtCore.QVariant(self.headerdata_vert[col])
else:
return QtCore.QVariant('')
return QtCore.QVariant()
class CellDelegate(QStyledItemDelegate):
def __init__(self):
QStyledItemDelegate.__init__(self)
self.diameter = 10
def paint(self, painter, item, modelindex): #QStyleOptionViewItem
diameter = min(item.rect.width(),item.rect.height())
self.diameter = diameter
adjustedRect = copy.copy(item.rect)
adjustedRect.setWidth(diameter)
adjustedRect.setHeight(diameter)
adjustedRect = adjustedRect.adjusted(5,5,-5,-5)
shade = 120
background = QColor(shade, shade, 128)
painter.setPen(background)
painter.setBrush(background)
painter.drawEllipse(adjustedRect)
val = modelindex.data()
level = '>' + val.split(':')[0] + ':' + str(int_to_db(int(val.split(':')[1])))
painter.setPen(Qt.red)
painter.drawText(item.rect.adjusted(round(diameter * 1.1),0,0,0),
QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter,
level)
return
The goal is to display an indicator with some text.
And that part works. But, I can't seem to figure out how to get the column width to resize to fit the painted cell width. (If I expand the width of the column, the complete string is there)
It appears that it is sizing the columns based on the with of the header data, not the cell data.
(I've "translated" this from an example in C++, and between my level of QT expertise and the translating...I probably have missed something obvious. :p )
The main window starts:
class TDDlg(QtWidgets.QMainWindow):
#CueFileUpdate_sig = pyqtSignal()
def __init__(self, parent=None):
super(TDDlg, self).__init__(parent)
self.setupUi(self)
self.tableheader_horz = self.get_header_horz()
self.tableheader_vert = []
#self.tableView.doubleClicked.connect(self.on_tabl e_dblclick)
#self.tableView.clicked.connect(self.on_table_clic k)
self.tabledata = []
self.get_table_data()
self.leveldata = []
self.get_level_data()
self.tablemodel = MyTableModel(self.tabledata, self.leveldata, self.tableheader_horz, self.tableheader_vert, self)
self.tableView.setModel(self.tablemodel)
#self.tableView.setItemDelegateForColumn(3, CellDelegate())
self.tableView.setItemDelegate(CellDelegate())
self.tableView.setSelectionMode(QAbstractItemView. SingleSelection)
self.tableView.setSelectionBehavior(QAbstractItemV iew.SelectItems)
self.tableView.resizeColumnsToContents()
i = self.tableView.model().index(0, 0)
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.tableView = QtWidgets.QTableView(self.centralwidget)
self.tableView.setObjectName("tableView")
self.gridLayout.addWidget(self.tableView, 0, 0, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 28))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.toolBar = QtWidgets.QToolBar(MainWindow)
self.toolBar.setObjectName("toolBar")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
And the model and the delegate:
class MyTableModel(QtCore.QAbstractTableModel):
def __init__(self, datain, leveldata, headerdata_horz, headerdata_vert, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent)
self.arraydata = datain
self.leveldata = leveldata
self.headerdata_horz = headerdata_horz
self.headerdata_vert = headerdata_vert
def rowCount(self, parent):
if parent.isValid():
return 0
return len(self.arraydata)
def columnCount(self, parent):
if parent.isValid():
return 0
else:
if self.arraydata:
return len(self.arraydata[0])
else:
return 0
def data(self, index, role): # Return data from the model
if not index.isValid():
logging.info('Invalid index in MyModel>data')
retval = QtCore.QVariant()
elif role == QtCore.Qt.BackgroundRole:
cell_contents = self.arraydata[index.row()][index.column()]
if cell_contents[-1] == '0':
retval = QtCore.QVariant()
else:
retval = QBrush(Qt.red)
elif role == QtCore.Qt.DisplayRole:
retval = QtCore.QVariant(self.arraydata[index.row()][index.column()])
else:
retval = QtCore.QVariant()
return retval
def setData(self, index, value, role): # Set data in the model
if role == QtCore.Qt.EditRole and index.isValid():
print(index.row())
self.arraydata[index.row()][index.column()] = value
print('Return from rowCount: {0}'.format(self.rowCount(index)))
self.dataChanged.emit(index, index, [QtCore.Qt.DisplayRole])
return True
return False
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
if col < len(self.headerdata_horz):
return QtCore.QVariant(self.headerdata_horz[col])
else:
return QtCore.QVariant('')
elif orientation == QtCore.Qt.Vertical and role == QtCore.Qt.DisplayRole:
if col < len(self.headerdata_vert):
return QtCore.QVariant(self.headerdata_vert[col])
else:
return QtCore.QVariant('')
return QtCore.QVariant()
class CellDelegate(QStyledItemDelegate):
def __init__(self):
QStyledItemDelegate.__init__(self)
self.diameter = 10
def paint(self, painter, item, modelindex): #QStyleOptionViewItem
diameter = min(item.rect.width(),item.rect.height())
self.diameter = diameter
adjustedRect = copy.copy(item.rect)
adjustedRect.setWidth(diameter)
adjustedRect.setHeight(diameter)
adjustedRect = adjustedRect.adjusted(5,5,-5,-5)
shade = 120
background = QColor(shade, shade, 128)
painter.setPen(background)
painter.setBrush(background)
painter.drawEllipse(adjustedRect)
val = modelindex.data()
level = '>' + val.split(':')[0] + ':' + str(int_to_db(int(val.split(':')[1])))
painter.setPen(Qt.red)
painter.drawText(item.rect.adjusted(round(diameter * 1.1),0,0,0),
QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter,
level)
return