【问题标题】:paint() vs paintEvent() in QtQt中的paint()与paintEvent()
【发布时间】:2015-05-25 05:54:53
【问题描述】:

我有两个问题。

  1. paint()QGraphicsItempaintEvent()QWidget API 之间有什么区别?

  2. 我正在开发一个类似于 GUI 的计时器,因此我在嵌入式 linux 板上使用 paint() API 每 100 毫秒更新一次屏幕。它几乎消耗了所有的CPU。知道如何防止这种情况吗?

或者有没有其他方法来做这个简单的图形?

  1. 我还有多个QGraphicsScene,每个都有自己的QGraphicsView,在网格布局中。如何从 MainWindow 更新单个视图。

以下是我目前如何执行此操作的代码:

/****SCENE 1*****/
    scene_1 = new QGraphicsScene();
    scene_1->setBackgroundBrush(Qt::black);
    ui->gv_1->setScene(scene_1);
    ui->gv_1->setRenderHint(QPainter::Antialiasing);
    circle = scene_1->addEllipse(50, 80, 150, 150, outlinePen, darkGreyBrush);
    textSlotNo = scene_1->addText("1", QFont("Arial", 30) );
    textSlotNo->setDefaultTextColor(Qt::gray);
    textSlotNo->setPos(0,50);

    MyItem *item_1 = new MyItem(1);
    scene_1->addItem(item_1);
    item_1->timer = new QTimer();
    connect(item_1->timer, SIGNAL(timeout()),scene_1, SLOT(update()));
    item_1->timer->start(100);

/****SCENE 2*****/
......

硬件:TI-AM3354

【问题讨论】:

  • 还添加每 100 毫秒更新项目的代码。每个项目都有一个计时器当然效率不高,即使没有任何改变,看起来你也会重新绘制所有内容。如果项目的属性发生变化,请尝试简单地更新项目,并且根本不要手动调用 update()。
  • 我确实每 100 毫秒更新一次场景。我画了一条不同起始位置的圆弧,从而使它好像在旋转。我还在场景中使用 drawText() 更新时间。在每个场景中不使用 QTimer 还有其他方法吗?
  • 我只用了一个定时器,CPU就被那个定时器完全消耗了。
  • 你有多少场景?
  • 我有 10 个场景要更新。现在只测试一个。

标签: qt paint qgraphicsitem paintevent


【解决方案1】:
  1. paintEvent() 是一个通用事件处理程序,由 Qt 调用以绘制一个小部件,通常是整个小部件,但有时可以通过尊重 QPaintEvent 的 region 和 rect 属性来优化。
  2. paint() 在绘制 QGraphicsScene 时由 QGraphicsView 在各个 QGraphicsItems 上调用。通常不会在所有项目上调用它,QGraphicsView 在绘制项目之前会进行各种检查,例如确保该项目在视口中并且不被其他项目等隐藏。

从您发布的代码中,我看到了两个优化:首先,不要为每个项目单独运行 QTimer,而是为整个场景运行一个计时器。现在,您的代码每 100 毫秒最多触发 N 次重绘,而不是一次。此外,如果属性确实发生了变化,请更新项目的属性并让他们自己调用QGraphicsItem::update(),而不是无条件地更新整个场景。

【讨论】:

  • 在项目实际发生变化时才调用 QGraphicsItem::update() doc.qt.io/qt-5/qgraphicsitem.html#update
  • 我现在每 1 分钟在 QTimer 的插槽上调用 update() 更改项目的视觉效果。对于单个计时器的想法,我应该为每个项目注册一个事件并在 timerEvent() 中使用它吗?再次感谢您的帮助:)
  • 我正在像这样connect(item_1->timer, SIGNAL(timeout()),this, SLOT(updateUI_1()));updateUI_1() 内的单独插槽中更新每个视图我打电话给scene_1->update() 你能告诉我这是正确的方法吗?
  • 您根本不需要在场景中调用 update(),只需更新项目属性并让它们在属性实际更改时在内部调用 update()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-07
  • 1970-01-01
相关资源
最近更新 更多