将文件加载到 drawBackground(QPainter *painter, const QRectF &)

Posted

技术标签:

【中文标题】将文件加载到 drawBackground(QPainter *painter, const QRectF &)【英文标题】:Loading files into drawBackground(QPainter *painter, const QRectF &) 【发布时间】:2012-01-19 17:25:16 【问题描述】:

目前我正在尝试将 *.obj 文件加载到我的程序中。我的代码基于这个例子:

Accelerate your widgets with OpenGL(changed link)

我的代码中唯一的区别是我有一个 glwidget 类,其中定义了所有绘图。在类 OpenGLScene 中只定义了我的 Gui。在函数 drawBackground(QPainter *painter, const QRectF &) 我调用函数paintGL。

void OpenGLScene::drawBackground(QPainter *painter, const QRectF &)

    if (painter->paintEngine()->type() != QPaintEngine::OpenGL
    && painter->paintEngine()->type() != QPaintEngine::OpenGL2)

    qWarning("OpenGLScene: drawBackground needs a QGLWidget to be set as viewport on the graphics view");
    return;


painter->beginNativePainting();

glClearColor(m_backgroundColor.redF(), m_backgroundColor.greenF(), m_backgroundColor.blueF(), 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

if (m_model) 

    m_model->paintGL();


painter->endNativePainting();

简单的绘图和东西工作正常。在我尝试加载 *.obj 文件之前,我只会遇到问题。我已经尝试了几件事,但没有奏效。 现在,我最终找到了在我的 glWidget-Class 中定义模型类(您可以在示例中找到)中的所有函数,然后在 paintGL 中调用渲染函数的解决方案。然后在OpenGLScene中调用paintGL。

在这里你可以看到我的头文件:OpenGLScene.h 和 GLWidget.h:

class GLWidget : public QGLWidget

Q_OBJECT
public:
float           m_distance;
GLWidget(const QString &filePath);
GLWidget(QWidget *parent = 0);
~GLWidget();
QSize           minimumSizeHint() const;
QSize           sizeHint() const;
void            initializeGL();
void            paintGL();
void            resizeGL(int width, int height);
void render() const;
QString fileName() const  return m_fileName; 
int faces() const  return m_pointIndices.size() / 3; 
int edges() const  return m_edgeIndices.size() / 2; 
int points() const  return m_points.size(); 
QString m_fileName;
QVector<Point3d> m_points;
QVector<Point3d> m_normals;
QVector<int> m_edgeIndices;
QVector<int> m_pointIndices;
;


#ifndef QT_NO_CONCURRENT
#include <QFutureWatcher>
#endif

class GLWidget;

class OpenGLScene : public QGraphicsScene

Q_OBJECT

public:
OpenGLScene();
void drawBackground(QPainter *painter, const QRectF &rect);
QDialog *createDialog(const QString &windowTitle) const;

void setModel(GLWidget *model);

//Model       *m_model;
GLWidget    *m_model;
QColor      m_backgroundColor;
float       m_distance;
QLabel      *m_labels[4];
QWidget     *m_modelButton;
#ifndef QT_NO_CONCURRENT
QFutureWatcher<GLWidget *> m_modelLoader;
#endif
public slots:
void loadModel();
void loadModel(const QString &filePath);
void modelLoaded();
;

不幸的是,这个想法行不通,因为我收到了这个错误:

“在 GUI 线程之外使用像素图是不安全的”

但我真的不明白这是什么意思。

【问题讨论】:

嗯……也许我应该更详细地说明它。我的第一个问题是为什么在 glwidget 中定义模型函数是一个问题? GLWidget 的内容与模型类的内容相同,但还有一些额外内容。因此我不明白错误:“在 GUI 线程之外使用像素图是不安全的”因为在 OpenGLScene 类中,除了数据类型名称之外我没有任何改变。我已将 Model-datatype 替换为 GLWidget-datatype。也许有人可以帮助我?或者它是如此明显以至于很容易回答。如果是这样,如果您能与我分享您的想法,我会很高兴。 对于所有可能尝试过上面链接中的代码的人。很抱歉,这是一个旧版本,无法正常工作。这是new one对不起 【参考方案1】:

如果您已将所有Model 内容移至GLWidget,那么我假设您现在正在::loadModel 中创建您的GLWidget 实例?如果是这样,请注意这是在新线程中创建的。当加载线程完成时,它看起来不会自动移动到主(GUI)线程中。 QObject 实际发生的事情是an open question。

如果您想完全禁用线程以简化事情,请删除这些行

#ifndef QT_NO_CONCURRENT
#include <QFutureWatcher>
#endif

#ifndef QT_NO_CONCURRENT
QFutureWatcher<Model *> m_modelLoader;
#endif

在 openglscene.h 中。在 OpenGLScene 构造函数主体中删除行

#ifndef QT_NO_CONCURRENT
    connect(&m_modelLoader, SIGNAL(finished()), this, SLOT(modelLoaded()));
#endif

OpenGLScene::loadModel(const QString &amp;filePath)

#ifndef QT_NO_CONCURRENT
    m_modelLoader.setFuture(QtConcurrent::run(::loadModel, filePath));
#else
    setModel(::loadModel(filePath));
    modelLoaded();
#endif

只是

    setModel(::loadModel(filePath));
    modelLoaded();

最后删除

#ifndef QT_NO_CONCURRENT
    setModel(m_modelLoader.result());
#endif

来自OpenGLScene::modelLoaded()

【讨论】:

好吧,据我了解,无法像我尝试的那样加载 obj 文件。我试图将我的对象推入主线程,但它不起作用。我是线程的完整新手。我已经对这个问题进行了一些研究,但我无法掌握这一点。线程的整个概念似乎是一件大事。可能有另一种加载 obj.-files 的方法吗?也许没有线程。从您的回答中,我感觉可能存在这种可能性。你可以再详细一点吗?谢谢。 @buddy:您当然可以轻松地删除线程,因为在使用线程的地方有两个代码路径。编译哪个取决于 QT_NO_CONCURRENT 预处理器宏。要么确保在相关源文件的顶部定义了这个宏,要么只是注释掉线程代码(在ifndef QT_NO_CONCURRENT 位中)。试试这个,看看它是否有效。如果你想让它与线程一起工作,请告诉我,我可以看看我能做什么。 实际上 Qt 似乎还有另一个问题。我已经从未更改的源代码中删除了线程。(我仍然有模型类)。这工作正常。一旦我添加到模型类: public QGLWidget 我得到错误:在 GUI 线程之外使用像素图是不安全的。所以它似乎是一般的继承而不是线程。还有我在 GLWidget 中需要的继承你知道为什么会这样吗? @buddy:我已经更新了我的答案,概述了您需要做的所有事情,以确保您没有线程化。检查您是否进行了所有这些更改。 抱歉我的回复晚了。我不得不在最后几天工作。感谢您的帮助,现在可以使用了。如果它以这种方式工作正常,我不明白为什么应该使用线程。但也许有一天我会开始学习整个线程的东西。也许那时它会有意义。再次感谢

以上是关于将文件加载到 drawBackground(QPainter *painter, const QRectF &)的主要内容,如果未能解决你的问题,请参考以下文章

QGraphicsView::drawBackground 中的故障网格

如何正确设置 QT_QPA_PLATFORM_PLUGIN_PATH(概念)?

[vscode][原创]pyqt5配置后报错:qt.qpa.plugin: Could not find the Qt platform plugin “windows“ in ““

PyCharm运行出现 Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run

PyCharm运行出现 Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run

pyqt5报错:qt.qpa.plugin: Could not find the Qt platform plugin "windows" in "" Thi