2016-07-31 7 views
0

Ich verwende QPixmap als Render-Cache. Dies führt zu Skalierungsproblemen bei Verwendung mehrerer Bildschirme mit unterschiedlichen Skalierungsfaktoren (getestet unter Windows).Bei Verwendung von QPixmap als Rendering-Cache korrekte GUI-Skalierung beibehalten

Ich habe ein kleines Widget zu Demonstrationszwecken geschrieben. Das Zeichnen kann entweder direkt oder auf einer QPixmap erfolgen, die dann auf dem Gerät gezeichnet wird. (In der realen Anwendung wird die Pixmap zwischengespeichert, um unnötige Paint() - Aufrufe zu vermeiden. Aber das ist der Einfachheit halber hier weggelassen). Falls jemand will das volle Beispiel: https://github.com/the-yeti/qpixmap-scaling-demo

void RenderWidget::paintEvent(QPaintEvent *event) 
{ 
    if (m_usePixmap) { 
     QPixmap pm(width(), height()); 
     paint(&pm); 
     QPainter(this).drawPixmap(0, 0, pm); 
    } else { 
     paint(this); 
    } 
} 

void RenderWidget::paint(QPaintDevice *pd) 
{ 
    QPainter p(pd); 
    p.fillRect(0, 0, pd->width(), pd->height(), QColor(192, 192, 192)); 

    QFontMetrics fm = p.fontMetrics(); 
    int h = fm.height(); 
    for (int i=1; i<6; i++) { 
     p.drawLine(0, i*h, width(), i*h); 
    } 
    p.drawText(4, fm.ascent(), m_usePixmap ? "using QPixmap draw" : "using direct draw"); 
    p.drawText(8, h+ fm.ascent(), QString("font pointsize: %1").arg(p.font().pointSize())); 
    p.drawText(8, 2*h + fm.ascent(), QString("font height: %1").arg(h)); 
    p.drawText(8, 3*h + fm.ascent(), QString("physicalDpiY: %1").arg(pd->physicalDpiY())); 
    p.drawText(8, 4*h + fm.ascent(), QString("logicalDpiY: %1").arg(pd->logicalDpiY())); 
} 

Zur Demonstration habe ich zwei Instanzen der Widgets Seite an Seite angeordnet. Links ist direkt gezeichnet, rechts verwendet die QPixmap.

Alles funktioniert gut auf einem einzigen Monitor.

enter image description here

Wenn jedoch I mehreren Bildschirmen mit verschiedenen Skalierungen haben, unterscheiden sich die Ergebnisse. Das direkte Zeichnen passt sich korrekt an und rendert bei der aktuellen Bildschirmauflösung. Die Pixmap wird immer mit der primären Bildschirmauflösung gerendert.

Fenster auf Sekundär Bildschirm mit 150% Skalierung, Hauptbildschirm mit 100% Skalierung:

enter image description here

Bisher das ist verständlich. Die Pixmap kennt keine Bildschirme, daher ist es sinnvoll, dass sie die Skalierung des primären Bildschirms verwendet. Meine Frage ist jetzt:

Gibt es eine Möglichkeit, die Skalierung des Pixmap-Renderings abzustimmen?

Ich fühle mich wie ich die logicalDpiX/Y der Pixmap ändern sollte. Aber das scheint ab Qt 5.6.1 unmöglich zu sein.

Antwort

0

Eine mögliche Problemumgehung wäre eine Neuskalierung der Schriftgröße anstelle der logicalDpiY. Zumindest scheint dies für Schriften zu funktionieren. Nicht sicher, ob man auch andere Einstellungen des Malers ändern müsste, wie z. B. Linienbreite.

void RenderWidget::paint(QPaintDevice *pd) 
{ 
    QPainter p(pd); 

    if (m_usePixmap) { 
     QWidget *w = this; // widget on which the pixmap should be drawn later on 

     if (pd->logicalDpiY() != w->logicalDpiY()) { 
      // workaround the scaling by adapting the font 
      QFont f(p.font()); 
      f.setPointSizeF((f.pointSizeF() * w->logicalDpiY())/pd->logicalDpiY()); 
      p.setFont(f); 
     } 
    } 

    p.fillRect(0, 0, pd->width(), pd->height(), QColor(192, 192, 192)); 

    ... 
} 

Wie oben: Fenster auf Sekundär Bildschirm mit 150% Skalierung, Hauptbildschirm mit 100% Skalierung:

enter image description here

Hinweis: die GitHub Repo mit diesem Code aktualisiert: https://github.com/the-yeti/qpixmap-scaling-demo

Verwandte Themen