gpt4 book ai didi

c++ - 将基于像素的图形绘制到 QWidget

转载 作者:太空狗 更新时间:2023-10-29 21:29:37 28 4
gpt4 key购买 nike

我有一个应用程序需要以指定的帧速率逐个像素地绘制(模拟旧机器)。需要注意的是,主机引擎在后台线程中运行,以确保 UI 在模拟期间保持响应和可用。

目前,我正在尝试使用这样的东西:

class QVideo : public QWidget {
public:
QVideo(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f), screen_image_(256, 240, QImage::Format_RGB32) {

}

void draw_frame(void *data) {
// render data into screen_image_
}

void start_frame() {
// do any pre-rendering prep work that needs to be done before
// each frame
}

void end_frame() {
update(); // force a paint event
}

void paintEvent(QPaintEvent *) {
QPainter p(this);
p.drawImage(rect(), screen_image_, screen_image_.rect());
}

QImage screen_image_;
};

这主要是有效的,而且令人惊讶的是不是很慢。但是,有一个问题。更新函数安排一个paintEvent,它可能不会马上发生。事实上,根据 Qt 文档,一堆 paintEvent 可能会“合并”。

我看到的负面影响是,在模拟几分钟后,屏幕停止更新(尽管模拟仍在运行,但图像似乎卡住了),直到我执行一些强制屏幕更新的操作,例如打开和关闭窗口的最大化。

我曾尝试使用 QTimer 和其他类似机制来实现在 GUI 线程中进行渲染的效果,以便我可以强制立即更新,但这导致了无法接受的性能问题。

有没有更好的方法以固定的间隔不断地将像素绘制到小部件上。首选纯 Qt 解决方案。

编辑some people选择有一种态度而不是阅读整个问题,我会澄清这个问题。我不能使用 QWidget::repaint 因为它有一个限制,它必须从与事件循环相同的线程调用。否则,不会发生任何更新,而是会收到如下 qDebug 消息:

QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QWidget::repaint: Recursive repaint detected
QPainter::begin: A paint device can only be painted by one painter at a time.
QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent
QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent

编辑:为了演示这个问题,我创建了这个简单的示例代码:

QVideo.h

#include <QWidget>
#include <QPainter>

class QVideo : public QWidget {
Q_OBJECT;
public:
QVideo(QWidget *parent = 0, Qt::WindowFlags f = 0) : QWidget(parent, f), screen_image_(256, 240, QImage::Format_RGB32) {

}

void draw_frame(void *data) {
// render data into screen_image_
// I am using fill here, but in the real thing I am rendering
// on a pixel by pixel basis
screen_image_.fill(rand());
}

void start_frame() {
// do any pre-rendering prep work that needs to be done before
// each frame
}

void end_frame() {
//update(); // force a paint event
repaint();
}

void paintEvent(QPaintEvent *) {
QPainter p(this);
p.drawImage(rect(), screen_image_, screen_image_.rect());
}

QImage screen_image_;
};

主.cc:

#include <QApplication>
#include <QThread>
#include <cstdio>
#include "QVideo.h"


struct Thread : public QThread {

Thread(QVideo *v) : v_(v) {
}

void run() {
while(1) {
v_->start_frame();
v_->draw_frame(0); // contents doesn't matter for this example
v_->end_frame();
QThread::sleep(1);
}
}

QVideo *v_;
};

int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QVideo w;
w.show();

Thread t(&w);
t.start();

return app.exec();
}

我绝对愿意探索不使用临时 QImage 进行渲染的选项。它只是 Qt 中唯一一个似乎具有直接像素写入接口(interface)的类。

最佳答案

尝试从线程向调用 repaint() 的事件循环小部件中的槽发出信号,然后立即执行。我正在我的绘图程序中做这样的事情,它在一个线程中执行主要计算,然后告诉小部件什么时候该重新绘制()数据。

关于c++ - 将基于像素的图形绘制到 QWidget,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4403019/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com