关于C++ Gui Programming with Qt4第20章Vowel Cube的bug

CrazyWind 2011-03-18 08:48:27
运行时出现如下错误:
Starting E:\Qt\OpenGL\QtOpenGL\VowelCube-build-desktop\debug\VowelCube.exe...
ASSERT: "d" in file ..\..\include/QtCore/../../src/corelib/tools/qscopedpointer.h, line 112
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
QWidget::repaint: Recursive repaint detected
ASSERT: "d" in file ..\..\include/QtCore/../../src/corelib/tools/qscopedpointer.h, line 112
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
E:\Qt\OpenGL\QtOpenGL\VowelCube-build-desktop\debug\VowelCube.exe exited with code 3

不知道到底出了什么问题,恳请各位高人指点迷津,在下感激不尽!


#ifndef VOWELCUBE_H
#define VOWELCUBE_H

#include <QtCore>
#include <QtGui>
#include <QtOpenGL>

class VowelCube : public QGLWidget
{
Q_OBJECT

public:
VowelCube(QWidget *parent = 0);
~VowelCube();

protected:
void paintEvent(QPaintEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void wheelEvent(QWheelEvent *e);

private:
void createGradient();
void createGLObject();
void drawBackground(QPainter *painter);
void drawCube();
void drawLegend(QPainter *painter);

GLuint glObject;
QRadialGradient gradient;
GLfloat xrot, yrot, zrot;
GLfloat scaling;
QPoint lastPos;
};

#endif // VOWELCUBE_H



#include <cmath>
#include "vowelcube.h"

#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
#endif

VowelCube::VowelCube(QWidget *parent)
: QGLWidget(parent)
{
setFormat(QGLFormat(QGL::SampleBuffers));

xrot = -38.0;
yrot = -58.0;
zrot = 0.0;
scaling = 1.0;

createGradient();
createGLObject();
}

VowelCube::~VowelCube()
{
makeCurrent();
glDeleteLists(glObject, 1);
}

void VowelCube::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
drawBackground(&painter);
drawCube();
drawLegend(&painter);
}

void VowelCube::mousePressEvent(QMouseEvent *e)
{
lastPos = e->pos();
}

void VowelCube::mouseMoveEvent(QMouseEvent *e)
{
GLfloat dx = GLfloat(e->x() - lastPos.x()) / width();
GLfloat dy = GLfloat(e->y() - lastPos.y()) / height();
if (e->buttons() & Qt::LeftButton) {
xrot += 180 * dy;
yrot += 180 * dx;
update();
} else if (e->buttons() & Qt::RightButton) {
xrot += 180 * dy;
zrot += 180 * dx;
update();
}
lastPos = e->pos();
}

void VowelCube::wheelEvent(QWheelEvent *e)
{
double numDegrees = -e->delta() / 8.0;
double numSteps = numDegrees / 15.0;
scaling *= std::pow(1.125, numSteps);
update();
}

void VowelCube::createGradient()
{
gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
gradient.setCenter(0.45, 0.50);
gradient.setFocalPoint(0.40, 0.45);
gradient.setColorAt(0.0, QColor(105, 146, 182));
gradient.setColorAt(0.4, QColor(81, 113, 150));
gradient.setColorAt(0.8, QColor(16, 56, 121));
}

void VowelCube::createGLObject()
{
static const GLfloat vertex_list[8][3] = {{-1.0, -1.0, 1.0},
{1.0, -1.0, 1.0},
{1.0, 1.0, 1.0},
{-1.0, 1.0, 1.0},
{-1.0, -1.0, -1.0},
{1.0, -1.0, -1.0},
{1.0, 1.0, -1.0},
{-1.0, 1.0, -1.0}};

static const int vertex_index_list1[6] = {6, 7, 5, 4, 1, 0};
static const int vertex_index_list2[10] = {2, 6, 5, 1, 2, 3, 7, 4, 0, 3};


makeCurrent();
glShadeModel(GL_FLAT);

glObject = glGenLists(1);
glNewList(glObject, GL_COMPILE); {
qglColor(QColor(255, 239, 191));
glLineWidth(1.0);

glBegin(GL_LINES); {
for (int i = 0; i < 6; i++)
glVertex3fv(vertex_list[vertex_index_list1[i]]);
} glEnd();

glBegin(GL_LINE_LOOP); {
for (int i = 0; i < 10; i++)
glVertex3fv(vertex_list[vertex_index_list2[i]]);
} glEnd();
} glEndList();
}

