在 Qt 5.12 上将 QGLWidget 作为视口实现
Implementing QGLWidget as viewport on Qt 5.12
我有一个功能完备的应用程序,它利用 QGraphicsView
+ QGLWidget
和 QGraphicsScene
通过用户交互绘制 3D 场景。
Qt5 的 Boxes 示例中解释了这个概念。
自更新到 Qt 5.12 后,该应用程序不再运行。除了我已经修复的其他一些小问题,现在我已经设置了所有内容,但是视口没有显示任何内容。
我创建了一个最小概念程序,它创建了一个 QGraphicsView
,一个 QGLWidget
作为视口,以及一个 QGraphicsScene
派生的 class 来绘制视口。
我设置了所有内容,但未调用 QGraphicsScene::DrawBackground()
函数。
有趣的是,该应用程序在 Qt 5.6 中运行良好,但在 5.12 中却不行。
两个版本之间有什么变化?
以下是示例应用程序:
CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(Prototypes)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -Wall)
find_package(Qt5 REQUIRED COMPONENTS Core Widgets OpenGL)
add_executable(Prototypes main.cpp GraphicsView.cpp GraphicsView.h Scene.cpp Scene.h)
target_link_libraries(Prototypes Qt5::Core Qt5::OpenGL Qt5::Widgets)
main.cpp
#include "GraphicsView.h"
#include "Scene.h"
#include <QApplication>
#include <QGLWidget>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGLWidget *widget = new QGLWidget(QGLFormat(QGL::SampleBuffers));
widget->makeCurrent();
Scene scene(1024,768);
GraphicsView view;
view.setViewport(widget);
view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
view.setScene(&scene);
view.resize(800, 600);
view.show();
return app.exec();
}
Scene.h
#ifndef PROTOTYPES_SCENE_H
#define PROTOTYPES_SCENE_H
#include <QGraphicsScene>
class QTimer;
class Scene : public QGraphicsScene {
Q_OBJECT
public:
Scene(int width, int height);
protected:
QTimer *m_timer;
void drawBackground(QPainter *painter, const QRectF &rect) override;
};
#endif //PROTOTYPES_SCENE_H
Scene.cpp
#include "Scene.h"
#include <QPainter>
#include <QDebug>
#include <QTimer>
Scene::Scene(int width, int height)
{
setSceneRect(0,0,width, height);
//m_timer = new QTimer(this);
//m_timer->setInterval(20);
//connect(m_timer, SIGNAL(timeout()), this, SLOT(update()));
//m_timer->start();
}
void Scene::drawBackground(QPainter *painter, const QRectF &rect)
{
qDebug() << "DrawBackground";
}
GraphicsView.h
#ifndef PROTOTYPES_GRAPHICSVIEW_H
#define PROTOTYPES_GRAPHICSVIEW_H
#include <QGraphicsView>
class GraphicsView : public QGraphicsView {
public:
GraphicsView();
protected:
void resizeEvent(QResizeEvent *event) override;
};
#endif //PROTOTYPES_GRAPHICSVIEW_H
GraphicsView.cpp
#include "GraphicsView.h"
#include <QResizeEvent>
#include <QDebug>
void GraphicsView::resizeEvent(QResizeEvent *event)
{
if (scene()) {
qDebug() << "Set Scene Rect " << event->size();
scene()->setSceneRect(QRect(QPoint(0, 0), event->size()));
}
QGraphicsView::resizeEvent(event);
}
GraphicsView::GraphicsView()
{
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
}
根据评论,QGLWidget
已被标记为过时一段时间并附带警告...
This class is obsolete. It is provided to keep old source code
working. We strongly advise against using it in new code.
解决方法是改用QOpenGLWidget
。
我有一个功能完备的应用程序,它利用 QGraphicsView
+ QGLWidget
和 QGraphicsScene
通过用户交互绘制 3D 场景。
Qt5 的 Boxes 示例中解释了这个概念。
自更新到 Qt 5.12 后,该应用程序不再运行。除了我已经修复的其他一些小问题,现在我已经设置了所有内容,但是视口没有显示任何内容。
我创建了一个最小概念程序,它创建了一个 QGraphicsView
,一个 QGLWidget
作为视口,以及一个 QGraphicsScene
派生的 class 来绘制视口。
我设置了所有内容,但未调用 QGraphicsScene::DrawBackground()
函数。
有趣的是,该应用程序在 Qt 5.6 中运行良好,但在 5.12 中却不行。
两个版本之间有什么变化?
以下是示例应用程序:
CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(Prototypes)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -Wall)
find_package(Qt5 REQUIRED COMPONENTS Core Widgets OpenGL)
add_executable(Prototypes main.cpp GraphicsView.cpp GraphicsView.h Scene.cpp Scene.h)
target_link_libraries(Prototypes Qt5::Core Qt5::OpenGL Qt5::Widgets)
main.cpp
#include "GraphicsView.h"
#include "Scene.h"
#include <QApplication>
#include <QGLWidget>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGLWidget *widget = new QGLWidget(QGLFormat(QGL::SampleBuffers));
widget->makeCurrent();
Scene scene(1024,768);
GraphicsView view;
view.setViewport(widget);
view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
view.setScene(&scene);
view.resize(800, 600);
view.show();
return app.exec();
}
Scene.h
#ifndef PROTOTYPES_SCENE_H
#define PROTOTYPES_SCENE_H
#include <QGraphicsScene>
class QTimer;
class Scene : public QGraphicsScene {
Q_OBJECT
public:
Scene(int width, int height);
protected:
QTimer *m_timer;
void drawBackground(QPainter *painter, const QRectF &rect) override;
};
#endif //PROTOTYPES_SCENE_H
Scene.cpp
#include "Scene.h"
#include <QPainter>
#include <QDebug>
#include <QTimer>
Scene::Scene(int width, int height)
{
setSceneRect(0,0,width, height);
//m_timer = new QTimer(this);
//m_timer->setInterval(20);
//connect(m_timer, SIGNAL(timeout()), this, SLOT(update()));
//m_timer->start();
}
void Scene::drawBackground(QPainter *painter, const QRectF &rect)
{
qDebug() << "DrawBackground";
}
GraphicsView.h
#ifndef PROTOTYPES_GRAPHICSVIEW_H
#define PROTOTYPES_GRAPHICSVIEW_H
#include <QGraphicsView>
class GraphicsView : public QGraphicsView {
public:
GraphicsView();
protected:
void resizeEvent(QResizeEvent *event) override;
};
#endif //PROTOTYPES_GRAPHICSVIEW_H
GraphicsView.cpp
#include "GraphicsView.h"
#include <QResizeEvent>
#include <QDebug>
void GraphicsView::resizeEvent(QResizeEvent *event)
{
if (scene()) {
qDebug() << "Set Scene Rect " << event->size();
scene()->setSceneRect(QRect(QPoint(0, 0), event->size()));
}
QGraphicsView::resizeEvent(event);
}
GraphicsView::GraphicsView()
{
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
}
根据评论,QGLWidget
已被标记为过时一段时间并附带警告...
This class is obsolete. It is provided to keep old source code working. We strongly advise against using it in new code.
解决方法是改用QOpenGLWidget
。