Aktualnie przesyłam rozwiązanie typu open-source (Albatross ATM solution http://www.albatross.aero/) z Qt3 na Qt5. Albatross to przeglądarka ruchu lotniczego, która wymaga bardzo dobrych osiągów. Są różne problemy, którymi mogłem zarządzać, ale nie część wyświetlana.Qt: Alternatywa dla BitBlt w Qt5 Windows
Architektura wyświetlania opiera się na poleceniu bitblt
, które najpierw kopiuje jedną piksel na inną i ostatecznie kopiuje piksel na ekran.
Oto kod wyświetlacz Qt3 (pracę i wydajnych):
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);
}
Próbowałem zastępując bitblt
przez drawPixmap
ale wydajność są bardzo złe, ponieważ mam bardzo często, aby wyświetlić ekran.
Oto nowy kod Qt5:
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();
}
dla warstw, istnieją 3 warstwy. Warstwa 0 jest najgłębsza (tło), warstwa 2 jest najwyższa. Ta konfiguracja jest używana w celu upewnienia się, że ruch lotniczy jest zawsze wyświetlany na górze ekranu.
Sposób OnDraw losowania, w zależności od warstwy, elementy, które uległy zmianie od czasu ostatniego paintEvent
Q: Czy masz jakiś pomysł, jak mogę poprawić tę metodę paintEvent
w celu odzyskać dobre zachowanie i znów mieć dobre wyniki z Qt5?
dlaczego potrzebny był pośredni etap bitmapy? Aby zapewnić przejrzystość? – UmNyobe
@UmNyobe To zawsze przechowuje Pixmap z ostatniej warstwy, aby mieć w pamięci całą zawartość ekranu. W ten sposób unika się rozwiązania polegającego jedynie na zachowaniu elementu ekranu, który się zmienił. Jeśli to rozwiązanie zostało użyte, mogą wystąpić pewne problemy z wyświetlaniem i odświeżaniem między warstwami (np. Wyświetlanie warstwy 1 po warstwie 2 i utrata cennych informacji). Zachowanie zawsze całej warstwy pozwala nam upewnić się, że to, co jest rysowane, jest poprawne. –