代码之家  ›  专栏  ›  技术社区  ›  Dani

高效地高速更新qtableview

  •  8
  • Dani  · 技术社区  · 14 年前

    我使用qTableView和qitemDelegate子类来控制TableView单元格的外观。

    每个单元显示外部连接设备的名称和状态,一次最多可连接100个设备。

    每个设备的名称和类型基本上都是静态的,很少更新(可能每小时更新一次),但每个单元都需要显示设备输入的实时值,我目前每50毫秒进行一次轮询。该值显示为由TableView提供给delegate::paint()方法的绘制器绘制的基本条形图。

    每秒更新模型20次的问题是,每次都会重新绘制整个表,这是非常低效的。将paint方法限制为只绘制条形图,这表明大部分CPU时间都专用于绘制每个单元上的名称、状态和相关图像,而不是绘制图形。

    我需要找到的是一种不需要重新绘制单元格就可以定期更新每个单元格的图形的方法,但是我不知道该怎么做。

    实现这一目标最有效的方法是什么?

    编辑:附加到帮助的图像。

    图像表示qTableView中的10个传感器。数字、名称和状态实际上是静态的,几乎从不更新。“传感器值”文本旁边的条形图每50毫秒更新一次。我只想绘制此条形图,而不是文本、状态和单元格背景。状态灯和背景是复杂的图像,因此比简单地绘制和填充一个rect要花费更多的CPU时间。

    alt text

    3 回复  |  直到 14 年前
        1
  •  6
  •   Live    14 年前

    由于qTableView继承了qWidget,因此可以对其调用以下内容:

    setUpdatesEnabled(false);
    changeAllYourData();
    setUpdatesEnabled(true);
    

    当SETUPDATESENABLED为false时,对它的任何paint()或update()调用都无效。所以,您可以停止它的更新,更改所有数据,然后重新启用它,可能通过手动调用paint()或update()来实现,我不确定这部分。

    这是SETUPDATESENABLED方法的文档。

    QWidget updatesEnabled

    希望这有帮助。

    用户评论后编辑:

    通过在执行原始paint()或update()之前测试标志,可以为qitemDelegate子类(因为它不继承qwidget,也没有qwidget)实现自己的setupdatesEnabled(bool)。 之后,如果必须更新或重新绘制qTableView的每个单元格(或行或列),则可以指定它们。

    通过这样做,您可以阻止其他单元格(代理)重新绘制,除非您更改手动创建的SETUPDATESENABLED标志,但保留包含图形的单元格上的更新。

    我必须说我从来没有测试过这个或者类似的东西,所以我希望它能像我认为的那样工作。

    祝你好运

    从用户编辑后编辑:

    在我之前的评论之后,您可以为每个单元格设置一个标志,而不是为每个单元格设置一个标志(我认为您的图形在一个单独的单元格中),使每个代理只绘制您的图形或整个图像。

    希望这有帮助,

    编辑:

    我偶然发现了Qt4.7中的一个新特性(我不知道您是否可以使用它,但它可以解决您的一些问题。) 功能是qstaticText。它是一个类,允许您缓存文本(字体和效果)并更快地绘制它们。查看链接 here

    希望它能解决你的问题。

        2
  •  2
  •   Caleb Huitt - cjhuitt    14 年前

    我很少建议这条路径而不是代表,但在你的情况下,它可能是值得的。我会考虑创建自己的视图,它足够了解只更新屏幕上需要更新的部分。像这样的视图小部件显然比通常情况下更具有特殊用途,但是如果您真的需要效率,这是一种方法。

    如果您需要提高效率,还需要考虑的其他事项是,确保您只标记实际更改的行(如果传感器值不经常更改,并且只经常进行轮询),或者考虑添加一个迟滞值,在这两个值之间实际上没有重绘(如果ENSOR值变化不够快,无法否定这一点)。

        3
  •  1
  •   user362638    14 年前

    将背景图像(单元背景图像、状态和名称)缓存到模型中,作为qpixmap。仅当状态或名称更改时才重新绘制该pixmap。在一般情况下,您只需要绘制缓存的qpixmap和上面的传感器值。

    编辑:

    向您的数据类添加fullrepairneeded标志。当状态或名称更改时,fullRepaintRequired设置为true。

    当代理正在绘制该项时,代理首先检查该项的“完全修复所需”标志。如果需要完全修复是真的,那么将创建一个新的qpixmap,并将所有内容绘制到该qpixmap上,最后将其绘制到TableView中。然后使用模型的setdata函数(但不调用datachanged)将qpixmap缓存到模型(这意味着对您的数据类而言)。“需要完全修复”现在设置为“假”。

    但是,如果代理的paint函数中的fullrepairneeded为false,则会从模型中请求先前缓存的qpixmap,并将其绘制到TableView中,最后在上面绘制传感器值。