python - 如何复制一行 QtableWidget 并插入到它下面的行?
问题描述
我想要一个表格,其中每一行在 QtableWidget 的第一个单元格中都有一个按钮,并且在按下该按钮时,整行会与前一行的所有条目(包括按钮和组合框)重复。
我尝试复制它们的文本并且它成功但它没有达到目的,因为它再次需要手动将其分配给组合框等。下面的尝试,只需在每次单击时插入一个空白行。行如何与其元素完全复制?
试图
from PyQt5 import QtCore, QtGui, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.m_tablewidget = QtWidgets.QTableWidget(0, 3)
self.m_tablewidget.setHorizontalHeaderLabels(
["Col 1", "Col 2", "Col 3"]
)
self.m_button = QtWidgets.QPushButton("Add Row", clicked=self.onClicked)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QVBoxLayout(central_widget)
lay.addWidget(self.m_tablewidget)
lay.addWidget(self.m_button, alignment=QtCore.Qt.AlignLeft)
def table_selector(self, tableName):
variableSelected = []
for r in range(tableName.rowCount()):
row_variables = []
for c in range(tableName.columnCount()):
widget = tableName.cellWidget(r, c)
if isinstance(widget, QtWidgets.QComboBox):
current_value = widget.currentText()
row_variables.append(current_value)
variableSelected.append(row_variables)
return variableSelected
@QtCore.pyqtSlot()
def addRow(self):
rc = self.m_tablewidget.rowCount()
self.m_tablewidget.insertRow(rc)
@QtCore.pyqtSlot()
def onClicked(self):
d = {
"a": ["x", "y", "z"],
"b": ["4", "5", "6"],
"c": ["21", "22", "23"],
}
combobox = QtWidgets.QComboBox()
for k, v in d.items():
combobox.addItem(k, v)
item = QtWidgets.QTableWidgetItem()
copyROw_button = QtWidgets.QPushButton("ADD ROW", clicked=self.addRow)
rc = self.m_tablewidget.rowCount()
self.m_tablewidget.insertRow(rc)
for i, combo in enumerate((copyROw_button, combobox)):
self.m_tablewidget.setCellWidget(rc, i, combo)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
解决方案
在您的情况下,复制行涉及复制小部件。根据我的经验,我得出的结论是您不能复制小部件(Qt 也不允许这样做),因此您必须复制小部件的更多相关功能 (1) ,而不是复制小部件。
首先是确定使一行与另一行不同的特征,在您的情况下,我已经确定:
- QComboBox 显示的数据
- QComboBox 的选定索引。
- 第三列的文本
具有您的逻辑的其他元素不会更改(例如,您的应用程序不允许修改按钮的文本)。
由于我们确定了区分行的特征,因此这些参数必须是创建行的函数所采用的参数。
(1) 这点是主观的
考虑到上述情况,解决方案如下:
from PyQt5 import QtCore, QtGui, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.m_tablewidget = QtWidgets.QTableWidget(0, 3)
self.m_tablewidget.setHorizontalHeaderLabels(
["Col 1", "Col 2", "Col 3"]
)
self.m_button = QtWidgets.QPushButton("Add Row", clicked=self.onClicked)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QVBoxLayout(central_widget)
lay.addWidget(self.m_tablewidget)
lay.addWidget(self.m_button, alignment=QtCore.Qt.AlignLeft)
@QtCore.pyqtSlot()
def addRow(self):
button = self.sender()
if not isinstance(button, QtWidgets.QPushButton):
return
p = button.mapTo(self.m_tablewidget.viewport(), QtCore.QPoint())
ix = self.m_tablewidget.indexAt(p)
if not ix.isValid() or ix.column() != 0:
return
r = ix.row()
ix_combobox = 0
text = ""
combo = self.m_tablewidget.cellWidget(r, 1)
if isinstance(combo, QtWidgets.QComboBox):
ix_combobox = combo.currentIndex()
item = self.m_tablewidget.item(r, 2)
if item is not None:
text = item.text()
self.insert_row(row=r + 1, ix_combobox=ix_combobox, text=text)
@QtCore.pyqtSlot()
def onClicked(self):
self.insert_row()
def insert_row(self, d=None, ix_combobox=0, text="", row=-1):
if d is None:
d = {
"a": ["x", "y", "z"],
"b": ["4", "5", "6"],
"c": ["21", "22", "23"],
}
combobox = QtWidgets.QComboBox()
for k, v in d.items():
combobox.addItem(k, v)
combobox.setCurrentIndex(ix_combobox)
item = QtWidgets.QTableWidgetItem()
copyROw_button = QtWidgets.QPushButton("ADD ROW", clicked=self.addRow)
if row == -1:
row = self.m_tablewidget.rowCount()
self.m_tablewidget.insertRow(row)
for i, combo in enumerate((copyROw_button, combobox)):
self.m_tablewidget.setCellWidget(row, i, combo)
if text:
self.m_tablewidget.setItem(row, 2, QtWidgets.QTableWidgetItem(text))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
推荐阅读
- ios - 如何在 Azure Pipeline 中为 iOS 版本使用自动预配
- python - 没有前缀的 URL
- javascript - Selenium 是否支持使用不同配置文件运行的多个浏览器窗口?
- php - Woocommerce:向 BACS 帐户详细信息页面添加自定义字段
- r - 模糊左连接精确+部分字符串匹配
- python - 每日历史平均阈值
- r - 在 r 中创建汇总表(降价)
- pine-script - 如何获得最高/最低蜡烛的收盘价?
- ios - 通过 Storyboard 创建时如何学习 Swift 命令?
- javascript - Javascript getFullYear 返回错误的年份