有许多小部件的性能问题,分别堆叠了QTableWidgets

时间:2018-12-17 12:56:15

标签: python python-3.x pyqt pyqt5

我需要显示一个复杂的表,并决定使用堆叠的QTableWidgets。随着行数的增加,该程序需要花费大量时间来创建所有小部件,并且几乎需要花费相同的时间来显示它们。

主表如下:MainTable

表中堆积的TableWidget:

StackedTables

如果该单元格包含数据,则MainTable的一个单元格中至少有一个TableWidget,在最坏的情况下,该单元格中还有2个以上的TableWidgets。这意味着我可以在一个单元格中拥有3个TableWidget。

使用cProfile和time.time进行80行的时间测量(每行48个复杂单元格):

complete update time: 15s (manually stopped)
time to create the table: 7.548534870147705s (time.time over complete function)
display time: 7.5s (complete update time - function time)
rows: 80

     63600 function calls in 7.462 seconds

   Ordered by: internal time

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 1896    2.455    0.001    3.882    0.002     DigitalePlanungstafel.py:6054(grundWidgetErstellen) -- (create table in cell)
 3936    2.027    0.001    2.027    0.001 {built-in method setCellWidget}
 2535    1.306    0.001    1.306    0.001 {built-in method setColumnCount}
  630    0.770    0.001    1.183    0.002 DigitalePlanungstafel.py:6035(obenWidgetErstellen) -- (create table in table in cell)
 2607    0.674    0.000    0.674    0.000 {built-in method setRowCount}
 2528    0.059    0.000    0.059    0.000 {built-in method horizontalHeader}
 2526    0.021    0.000    0.021    0.000 {built-in method verticalHeader}
  163    0.019    0.000    0.019    0.000 {method 'execute' of 'sqlite3.Cursor' objects}
 2526    0.016    0.000    0.016    0.000 {built-in method setFrameShape}
 1410    0.014    0.000    0.014    0.000 {built-in method setStyleSheet}
 4502    0.013    0.000    0.013    0.000 {built-in method setRowHeight}
 2526    0.009    0.000    0.009    0.000 {built-in method setFixedSize}
 2546    0.009    0.000    0.009    0.000 {built-in method setColumnWidth}
 5052    0.009    0.000    0.009    0.000 {built-in method setVisible}
 1329    0.007    0.000    0.007    0.000 {built-in method setItem}
 2181    0.006    0.000    0.006    0.000 {built-in method cellWidget}
   80    0.005    0.000    0.005    0.000 {built-in method addWidget}
 2526    0.004    0.000    0.004    0.000 {built-in method setEditTriggers}
  929    0.004    0.000    0.004    0.000 {built-in method setBackground}
 1330    0.003    0.000    0.003    0.000 {method 'format' of 'str' objects}
  414    0.003    0.000    0.003    0.000 {built-in method _pickle.loads}
  336    0.003    0.000    0.003    0.000 {method 'strftime' of 'datetime.date' objects}
 2526    0.003    0.000    0.003    0.000 {built-in method setHorizontalScrollBarPolicy}
 1410    0.002    0.000    0.002    0.000 {built-in method setFixedHeight}
 1377    0.002    0.000    0.002    0.000 {built-in method setTextAlignment}
   83    0.002    0.000    0.004    0.000 _strptime.py:321(_strptime)
    2    0.002    0.001    0.002    0.001 {built-in method setSortingEnabled}
 2526    0.001    0.000    0.001    0.000 {built-in method setShowGrid}
 1570    0.001    0.000    0.001    0.000 {built-in method rowHeight}
 2526    0.001    0.000    0.001    0.000 {built-in method setSelectionMode}
  163    0.001    0.000    0.001    0.000 {method 'fetchall' of 'sqlite3.Cursor' objects}
  240    0.001    0.000    0.001    0.000 DigitalePlanungstafel.py:7494(__init__)
 2526    0.001    0.000    0.001    0.000 {built-in method setVerticalScrollBarPolicy}
    1    0.001    0.001    0.001    0.001 {built-in method sortByColumn}
   80    0.001    0.000    0.001    0.000 {built-in method setLayout}
   83    0.001    0.000    0.001    0.000 {built-in method _locale.setlocale}
    1    0.001    0.001    0.001    0.001 {built-in method _sqlite3.connect}
   89    0.000    0.000    0.000    0.000 {built-in method setForeground}
   83    0.000    0.000    0.000    0.000 {method 'match' of '_sre.SRE_Pattern' objects}
   83    0.000    0.000    0.004    0.000 _strptime.py:562(_strptime_datetime)
   48    0.000    0.000    0.000    0.000 {built-in method setHorizontalHeaderItem}
   80    0.000    0.000    0.000    0.000 {built-in method setContentsMargins}
   83    0.000    0.000    0.005    0.000 {built-in method strptime}
   83    0.000    0.000    0.000    0.000 locale.py:379(normalize)
   88    0.000    0.000    0.000    0.000 {built-in method setFont}
  160    0.000    0.000    0.000    0.000 {built-in method setData}
   83    0.000    0.000    0.000    0.000 {method 'groupdict' of '_sre.SRE_Match' objects}
   80    0.000    0.000    0.000    0.000 {built-in method setAlignment}
   83    0.000    0.000    0.001    0.000 _strptime.py:29(_getlang)
   83    0.000    0.000    0.001    0.000 locale.py:565(getlocale)
   83    0.000    0.000    0.001    0.000 locale.py:462(_parse_localename)
   80    0.000    0.000    0.000    0.000 {built-in method setUnderline}
    1    0.000    0.000    0.000    0.000 {built-in method io.open}
  249    0.000    0.000    0.000    0.000 {method 'get' of 'dict' objects}
    1    0.000    0.000    0.000    0.000 {method 'close' of 'sqlite3.Connection' objects}
  160    0.000    0.000    0.000    0.000 {built-in method item}
  742    0.000    0.000    0.000    0.000 DigitalePlanungstafel.py:7499(__lt__)
   48    0.000    0.000    0.000    0.000 {built-in method today}
  165    0.000    0.000    0.000    0.000 {method 'toordinal' of 'datetime.date' objects}
  475    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
  167    0.000    0.000    0.000    0.000 {built-in method builtins.len}
  166    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
   83    0.000    0.000    0.000    0.000 {method 'end' of '_sre.SRE_Match' objects}
   84    0.000    0.000    0.000    0.000 {method 'lower' of 'str' objects}
    1    0.000    0.000    0.000    0.000 {method 'close' of '_io.TextIOWrapper' objects}
    2    0.000    0.000    0.000    0.000 {built-in method builtins.print}
   83    0.000    0.000    0.000    0.000 {method 'keys' of 'dict' objects}
   47    0.000    0.000    0.000    0.000 {built-in method columnCount}
   83    0.000    0.000    0.000    0.000 {method 'weekday' of 'datetime.date' objects}
   96    0.000    0.000    0.000    0.000 {method 'date' of 'datetime.datetime' objects}
   20    0.000    0.000    0.000    0.000 {built-in method columnWidth}
    1    0.000    0.000    0.000    0.000 {built-in method _locale._getdefaultlocale}
    3    0.000    0.000    0.000    0.000 {method 'split' of 'str' objects}
    1    0.000    0.000    0.000    0.000 _strptime.py:284(_calc_julian_from_U_or_W)
    1    0.000    0.000    0.000    0.000 _bootlocale.py:11(getpreferredencoding)
    1    0.000    0.000    0.000    0.000 {built-in method sortIndicatorOrder}
    2    0.000    0.000    0.000    0.000 {built-in method time.time}
    1    0.000    0.000    0.000    0.000 {method 'cursor' of 'sqlite3.Connection' objects}
    2    0.000    0.000    0.000    0.000 {method 'index' of 'list' objects}
    1    0.000    0.000    0.000    0.000 {built-in method fromordinal}
    1    0.000    0.000    0.000    0.000 {built-in method sortIndicatorSection}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    1    0.000    0.000    0.000    0.000 codecs.py:259(__init__)