void VowelCube::drawBackground(QPainter *painter)
{
painter->setPen(Qt::NoPen);
painter->setBrush(gradient);
painter->drawRect(rect());
}

void VowelCube::drawCube()
{
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);

glPushMatrix(); {
glLoadIdentity();
GLfloat x = 3.0 * GLfloat(width()) / height();
glOrtho(-x, x, -3.0, 3.0, 4.0, 15.0);

glMatrixMode(GL_MODELVIEW);
glPushMatrix(); {
glLoadIdentity();
glTranslatef(0.0, 0.0, -10.0);
glScalef(scaling, scaling, scaling);

glRotatef(xrot, 1.0, 0.0, 0.0);
glRotatef(yrot, 0.0, 1.0, 0.0);
glRotatef(zrot, 0.0, 0.0, 1.0);

glEnable(GL_MULTISAMPLE);

glCallList(glObject);

setFont(QFont("Times", 24));
qglColor(QColor(255, 223, 127));

renderText(1.0, 1.0, 1.0, QChar('a'));
renderText(-1.0, 1.0, 1.0, QChar('e'));
renderText(1.0, 1.0, -1.0, QChar('o'));
renderText(-1.0, 1.0, -1.0, QChar(0x00F6));
renderText(1.0, -1.0, 1.0, QChar(0x0131));
renderText(-1.0, -1.0, 1.0, QChar('i'));
renderText(1.0, -1.0, -1.0, QChar('u'));
renderText(-1.0, -1.0, -1.0, QChar(0x00FC));

glMatrixMode(GL_MODELVIEW);
} glPopMatrix();
glMatrixMode(GL_PROJECTION);
} glPopMatrix();
glPopAttrib();
}

void VowelCube::drawLegend(QPainter *painter)
{
const int Margin = 11;
const int Padding = 6;

QTextDocument textDocument;
textDocument.setDefaultStyleSheet("* { color: #FFEFEF }");
textDocument.setHtml("<h4 align=\"center\">Vowel Categories</h4>"
"<p align=\"center\"><table width=\"100%\">"
"<tr><td>Open:<td>a<td>e<td>o<td>ö"
"<tr><td>Close:<td>ı<td>i<td>u<td>ü"
"<tr><td>Front:<td>e<td>i<td>ö<td>ü"
"<tr><td>Back:<td>a<td>ı<td>o<td>u"
"<tr><td>Round:<td>o<td>ö<td>u<td>ü"
"<tr><td>Unround:<td>a<td>e<td>ı<td>i"
"</table>");
textDocument.setTextWidth(textDocument.size().width());

QRect rect(QPoint(0, 0), textDocument.size().toSize() + QSize(2 * Padding, 2 * Padding));
painter->translate(width() - rect.width() - Margin, height() - rect.height() - Margin);
painter->setPen(QColor(255, 239, 239));
painter->setBrush(QColor(255, 0, 0, 31));
painter->drawRect(rect);
painter->translate(Padding, Padding);
textDocument.drawContents(painter);
}



#include <QtGui/QApplication>
#include "vowelcube.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

if (!QGLFormat::hasOpenGL()) {
QMessageBox::warning(0, "Fatal Error!", "This system has no OpenGL support!");
return -1;
}

VowelCube w;
w.setWindowTitle(QObject::tr("Vowel Cube"));
w.setMinimumSize(200, 200);
w.resize(500, 500);
w.show();

return a.exec();
}
...全文
633 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
msccreater 2012-12-26
  • 打赏
  • 举报
回复
引用 11 楼 cymurs 的回复:
在窗口部件的构造函数中增加下面两行:
setAutoBufferSwap(false); setAutoFillBackground(false);
在paintEvent函数中增加: [align=center]painter.end(); drawCube();//原先的 painter.begin(this);……
经过测试,如果不注释掉setFormat(QGLFormat(QGL::SampleBuffers));是无法在windows下运行的 环境:win7 工具:QCreater2.6.1 based on 4.8.3
cymurs 2012-04-06
  • 打赏
  • 举报
回复
在窗口部件的构造函数中增加下面两行:
setAutoBufferSwap(false);
setAutoFillBackground(false);

在paintEvent函数中增加:
painter.end();
drawCube();//原先的
painter.begin(this);
drawLegend(&painter);
painter.end();//原先的
swapBuffers();

