我是Qt编程的新手。我正在尝试创建一个可以通过单击按钮添加行的简单表。我可以很好地实现表,但似乎无法获得更新的数据显示在表上。我相信我的问题源于这样一个事实:我似乎无法使用按钮正确调用任何类型的“更改数据”方法。我已经尝试了几种不同的在线解决方案,所有这些都导致了4年前的死胡同。到目前为止我所拥有的是基本结构,我无法弄清楚如何使用新数据更新表。
这是基本视图
我已经设置了一些测试数据。
在最后的实现中,表将从空开始,我想追加行并将它们显示在表视图中。
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MyWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
# create table
self.get_table_data()
self.table = self.createTable()
# layout
self.layout = QVBoxLayout()
self.testButton = QPushButton("test")
self.connect(self.testButton, SIGNAL("released()"), self.test)
self.layout.addWidget(self.testButton)
self.layout.addWidget(self.table)
self.setLayout(self.layout)
def get_table_data(self):
self.tabledata = [[1234567890,2,3,4,5],
[6,7,8,9,10],
[11,12,13,14,15],
[16,17,18,19,20]]
def createTable(self):
# create the view
tv = QTableView()
# set the table model
header = ['col_0', 'col_1', 'col_2', 'col_3', 'col_4']
tablemodel = MyTableModel(self.tabledata, header, self)
tv.setModel(tablemodel)
# set the minimum size
tv.setMinimumSize(400, 300)
# hide grid
tv.setShowGrid(False)
# hide vertical header
vh = tv.verticalHeader()
vh.setVisible(False)
# set horizontal header properties
hh = tv.horizontalHeader()
hh.setStretchLastSection(True)
# set column width to fit contents
tv.resizeColumnsToContents()
# set row height
tv.resizeRowsToContents()
# enable sorting
tv.setSortingEnabled(False)
return tv
def test(self):
self.tabledata.append([1,1,1,1,1])
self.emit(SIGNAL('dataChanged()'))
print 'success'
class MyTableModel(QAbstractTableModel):
def __init__(self, datain, headerdata, parent=None):
"""
Args:
datain: a list of lists\n
headerdata: a list of strings
"""
QAbstractTableModel.__init__(self, parent)
self.arraydata = datain
self.headerdata = headerdata
def rowCount(self, parent):
return len(self.arraydata)
def columnCount(self, parent):
if len(self.arraydata) > 0:
return len(self.arraydata[0])
return 0
def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
return QVariant(self.arraydata[index.row()][index.column()])
def setData(self, index, value, role):
pass # not sure what to put here
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return QVariant(self.headerdata[col])
return QVariant()
def sort(self, Ncol, order):
"""
Sort table by given column number.
"""
self.emit(SIGNAL("layoutAboutToBeChanged()"))
self.arraydata = sorted(self.arraydata, key=operator.itemgetter(Ncol))
if order == Qt.DescendingOrder:
self.arraydata.reverse()
self.emit(SIGNAL("layoutChanged()"))
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
答案 0 :(得分:4)
当模型的基础数据发生变化时,模型应发出layoutChanged或layoutAboutToBeChanged,以便视图正确更新(如果您想要更新特定内容,还可以dataChanged细胞范围)。
所以你只需要这样的东西:
def test(self):
self.tabledata.append([1,1,1,1,1])
self.table.model().layoutChanged.emit()
print 'success'
答案 1 :(得分:1)
我已经使您的表引用了一个类变量而不是实例变量,因此您几乎可以在代码中的任何地方编辑该表的数据。
#include <stdio.h>
//this is number structure(object)
//probably you have defined something similar
typedef struct __number_t{
char redeslod;
int number;
}Number;
void reverse(Number *n){ // accept pointer as argument
//do your reverse logic here
printf("number is %d\n", n->number);
}
Number *fun(Number *first, Number *second){ //accept pointer as argument, returns a pointer
Number *ret = NULL;
if(first->redeslod=='d'){
//reverse(&first); this will pass a pointer to pointer
reverse(first);
}
if(second->redeslod=='d'){
reverse(second);
}
//do not forget to return your number here
return ret;
}
int main()
{
Number first,second;
first.redeslod = 'd';
first.number = 1;
second.redeslod = 'c';
second.number = 2;
fun(&first, &second); //here &passes the address
return 0;
}
第二,我使用了pandas-dataframe-editing类型的方法。 假设您要添加的数据单独存储在变量中:
# First access the data of the table
self.tv_model = self.tv.model()
根据将数据添加到表中还是更新现有值,可以采用不同的方法进行下一步。将数据添加为新行如下。
# These can be whatever, but for consistency,
# I used the data in the OP's example
new_values = [1, 1, 1, 1, 1]
由于self.tv_model是对表实际数据的引用, 发出以下信号将更新数据,或将其“提交”给模型, 可以这么说。
# The headers should also be a class variable,
# but I left it as the OP had it
header = ['col_0', 'col_1', 'col_2', 'col_3', 'col_4']
# There are multiple ways of establishing what the row reference should be,
# this is just one example how to add a new row
new_row = len(self.tv_model.dataFrame.index)
for i, col in enumerate(header):
self.tv_model.dataFrame.loc[new_row, col] = new_values[i]
答案 2 :(得分:0)
QAbstractTableModel
有两种特殊的方法(beginInsertRows()和endInsertRows())。
您可以在自定义模型中添加api-point。例如:
def insertGuest(self, guest):
self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
self.guestsTableData.append(guest)
self.endInsertRows()