在基类中访问 QPainter

Posted

技术标签:

【中文标题】在基类中访问 QPainter【英文标题】:Accessing a QPainter in base class 【发布时间】:2012-12-15 23:09:49 【问题描述】:

我正在创建使用 QWidgets 绘制事件绘制网格的小部件类。我的基类 BaseRenderArea 包含这个方法:

//draws a list of guesses in the grid
void BaseRenderArea::drawGuesses(const QList <GuessPoint> &list, QPainter *painter)

    //QPainter painter1(this);

    QPen currentPen = painter->pen();

    painter->setPen(QString("red"));

    for(int i=0;i<list.size();i++)
    
        GuessPoint gp = list.at(i);

        switch(gp.m_type)
        
        case GuessPoint::Miss:
            drawMiss(gp.m_row, gp.m_col, painter);
            break;
        case GuessPoint::Dead:
            drawDead(gp.m_row, gp.m_col, painter);
            break;
        case GuessPoint::Hit:
            drawHit(gp.m_row, gp.m_col, painter);
            break;
        default:
            ;
        
    

    painter->setPen(currentPen);


我从派生类小部件的paintEvent中调用这个方法。

//the paint event
//uses the base class to draw the texts and
//the grid
//and then draws the guesses made until now
//as well as the score for each choice of the computer
void DebugRenderArea::paintEvent(QPaintEvent *event)

    QPainter painter(this);

    BaseRenderArea::paintEvent(event);

    //to do: draw guesses
    drawGuesses(&painter);

    //draw scores
    //drawScores(&painter);


派生类中的drawGuesses方法实现如下:

//draws the guesses made until this moment
void DebugRenderArea::drawGuesses(QPainter *painter)

    QList <GuessPoint> list = m_logic->getListGuesses();
    BaseRenderArea::drawGuesses(list,painter);


这种方法在第二行画家的 BaseRenderArea::drawGuesses 中给我一个分段错误->setPen....

如果我使用以下代码更改 BaseRenderArea::drawGuesses(不重用在派生类中创建的 QPainter,而是创建新的 QPainter):

//draws a list of guesses in the grid
void BaseRenderArea::drawGuesses(const QList <GuessPoint> &list, QPainter *painter)

    QPainter painter1(this);

    QPen currentPen = painter1.pen();

    painter1.setPen(QString("red"));

    for(int i=0;i<list.size();i++)
    
        GuessPoint gp = list.at(i);

        switch(gp.m_type)
        
        case GuessPoint::Miss:
            drawMiss(gp.m_row, gp.m_col, &painter1);
            break;
        case GuessPoint::Dead:
            drawDead(gp.m_row, gp.m_col, &painter1);
            break;
        case GuessPoint::Hit:
            drawHit(gp.m_row, gp.m_col, &painter1);
            break;
        default:
            ;
        
    

    painter1.setPen(currentPen);


一切正常。我的问题为什么?在基类的方法中使用派生类的paintEvent中创建的QPainter怎么办?

【问题讨论】:

setpen() 应该得到一个 QColor 作为参数,你不应该写 Qt::red 而不是 QString("red") 吗?在第一种情况下,您通过给它一个对 DebugRenderArea 实例的引用来初始化 QPainter,在第二种情况下,给它一个对 BaseRenderArea 实例的引用,这就是您想要的吗? 该代码也适用于 QString("red")。在这种情况下,我认为除了一次在基类中创建 QPainter 而另一次在派生类中创建之外,存在一个相同的对象。我不确定这应该怎么做。你有什么建议吗? 【参考方案1】:

documentation 表示您不能在同一个绘图设备上拥有 2 个活动的QPainters。

所以,因为BaseRenderArea::paintEvent 可能正在创建自己的QPainter,它可能使您之前在DebugRenderArea::paintEvent 中创建的那个无效。

您可以简单地重新排列这两行:

BaseRenderArea::paintEvent(event);

QPainter painter(this);

【讨论】:

谢谢。那确实奏效了。所以Qt明白BaseRenderArea::paintEvent中创建的QPainter和DebugRenderArea::paintEvent中创建的QPainter指的是同一个widget-

以上是关于在基类中访问 QPainter的主要内容,如果未能解决你的问题,请参考以下文章

在基类和派生类中使用基类的装饰器

如何在基类中实例化泛型类型?

不能在基类中声明 Signal

在基类中存储指向派生类函数的指针

JAXB 可以在基类中初始化值吗?

在基类中编写需要在子类中覆盖的方法实现?