不必注释setFormat(QGLFormat(QGL::SampleBuffers));就可以在Windows 下运行出书中的效果。这也解决了“QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is active on the same device is not allowed.”——这个错误。
CrazyWind 2011-03-19
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 coblan 的回复:]

引用 4 楼 comfanter 的回复:
现在错误变成了
QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is active on the same device is not allowed.


这个问题我遇到过,这个例子我也弄过。。while a GL 2 paint engine ……
[/Quote]

谢谢8楼的回答,我修改了构造函数和paintEvent函数

VowelCube::VowelCube(QWidget *parent)
: QGLWidget(parent)
{
//setFormat(QGLFormat(QGL::SampleBuffers));

xrot = -38.0;
yrot = -58.0;
zrot = 0.0;
scaling = 1.0;

setAutoBufferSwap(false);
setAutoFillBackground(false);

createGradient();
createGLObject();
}



void VowelCube::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
//painter.begin(this);
drawBackground(&painter);
painter.end();
//painter.beginNativePainting();
drawCube();
//painter.endNativePainting();
painter.begin(this);
drawLegend(&painter);
painter.end();
swapBuffers();
}

现在程序能正常运行了,另外第一个painter.begin(this);是不需要的,这是我第一次发帖提问,感谢各位的帮助,特别感谢coblan!
coblan 2011-03-19
  • 打赏
  • 举报
回复
对了,记得按照书上说的,把 autofillbackground(false) 和 autoswapbuff(false)关掉,
代码最后 交换图形的buff。.....swapbuff()
coblan 2011-03-19
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 comfanter 的回复:]
现在错误变成了
QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is active on the same device is not allowed.
[/Quote]

这个问题我遇到过,这个例子我也弄过。。while a GL 2 paint engine 这个提示已经说得很清楚了;;
你的代码这样写:
void VowelCube::paintEvent(QPaintEvent *e)
{
QPainter painter
painter.begin(this);
drawBackground(&painter);
painter.end(); //这里把painter给deactive了,就不会在GL绘制的时候出现两个 painter engin了
drawCube();
painter.begin(this);
drawLegend(&painter);
painter.end();
}

CrazyWind 2011-03-18
  • 打赏
  • 举报
回复
用的是QtCreator.
Qt不是跨平台的吗,代码里面也没有和具体系统相关的东西,怎么回事呢?
等会儿我去linux下测试
残剑待飞雪 2011-03-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 comfanter 的回复:]

首先感谢你的第一个回答,软件有bug很正常啊,一个bug都没有的软件真是罕见,例如这个setFormat(QGL::DoubleBuffer | QGL::DepthBuffer);在BugTracker上有提交的,书上的这个例子配套代码编译后都不能运行,就算不是bug吧,我是初学者,这个问题无法解决,还希望有人能够帮忙解答,谢谢!
[/Quote]

其实我的话潜在意思就是:
在讲一件事情行不行时,不要一上来就想“这肯定不可能”
科学的态度应该是“以我们目前的水平,暂时还做不到”

另外看到了太多的BugTracker上提交的都是伪Bug.

QT的示例程序我在Linux下面才有编译过,都能通过。
Windows下面,不感冒,没测过。
欢迎各位大虾一起来看看。
  • 打赏
  • 举报
回复
楼主是在QtCreator下编译的吗
CrazyWind 2011-03-18
  • 打赏
  • 举报
回复
现在错误变成了
QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is active on the same device is not allowed.
CrazyWind 2011-03-18
  • 打赏
  • 举报
回复
setFormat(QGLFormat(QGL::SampleBuffers));
我把上面这一行注释了,程序就能运行了,虽然立方体没有显示出来,但这说明上面这个函数很可能存在bug
http://bugreports.qt.nokia.com/browse/QTBUG-14971?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel
CrazyWind 2011-03-18
  • 打赏
  • 举报
回复
首先感谢你的第一个回答,软件有bug很正常啊,一个bug都没有的软件真是罕见,例如这个setFormat(QGL::DoubleBuffer | QGL::DepthBuffer);在BugTracker上有提交的,书上的这个例子配套代码编译后都不能运行,就算不是bug吧,我是初学者,这个问题无法解决,还希望有人能够帮忙解答,谢谢!
残剑待飞雪 2011-03-18
  • 打赏
  • 举报
回复
若干年前,我遇到问题就说是别人的Bug,一直在证明自己是菜鸟。


说别人的东西是Bug请证明之。

16,213

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