Qt的paintEvent崩溃

3
我正在尝试在我的小部件上绘制简单的面板。
当我试图自动化此过程时,我的paintEvent崩溃了。我认为这是由于循环内部的问题引起的,我是对的吗?有没有其他方法来绘制它?
void Widget::paintEvent(QPaintEvent *event)
{
QPixmap myPix( QSize(20,20) );
QPainter painter(this);
for(int i = 0; i < 100; i+5){
    painter.drawLine(QPointF(i,0),QPointF(i,max));
}
this->setPixmap(myPix);
}

你是否定义了 max,或者不小心将函数地址传递给了 QPointF? - RobH
3
我认为 this->setPixmap(myPix); 会产生一个递归调用你的绘图事件。 - vahancho
是的,max只是一些浮点值,我在从文本文件加载数据时设置它,它只是小部件的最大高度。 我删除了使用setPixmap的那行代码,但没有帮助(通常我也删除了myPix的声明 :) ) - Tatarinho
@Chernobyl,很好,但你的回答似乎没有解释为什么这段代码会崩溃。 - vahancho
@vahancho 为什么?我的回答的第一行是 i+=5 而不是 i+5,循环是错误的。OP 同意这个吗? - Jablonski
显示剩余2条评论
1个回答

7

你的for循环有误,导致程序崩溃(我相信这不是你的错)。应该像这样编写:

for(int i = 0; i < 100; i+=5){
    p.drawLine(QPointF(i,0),QPointF(i,max));
}

也就是说,通过增量的赋值来完成任务并正确结束。

顺便提一下,我建议使用 drawPixmap() 而不是 setPixmap()。但是,setPixmap() 不会导致无限递归,例如下面的代码可以正常工作。

//...
this->setPixmap(QPixmap("G:/2/qt.jpg"));
QLabel::paintEvent(event);

为什么?采用这种方法,永远不会产生无限递归(请参见此处):

如果您在可能从paintEvent()调用的函数中调用repaint(),则可能会出现无限递归。update()函数永远不会导致递归。

实际上,setPixmap()调用的是update()而不是repaint()。要证明这一点,请参见源代码:

setPixmap源码:

void QLabel::setPixmap(const QPixmap &pixmap)
{
    Q_D(QLabel);
    //...
    d->updateLabel();//what it does?
}

更新标签来源:

void QLabelPrivate::updateLabel()
{
    Q_Q(QLabel);
    //...
    q->updateGeometry();
    q->update(q->contentsRect());//not repaint

}

正如我所说,这不是一个错误,但我认为如果您使用QPainter完成所有需要的工作会更好。


可以运行了!我的天啊,为什么我自己没看出来。无论如何还是谢谢! - Tatarinho
我想知道是否有可能获取这样的板作为小部件的背景,而不是在paintEvent中重新绘制它? - Tatarinho
你说“我建议使用drawPixmap()而不是setPixmap()”,但在你的代码片段中,你有this->setPixmap(..).. 这有点令人困惑.. 那是一个错误吗? - thuga
@thuga 你可以看到,我的回答已经被编辑过了,你可以查看之前的版本(查看编辑历史记录),虽然语法不是很完美,但是很清晰。我没有注意到我的回答被错误地编辑了,所以我进行了修改。主要的想法是证明在paintEvent中使用setPixmap不会导致递归绘制。 - Jablonski
@Tatarinho 请注意查看此链接:http://qt-project.org/doc/qt-4.8/qwidget.html#paintEvent,特别关注setPalette方法。正如您所见,您应该使用paintEvent或setPixmap、setPalette等方法。 - Jablonski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接