I am currently porting an open-source solution (Albatross ATM solution http://www.albatross.aero/) from Qt3 to Qt5. Albatross is an air traffic viewer which requires very good performances. There are various issues that I have been able to manage but not the display part.
The display architecture rests on a bitblt
command which firstly copies one pixmap into another and finally copies the pixmap to the screen.
Here is the Qt3 display code (working and performant):
void CAsdView::paintEvent ( QPaintEvent * Event)
{
QRect rcBounds=Event->rect();
QPainter tmp;
for (int lay=0;lay<(int)m_RectTable.size();lay++) //For each drawing layer (there are 3)
{
if (!m_RectTable[lay].isEmpty())
{
if (lay!=0)
bitBlt(m_BitmapTable[lay],m_RectTable[lay].left(),m_RectTable[lay].top(),m_BitmapTable[lay-1],m_RectTable[lay].left(),m_RectTable[lay].top(),m_RectTable[lay].width(),m_RectTable[lay].height(),CopyROP); //m_BitmapTable is a QVector< QPixmap* >, m_RectTable is a QVector<QRect>
tmp.begin(m_BitmapTable[lay]);
if (lay==0)
tmp.fillRect(m_RectTable[lay], *m_pBrush);
OnDraw(&tmp,lay);
tmp.end();
m_RectTable[lay].setRect(0,0,-1,-1);
}
}
bitBlt(this, rcBounds.left(), rcBounds.top(),m_BitmapTable[m_LayerNb-1],rcBounds.left(), rcBounds.top(),rcBounds.width(), rcBounds.height(), CopyROP);
}
I have tried replacing bitblt
by drawPixmap
but the performance are very bad since I have to display very often the screen.
Here is the new Qt5 code :
void CAsdView::paintEvent ( QPaintEvent * Event)
{
QRect rcBounds=Event->rect();
QPainter tmp;
for (int lay=0;lay<(int)m_RectTable.size();lay++)
{
if (!m_RectTable.at(lay).isEmpty())
{
tmp2.begin(m_BitmapTable[lay]);
if (lay != 0)
{
tmp.drawPixmap(m_RectTable[lay].left(), m_RectTable[lay].top(), *m_BitmapTable.at(lay - 1), m_RectTable[lay].left(), m_RectTable[lay].top(), m_RectTable[lay].width(), m_RectTable[lay].height());//TOCHECK
m_BitmapTable[lay] = m_BitmapTable[lay - 1].copy(m_RectTable[lay]);
}
if (lay==0)
tmp.fillRect(m_RectTable.at(lay), *m_pBrush);
OnDraw(&tmp, lay);
tmp.end();
m_RectTable[lay].setRect(0, 0, -1, -1);
}
}
tmp.begin(this);
tmp.drawPixmap(rcBounds.left(), rcBounds.top(), m_BitmapTable.at(m_LayerNb - 1), rcBounds.left(), rcBounds.top(), rcBounds.width(), rcBounds.height());
tmp.end();
}
For the layers, there are 3 layers. The layer 0 is the deepest (background), the layer 2 is the highest. This configuration is used in order to be sure that the air traffic is always displayed on top of the screen.
The OnDraw method draws, depending on the layer, the elements that have changed since the last paintEvent
Q: Do you have any idea on how I could improve this paintEvent
method in order to geta good behaviour back and have good performances again with Qt5 ?
I found the problem here.
drawPixmap/drawImage is cleary the best alternative to bitblt in Qt4/Qt5. Unfortunately I had some issues with the scaled() method of QPixmap (used in another piece of code not shown here...)which returned me bad results. I had to go from pixmap.resize() to pixmap.scaled() and I made a mistake here.
I changed it and now I clearly have a pretty good result. So for those like me who are still wondering, the best alternative in Qt for Bitblt is drawPixmap with a QPainter.