在 QTableWidget 中将组合框添加到水平 header
Add combobox to horizontal header in QTableWidget
我想在 PyQt5 中创建一个 table,它在每列 header 中都有一个组合框。当我尝试这样做时,返回以下错误:
TypeError: setHorizontalHeaderItem(self, int, QTableWidgetItem): argument 2 has unexpected type 'QComboBox'
显然函数 setHorizontalHeaderItem()
不接受小部件作为项目。那么有没有办法实现这一目标?如果没有,我会解决将组合框 放在 上面 headers,但它们应该与每列的大小对齐,即使用户更改宽度老鼠。我也不知道这是否可行。
我的代码:
from PyQt5 import QtWidgets
import numpy as np
class App(QtWidgets.QWidget):
def __init__(self):
super(App,self).__init__()
self.data = np.random.rand(5,5)
self.createTable()
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.table)
self.setLayout(self.layout)
self.showMaximized()
def createTable(self):
self.header = []
self.table = QtWidgets.QTableWidget(len(self.data), len(self.data[0]))
for i in range(len(self.data[0])):
self.header.append(QtWidgets.QComboBox())
self.header[-1].addItem('Variable')
self.header[-1].addItem('Timestamp')
self.table.setHorizontalHeaderItem(i,self.header[-1])
for i in range(len(self.data)):
for j in range(len(self.data[0])):
self.table.setItem(i,j,QtWidgets.QTableWidgetItem(str(self.data[i][j])))
if __name__ == '__main__':
app = QtWidgets.QApplication([])
ex = App()
app.exec_()
QHeaderView
不支持小部件作为项目,因此您必须创建自定义 header,如下所示:
from PyQt5 import QtCore, QtWidgets
import numpy as np
class HorizontalHeader(QtWidgets.QHeaderView):
def __init__(self, values, parent=None):
super(HorizontalHeader, self).__init__(QtCore.Qt.Horizontal, parent)
self.setSectionsMovable(True)
self.comboboxes = []
self.sectionResized.connect(self.handleSectionResized)
self.sectionMoved.connect(self.handleSectionMoved)
def showEvent(self, event):
for i in range(self.count()):
if i < len(self.comboboxes):
combo = self.comboboxes[i]
combo.clear()
combo.addItems(["Variable", "Timestamp"])
else:
combo = QtWidgets.QComboBox(self)
combo.addItems(["Variable", "Timestamp"])
self.comboboxes.append(combo)
combo.setGeometry(self.sectionViewportPosition(i), 0, self.sectionSize(i)-4, self.height())
combo.show()
if len(self.comboboxes) > self.count():
for i in range(self.count(), len(self.comboboxes)):
self.comboboxes[i].deleteLater()
super(HorizontalHeader, self).showEvent(event)
def handleSectionResized(self, i):
for i in range(self.count()):
j = self.visualIndex(i)
logical = self.logicalIndex(j)
self.comboboxes[i].setGeometry(self.sectionViewportPosition(logical), 0, self.sectionSize(logical)-4, self.height())
def handleSectionMoved(self, i, oldVisualIndex, newVisualIndex):
for i in range(min(oldVisualIndex, newVisualIndex), self.count()):
logical = self.logicalIndex(i)
self.comboboxes[i].setGeometry(self.ectionViewportPosition(logical), 0, self.sectionSize(logical) - 5, height())
def fixComboPositions(self):
for i in range(self.count()):
self.comboboxes[i].setGeometry(self.sectionViewportPosition(i), 0, self.sectionSize(i) - 5, self.height())
class TableWidget(QtWidgets.QTableWidget):
def __init__(self, *args, **kwargs):
super(TableWidget, self).__init__(*args, **kwargs)
header = HorizontalHeader(self)
self.setHorizontalHeader(header)
def scrollContentsBy(self, dx, dy):
super(TableWidget, self).scrollContentsBy(dx, dy)
if dx != 0:
self.horizontalHeader().fixComboPositions()
class App(QtWidgets.QWidget):
def __init__(self):
super(App,self).__init__()
self.data = np.random.rand(10, 10)
self.createTable()
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.table)
self.showMaximized()
def createTable(self):
self.header = []
self.table = TableWidget(*self.data.shape)
for i, row_values in enumerate(self.data):
for j, value in enumerate(row_values):
self.table.setItem(i, j, QtWidgets.QTableWidgetItem(str(value)))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
我想在 PyQt5 中创建一个 table,它在每列 header 中都有一个组合框。当我尝试这样做时,返回以下错误:
TypeError: setHorizontalHeaderItem(self, int, QTableWidgetItem): argument 2 has unexpected type 'QComboBox'
显然函数 setHorizontalHeaderItem()
不接受小部件作为项目。那么有没有办法实现这一目标?如果没有,我会解决将组合框 放在 上面 headers,但它们应该与每列的大小对齐,即使用户更改宽度老鼠。我也不知道这是否可行。
我的代码:
from PyQt5 import QtWidgets
import numpy as np
class App(QtWidgets.QWidget):
def __init__(self):
super(App,self).__init__()
self.data = np.random.rand(5,5)
self.createTable()
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.table)
self.setLayout(self.layout)
self.showMaximized()
def createTable(self):
self.header = []
self.table = QtWidgets.QTableWidget(len(self.data), len(self.data[0]))
for i in range(len(self.data[0])):
self.header.append(QtWidgets.QComboBox())
self.header[-1].addItem('Variable')
self.header[-1].addItem('Timestamp')
self.table.setHorizontalHeaderItem(i,self.header[-1])
for i in range(len(self.data)):
for j in range(len(self.data[0])):
self.table.setItem(i,j,QtWidgets.QTableWidgetItem(str(self.data[i][j])))
if __name__ == '__main__':
app = QtWidgets.QApplication([])
ex = App()
app.exec_()
QHeaderView
不支持小部件作为项目,因此您必须创建自定义 header,如下所示:
from PyQt5 import QtCore, QtWidgets
import numpy as np
class HorizontalHeader(QtWidgets.QHeaderView):
def __init__(self, values, parent=None):
super(HorizontalHeader, self).__init__(QtCore.Qt.Horizontal, parent)
self.setSectionsMovable(True)
self.comboboxes = []
self.sectionResized.connect(self.handleSectionResized)
self.sectionMoved.connect(self.handleSectionMoved)
def showEvent(self, event):
for i in range(self.count()):
if i < len(self.comboboxes):
combo = self.comboboxes[i]
combo.clear()
combo.addItems(["Variable", "Timestamp"])
else:
combo = QtWidgets.QComboBox(self)
combo.addItems(["Variable", "Timestamp"])
self.comboboxes.append(combo)
combo.setGeometry(self.sectionViewportPosition(i), 0, self.sectionSize(i)-4, self.height())
combo.show()
if len(self.comboboxes) > self.count():
for i in range(self.count(), len(self.comboboxes)):
self.comboboxes[i].deleteLater()
super(HorizontalHeader, self).showEvent(event)
def handleSectionResized(self, i):
for i in range(self.count()):
j = self.visualIndex(i)
logical = self.logicalIndex(j)
self.comboboxes[i].setGeometry(self.sectionViewportPosition(logical), 0, self.sectionSize(logical)-4, self.height())
def handleSectionMoved(self, i, oldVisualIndex, newVisualIndex):
for i in range(min(oldVisualIndex, newVisualIndex), self.count()):
logical = self.logicalIndex(i)
self.comboboxes[i].setGeometry(self.ectionViewportPosition(logical), 0, self.sectionSize(logical) - 5, height())
def fixComboPositions(self):
for i in range(self.count()):
self.comboboxes[i].setGeometry(self.sectionViewportPosition(i), 0, self.sectionSize(i) - 5, self.height())
class TableWidget(QtWidgets.QTableWidget):
def __init__(self, *args, **kwargs):
super(TableWidget, self).__init__(*args, **kwargs)
header = HorizontalHeader(self)
self.setHorizontalHeader(header)
def scrollContentsBy(self, dx, dy):
super(TableWidget, self).scrollContentsBy(dx, dy)
if dx != 0:
self.horizontalHeader().fixComboPositions()
class App(QtWidgets.QWidget):
def __init__(self):
super(App,self).__init__()
self.data = np.random.rand(10, 10)
self.createTable()
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.table)
self.showMaximized()
def createTable(self):
self.header = []
self.table = TableWidget(*self.data.shape)
for i, row_values in enumerate(self.data):
for j, value in enumerate(row_values):
self.table.setItem(i, j, QtWidgets.QTableWidgetItem(str(value)))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())