【问题标题】:QTableWidget: Insert row crashes the application pythonQTableWidget:插入行使应用程序python崩溃
【发布时间】:2017-05-11 22:59:20
【问题描述】:

我创建了一个表,我希望通过单击一个按钮来创建行。我创建了一个表,但没有分配行数。当我运行程序时,它显示没有任何行的表格(显示标题标签等)。到目前为止一切都很好。我放了一个按钮来添加一行并写了以下代码:

self.tableWidget.InsertRow(self.tableWidget.rowCount()+1)

应用程序直接退出。

如果我尝试:

self.tableWidget.setRowCount(count+1)

它增加了行。假设我在行中输入了一些数据并再次调用

self.tableWidget.setRowCount(count+1)

删除一行数据。

我的问题是:

我们可以在不设置 setRowCount 的情况下使用 InsertRow 吗?

当我多次调用 setRowCount 时,为什么它会删除行中填充的数据(使用 UI)?

【问题讨论】:

  • setRowCountcount 调用。每次都是一样的值吗?
  • 应该是insertRow,小写i
  • @DavidChing 感谢 cmets。每次通话时计数都会增加。当我运行程序时,它会添加行。假设创建了 3 行并且用户在行中输入了数据。现在用户想要再添加一行和数据。调用 setRowCount 时,会添加一个空白行,但会删除现有行的数据:-( .
  • 我尝试使用小写 i 但它没有添加任何行
  • 你用这个神秘的count 调用 setRowCount。它设置成什么?

标签: python pyqt qtablewidget


【解决方案1】:

我可以实现一些更简单的东西来准确显示您的要求,但我只是实现了类似于您需要的东西,我需要做您需要做的事情,从表格中获取数据并填写我的 QLineChart。

总之,您必须根据您的需要覆盖 QAbstractItemModel 所需的所有必需方法。

有一个小例子,我在点击按钮时在表格的 and 中添加了一行:

import random

from PyQt5.QtCore import QAbstractItemModel
from PyQt5.QtCore import QModelIndex
from PyQt5.QtCore import QRect
from PyQt5.QtCore import QVariant
from PyQt5.QtCore import Qt
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QColor


class ItemModelLineChart(QAbstractItemModel):

    signal_update_models = pyqtSignal()

    def __init__(self):
        super(ItemModelLineChart, self).__init__()
        self.m_column_count = 2
        self.m_row_count = 0
        self.m_mapping = {}
        self.m_data = []
        # self.fill_with_random_data()

    def fill_with_random_data(self):
        print(self.m_row_count)
        for r in range(self.m_row_count):
            data_vec = [None] * self.m_column_count
            for c in range(len(data_vec)):
                if (c%2)==0:
                    data_vec[c] = r*50+random.randint(0,100)%20
                else:
                    data_vec[c] = random.randint(0, 100) % 20
            self.m_data.append(data_vec)

    def rowCount(self, parent=None, *args, **kwargs):
        return len(self.m_data)

    def columnCount(self, parent=None, *args, **kwargs):
        return self.m_column_count

    def headerData(self, section, orientation, role=None):
        if role == Qt.DisplayRole:
            return QVariant()
        if orientation == Qt.Horizontal:
            if section%2==0:
                return "x"
            else:
                return "y"
        else:
            return "{}".format(section+1)

    def data(self, index, role=None):
        if role == Qt.DisplayRole:
            return self.m_data[index.row()][index.column()]
        elif role == Qt.EditRole:
            return self.m_data[index.row()][index.column()]
        elif role == Qt.BackgroundRole:
            for color, rect in self.m_mapping.items():
                if rect.contains(index.column(), index.row()):
                    return QColor(color)
        return QVariant()

    def setData(self, index, value, role=None):
        if index.isValid() and role == Qt.EditRole:
            self.m_data[index.row()][index.column()] = int(value)
            self.dataChanged.emit(index,index)
            self.signal_update_models.emit()
            return True
        return False

    def get_data(self, index):
        return self.m_data[index.row()][index.column()]

    def add_mapping(self, color, area):
        self.color = color
        self.area = area
        self.m_mapping[color] = area

    def flags(self, index):
        return Qt.ItemIsEditable | Qt.ItemIsEnabled
        # if (index.column() == 0):
        #     return Qt.ItemIsEditable | Qt.ItemIsEnabled
        # else:
        #     return Qt.ItemIsEnabled

    def index(self, row, column, parent=None, *args, **kwargs):
        if self.hasIndex(row,column,parent):
            return self.createIndex(row,column,self.m_data[row])
        return QModelIndex()

    def parent(self, index=None):
        return QModelIndex()

    def insertRows(self):
        self.beginInsertRows(QModelIndex(), self.m_row_count, self.m_row_count)

        self.m_data.append([0,0])
        self.m_row_count += 1
        self.add_mapping(self.color, QRect(0, 0, 2, self.rowCount()))
        self.endInsertRows()
        return True

    def removeRows(self):
        self.beginRemoveRows(QModelIndex(), self.m_row_count, self.m_row_count)
        self.m_data.pop()
        self.m_row_count -= 1
        self.endRemoveRows()

        return True

    def add_row(self):
        self.insertRows()

    def remove_row(self):
        if self.m_row_count>0:
            self.m_row_count -= 1
            self.removeRows()

在小部件或任何你有你的按钮的地方,只需将你的按钮点击连接到上面的项目模型中的插入和删除线方法。

#...
    def create_connections(self):
        self.btn_add_line.clicked.connect(self.table.model().insertRows)
        self.btn_remove_line.clicked.connect(self.table.model().remove_row)
#...

现在您只需将模型从您的 tableview 设置为您覆盖的模型。

【讨论】:

  • 感谢您快速详细的回复。看起来你在我们使用数据模型的地方使用了 QTableView。我正在使用 QTableWidget,我需要创建模型吗?我想模型只用于查看。
  • @Manish 如果您选择 QTableWidget,您不需要拥有自己的模型。它已经更加健壮并且有许多自己的功能可以用来做你需要的事情,否则如果你关心内存并且不想浪费它,我建议你将 QTableView 与你自己的个性化 QAbstractItemModel 一起使用。总而言之,QTableWidget 是一个 QTableView,其中很多东西已经在底层实现了。 ")
  • QTableView 与 QTableWidget 如此不同,我认为需要一个显示 QTableWidget 的新示例。
猜你喜欢
  • 2019-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多