调用函数和创建表的时间还可以,但是程序需要几乎相同的时间才能做出反应。

目标是将更新时间减少大约20%。 50%。我需要显示约200行。

堆叠的QTableWidget是正确的方法吗-如果是的话,我该怎么做才能优化更新时间?

我已经考虑过将演示文稿从QTableWidget更改为QGraphicsView,并简单地绘制矩形。 或也许是一个组合,例如:对表头和第一列使用QTableWidget,然后合并所有复杂的单元格并插入QGraphicsView,但是我不确定是否能够为绘制的单元格获取正确的大小,不知道显示时间是否会缩短。

你们认为什么样的方式适合这样的桌子?

如果需要,我可以追加该函数,该函数将更新表。

编辑:

我现在在MainTable中将2行用于一个Block,这将堆叠的小部件的数量从2.526减少到7!

同一行的时间度量现在看起来像这样:

complete update time: ~2s (manually stopped)
time to create the table: 0.572490930557251 (time.time over complete function)
display time: ~1.5s (complete update time - function time)
rows: 160
     20912 function calls in 0.534 seconds

Ordered by: internal time

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 1417    0.258    0.000    0.258    0.000 {built-in method setCellWidget}
   88    0.209    0.002    0.209    0.002 {built-in method setRowCount}
  163    0.017    0.000    0.017    0.000 {method 'execute' of 'sqlite3.Cursor' objects}
 1410    0.010    0.000    0.010    0.000 {built-in method setStyleSheet}
   80    0.005    0.000    0.005    0.000 {built-in method addWidget}
 1336    0.004    0.000    0.004    0.000 {built-in method setItem}
    7    0.003    0.000    0.004    0.001 DigitalePlanungstafel.py:6037(obenWidgetErstellen)
  501    0.003    0.000    0.003    0.000 {built-in method _pickle.loads}
 1990    0.003    0.000    0.003    0.000 {built-in method cellWidget}
  336    0.002    0.000    0.002    0.000 {method 'strftime' of 'datetime.date' objects}
   83    0.002    0.000    0.004    0.000 _strptime.py:321(_strptime)
 1330    0.002    0.000    0.002    0.000 {method 'format' of 'str' objects}
 1410    0.002    0.000    0.002    0.000 {built-in method setFixedHeight}
  929    0.001    0.000    0.001    0.000 {built-in method setBackground}
 1377    0.001    0.000    0.001    0.000 {built-in method setTextAlignment}
  240    0.001    0.000    0.001    0.000 DigitalePlanungstafel.py:7452(__init__)
  163    0.001    0.000    0.001    0.000 {method 'fetchall' of 'sqlite3.Cursor' objects}
   16    0.001    0.000    0.001    0.000 {built-in method setColumnCount}
  770    0.001    0.000    0.001    0.000 {built-in method setSpan}
 2127    0.001    0.000    0.001    0.000 {built-in method item}
 1570    0.001    0.000    0.001    0.000 {built-in method rowHeight}
   80    0.001    0.000    0.001    0.000 {built-in method setLayout}
   83    0.000    0.000    0.000    0.000 {built-in method _locale.setlocale}
    1    0.000    0.000    0.000    0.000 {built-in method _sqlite3.connect}
  167    0.000    0.000    0.000    0.000 {built-in method setRowHeight}
   89    0.000    0.000    0.000    0.000 {built-in method setForeground}
   83    0.000    0.000    0.000    0.000 {method 'match' of '_sre.SRE_Pattern' objects}
   48    0.000    0.000    0.000    0.000 {built-in method setHorizontalHeaderItem}
   83    0.000    0.000    0.004    0.000 _strptime.py:562(_strptime_datetime)
    7    0.000    0.000    0.000    0.000 {built-in method takeItem}
   80    0.000    0.000    0.000    0.000 {built-in method setContentsMargins}
   83    0.000    0.000    0.004    0.000 {built-in method strptime}
   88    0.000    0.000    0.000    0.000 {built-in method setFont}
  160    0.000    0.000    0.000    0.000 {built-in method setData}
   83    0.000    0.000    0.000    0.000 locale.py:379(normalize)
   80    0.000    0.000    0.000    0.000 {built-in method setAlignment}
   83    0.000    0.000    0.001    0.000 _strptime.py:29(_getlang)
   83    0.000    0.000    0.000    0.000 {method 'groupdict' of '_sre.SRE_Match' objects}
   83    0.000    0.000    0.001    0.000 locale.py:565(getlocale)
    1    0.000    0.000    0.000    0.000 {method 'close' of 'sqlite3.Connection' objects}
    1    0.000    0.000    0.000    0.000 {built-in method io.open}
    7    0.000    0.000    0.000    0.000 {built-in method horizontalHeader}
   80    0.000    0.000    0.000    0.000 {built-in method setUnderline}
  249    0.000    0.000    0.000    0.000 {method 'get' of 'dict' objects}
   83    0.000    0.000    0.000    0.000 locale.py:462(_parse_localename)
   48    0.000    0.000    0.000    0.000 {built-in method today}
    7    0.000    0.000    0.000    0.000 {built-in method verticalHeader}
  475    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
  167    0.000    0.000    0.000    0.000 {built-in method builtins.len}
  165    0.000    0.000    0.000    0.000 {method 'toordinal' of 'datetime.date' objects}
    1    0.000    0.000    0.000    0.000 {method 'close' of '_io.TextIOWrapper' objects}
  166    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
    7    0.000    0.000    0.000    0.000 {built-in method setFrameShape}
   27    0.000    0.000    0.000    0.000 {built-in method setColumnWidth}
   84    0.000    0.000    0.000    0.000 {method 'lower' of 'str' objects}
    1    0.000    0.000    0.000    0.000 {method 'sort' of 'list' objects}
   83    0.000    0.000    0.000    0.000 {method 'end' of '_sre.SRE_Match' objects}
   87    0.000    0.000    0.000    0.000 DigitalePlanungstafel.py:6059(<lambda>)
   83    0.000    0.000    0.000    0.000 {method 'keys' of 'dict' objects}
    2    0.000    0.000    0.000    0.000 {built-in method builtins.print}
    7    0.000    0.000    0.000    0.000 {built-in method setFixedSize}
   14    0.000    0.000    0.000    0.000 {built-in method setVisible}
   83    0.000    0.000    0.000    0.000 {method 'weekday' of 'datetime.date' objects}
   96    0.000    0.000    0.000    0.000 {method 'date' of 'datetime.datetime' objects}
    7    0.000    0.000    0.000    0.000 {built-in method setEditTriggers}
   20    0.000    0.000    0.000    0.000 {built-in method columnWidth}
    7    0.000    0.000    0.000    0.000 {built-in method setHorizontalScrollBarPolicy}
    1    0.000    0.000    0.000    0.000 {built-in method _locale._getdefaultlocale}

更新时间不止一次,但是由于拆分,我有两个问题。

  1. 排序(在标题上)不再起作用。这是由于合并引起的,它弄乱了所有内容。有没有一种方法可以在排序之前冻结两个关联的行?

  2. 我只希望一次选择一行。分裂的原因无论选择哪一个,我都需要选择两个关联的行。没什么大不了的,但是看起来确实不好(参见图片)。

MainTable selected row

MainTable selected row

1 个答案:

答案 0 :(得分:0)

您不想执行任何操作-相反:

  1. 为数据使用模型。

  2. 使用一个视图模型,使模型适合您想要的视图。

  3. 使用QTableView显示视图模型。