简体   繁体   中英

QTableWidget: Insert row crashes the application python

I have created a table and I want the row should be created based on click on one button. I created a table and I didn't assign rowcount. When I run program, it shows table without any row (shows header label etc). So far everything is fine. I put a button to add a row and wrote following code:

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

The application simply exits.

If I try:

self.tableWidget.setRowCount(count+1)

it adds row. Suppose I entered some data in rows and again call

self.tableWidget.setRowCount(count+1)

it deletes data of one row.

My question is:

Can we use InsertRow without setting setRowCount?

When I call setRowCount multiple time, why does it delete data filled in rows (using UI)?

I could implement something simpler to show exactly just what you are asking for, but I just implemented something similar to what you need, I needed to do what you need to get data from a table and fill out my QLineChart.

In summary you have to override all the required methods a QAbstractItemModel requires according to your needs.

Have this small example that I add a line to the and of my table when clicking in a button:

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()

and in the widget or whatever you have your buttons just connect your button clicking to the insert and remove line methods from your item model above.

#...
    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)
#...

Now you just gotta set the model from your tableview to the model you overwrote.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM