Сохранение позиции просмотра / прокрутки в QGraphicsView при обмене изображениями - PullRequest
1 голос
/ 20 января 2012

У меня проблемы с масштабированием изображений TIFF, загруженных в QGraphicsView с помощью QGraphicsPixmapItem.

. Проблема заключается в том, чтобы поддерживать качество изображения и скорость масштабирования, которая не мешает работе приложения.,Для начала я просто заменял изображение масштабированным QPixmap - я использовал Qt.FastTransformation, пока пользователь удерживал горизонтальный слайдер, а затем, когда слайдер был освобожден, снова заменил растровое изображение на другое растровое растровое изображение, используя Qt.SmoothTransformation.Это дало хорошее качество увеличенного изображения, но масштабирование было резким после того, как размер изображения начал увеличиваться до размера, превышающего его первоначальный размер;масштабирование изображения было нормальным.

Использование QTransform.fromScale () в QGraphicsView дает намного более плавное масштабирование, но изображение более низкого качества, даже при применении .setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform | QPainter.HighQualityAntialiasing) к QGraphicsView.

MyПоследний подход заключается в объединении двух методов и использовании QTransform на QGraphicsView для плавного масштабирования, но когда пользователь отпускает ползунок, замените изображение в QGraphicsView на растровое растровое изображение.Это прекрасно работает, но позиция в представлении потеряна - пользователь увеличивает одну область, и, поскольку масштабированное растровое изображение больше, представление переходит в другое место, когда ползунок отпущен и масштабированное растровое изображение более высокого качества заменяет предыдущее изображение.

Я полагал, что, поскольку отношение высоты к ширине одинаково на обоих изображениях, я мог бы взять проценты полос прокрутки перед заменой изображения и применить те же проценты после замены, и все должно работать нормально.В основном это работает хорошо, но бывают моменты, когда вид «скачет» после замены изображения.

Я почти уверен, что здесь я делаю что-то совершенно не так.Кто-нибудь знает лучший способ сделать это, или кто-то может найти что-то в приведенном ниже коде, который может вызвать этот прыжок?

Это код для сохранения / восстановления местоположения полосы прокрутки.Это методы подкласса QGraphicsView:

def store_scrollbar_position(self):
    x_max = self.horizontalScrollBar().maximum()
    if x_max:
        x = self.horizontalScrollBar().sliderPosition()
        self.scroll_x_percentage = x * (100 / float(x_max))

    y_max = self.verticalScrollBar().maximum()
    if y_max:
        y = self.verticalScrollBar().sliderPosition()
        self.scroll_y_percentage = y * (100 / float(y_max))


def restore_scrollbar_position(self):
    x_max = self.horizontalScrollBar().maximum()
    if self.scroll_x_percentage and x_max:
        x = x_max * (float(self.scroll_x_percentage) / 100)
        self.horizontalScrollBar().setSliderPosition(x)

    y_max = self.verticalScrollBar().maximum()
    if self.scroll_y_percentage and y_max:
        y = y_max * (float(self.scroll_y_percentage) / 100)
        self.verticalScrollBar().setSliderPosition(y)

А вот как я делаю масштабирование.self.imageFile - это QPixmap, а self.image - это мое QGraphicsPixmapItem.Опять же часть подкласса QGraphicsView.Метод привязан к движению ползунка с параметром highQuality, установленным на False.Он снова вызывается при отпускании слайдера с highQuality как True для замены изображения.

def setImageScale(self, scale=None, highQuality=True):
    if self.imageFile.isNull():
        return
    if scale is None:
        scale = self.scale
    self.scale = scale

    self.image.setPixmap(self.imageFile)
    self.scene.setSceneRect(self.image.boundingRect())
    self.image.setPos(0, 0)
    if not highQuality:
        self.setTransform(QTransform.fromScale(self.scaleFactor, self.scaleFactor))
        self.store_scrollbar_position()
    else:
        self.image.setPixmap(self.imageFile.scaled(self.scaleFactor * self.imageFile.size(),
                                                   Qt.KeepAspectRatio, Qt.SmoothTransformation))
        self.setTransform(self.transform)
        self.scene.setSceneRect(self.image.boundingRect())
        self.image.setPos(0, 0)
        self.restore_scrollbar_position()
    return

Любая помощь будет принята с благодарностью.Теперь я начинаю расстраиваться из-за этого.

1 Ответ

1 голос
/ 09 марта 2012

Я нашел решение, которое работает лучше, чем код, который я впервые опубликовал. Это все еще не идеально, но значительно улучшилось. На всякий случай, если кто-то еще пытается решить подобную проблему ...

При настройке изображения низкого качества я вызываю этот метод, добавленный в мой QGraphicsView:

def get_scroll_state(self):
    """
    Returns a tuple of scene extents percentages. 
    """
    centerPoint = self.mapToScene(self.viewport().width()/2,
                                  self.viewport().height()/2)
    sceneRect = self.sceneRect()
    centerWidth = centerPoint.x() - sceneRect.left()
    centerHeight = centerPoint.y() - sceneRect.top()
    sceneWidth =  sceneRect.width()
    sceneHeight = sceneRect.height()

    sceneWidthPercent = centerWidth / sceneWidth if sceneWidth != 0 else 0
    sceneHeightPercent = centerHeight / sceneHeight if sceneHeight != 0 else 0
    return sceneWidthPercent, sceneHeightPercent

Это сохраняется в self.scroll_state. При настройке изображения высокого качества я вызываю другую функцию, чтобы восстановить проценты, использованные в предыдущей функции.

def set_scroll_state(self, scroll_state):
    sceneWidthPercent, sceneHeightPercent = scroll_state
    x = (sceneWidthPercent * self.sceneRect().width() +
         self.sceneRect().left())
    y = (sceneHeightPercent * self.sceneRect().height() +
         self.sceneRect().top())
    self.centerOn(x, y)

Устанавливает центральное положение в то же положение (в процентном отношении), в котором я находился до смены изображения.

...