2016-07-31 8 views
0

Я использую QPixmap в качестве кеша рендеринга. Это вызывает проблемы масштабирования при использовании нескольких экранов с различными коэффициентами масштабирования (проверяется на окнах).Поддержание правильного масштабирования графического интерфейса при использовании QPixmap в качестве кэша рендеринга

Я написал небольшой виджет для демонстрационной цели. Рисование может быть выполнено непосредственно или на QPixmap, которое затем нарисовано на устройстве. (В реальном приложении pixmap кэшируется, чтобы предотвратить ненужные вызовы paint(), но это просто для простоты). В случае, если кто-то хочет получить полный пример: 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())); 
} 

Для демонстрации, я поместил два экземпляра виджета бок о бок. Левая строка прямо нарисована, справа используется QPixmap.

Все работает нормально на одном мониторе.

enter image description here

Однако, когда у меня есть несколько экранов с различными шероховатостями, результаты отличаются. Прямая прямая правильно адаптируется и делает рендеринг при текущем разрешении экрана. Радиус изображения всегда отображается в основном разрешении экрана.

Окно на вторичном экране с 150% масштабированием, основным экраном со 100% масштабированием:

enter image description here

До сих пор это понятно. Pixmap не знает о экранах, поэтому разумно, что он использует масштабирование основного экрана. Мой вопрос сейчас:

Есть ли способ настроить масштабирование рендеринга pixmap?

Я чувствую, что должен изменить logicalDpiX/Y из Pixmap. Но это кажется невозможным, как из Qt 5.6.1.

ответ

0

Возможным обходным решением было бы изменить масштаб шрифта вместо logicalDpiY. По крайней мере, это похоже на работу с шрифтами. Не уверен, что нужно будет изменить другие настройки живописи, например, ширину линии.

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)); 

    ... 
} 

Как указано выше: Окно на вторичном экране с 150% масштабированием, основным экраном со 100% масштабированием:

enter image description here

Примечание: обновлен GitHub репо с этим кодом: https://github.com/the-yeti/qpixmap-scaling-demo

 Смежные вопросы

  • Нет связанных вопросов^_^