【问题标题】:zoom and pan in a widget in pyqt在 pyqt 中缩放和平移小部件
【发布时间】:2020-11-19 21:44:39
【问题描述】:

我制作了一个自定义滚动小部件并实现了缩放和平移。现在的问题是它不会放大子小部件,并且平移不会从当前位置平移,而是滚动回初始位置。 (注:平移使用鼠标中键,放大和缩小使用ctrl+滚轮)

import sys

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import Qt, QSize, QPoint
from PyQt5 import QtWidgets
from PyQt5.QtGui import *

from PyQt5.QtWidgets import *


class ScrollArea(QWidget):

    _style = '''
            QScrollArea{
                background: white;
            }
            
            QScrollBar:handle{
                background: gray;
                max-width: 20px;
                color:green;
            
            }
            '''

    factor = 1.5

    def __init__(self, parent=None):
        super(ScrollArea, self).__init__()

        self.v_layout = QVBoxLayout(self)
        self.v_layout.setContentsMargins(0, 0, 0, 0)
        self.v_layout.setSpacing(0)

        self.container_widget = QWidget()

        # Scroll Area Properties
        self.scroll = QScrollArea()
        self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scroll.setWidgetResizable(False)
        self.scroll.setWidget(self.container_widget)
        self.scroll.setStyleSheet(ScrollArea._style)

        l = QLabel('Hello world', self.container_widget)
        l.setStyleSheet('color: red; font-size: 30px')

      
        self.container_widget.setGeometry(0, 0, self.width(), self.height())


        self.v_layout.addWidget(self.scroll)
        self.setLayout(self.v_layout)

        self._zoom = 0
        self.mousepos = QPoint(0, 0)
        self.setMouseTracking(True)
        self.showMaximized()

    def fitInView(self, scale=True):
        rect = QtCore.QRectF(self._photo.pixmap().rect())
        if not rect.isNull():
            self.setSceneRect(rect)
            if self.hasPhoto():
                unity = self.transform().mapRect(QtCore.QRectF(0, 0, 1, 1))
                self.scale(1 / unity.width(), 1 / unity.height())
                viewrect = self.viewport().rect()
                scenerect = self.transform().mapRect(rect)
                factor = min(viewrect.width() / scenerect.width(),
                             viewrect.height() / scenerect.height())
                self.scale(factor, factor)
            self._zoom = 0

    def wheelEvent(self, wheel_event):

        if wheel_event.modifiers() == Qt.ControlModifier:
            delta = wheel_event.angleDelta().y()
            if delta > 0:
                self.zoom_in()

            elif delta < 0:
                self.zoom_out()

        else:
            return super().wheelEvent(wheel_event)

    def mousePressEvent(self, event):
        cursor = self.container_widget.cursor().pos()
        print(cursor)
        if event.button() == Qt.MidButton:
            self.setCursor(Qt.OpenHandCursor)

        super(ScrollArea, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):

        delta = event.localPos() - self.mousepos

        # panning area
        if event.buttons() == Qt.MidButton:
            h = self.scroll.horizontalScrollBar().value()
            v = self.scroll.verticalScrollBar().value()

            self.scroll.horizontalScrollBar().setValue(int(h - delta.x()))
            self.scroll.verticalScrollBar().setValue(int(v - delta.y()))

        self.mousepos = event.localPos()

        super(ScrollArea, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):

        self.unsetCursor()
        self.mousepos = event.localPos()
        super(ScrollArea, self).mouseReleaseEvent(event)

    def resizeEvent(self, event):
        self.container_widget.resize(self.width(), self.height())

        super(ScrollArea, self).resizeEvent(event)

    def resize_container(self, option):

        option = int(option)

        if option == 0:
            self.container_widget.resize(self.width()+50, self.height())

        elif option == 1:
            self.container_widget.resize(self.width()+50, self.height())

        elif option == 2:
            self.container_widget.resize(self.width()+50, self.height()+50)

    @QtCore.pyqtSlot()
    def zoom_in(self):
        self.container_widget.setGeometry(200, 200, self.container_widget.width() + 4,
                                          self.container_widget.height() + 4)

    @QtCore.pyqtSlot()
    def zoom_out(self):
   
        self.container_widget.setGeometry(0, 0, self.container_widget.width() - 4,
                                          self.container_widget.height() - 4)


if __name__ == '__main__':
    a = QtWidgets.QApplication(sys.argv)
    q = ScrollArea()
    q.show()
    sys.exit(a.exec_())

一旦你执行,你会发现标签并没有改变它的大小,并且在平移一次后再次平移会导致奇怪的行为。

注意:我发现缩放只是调整容器的大小,有没有办法可以正确放大和缩小

【问题讨论】:

  • 您想通过缩放达到什么效果?字体大小应该增加吗?
  • @ChristianKarcher 有一些其他小部件以及容器内的标签。我希望容器内的所有小部件都被放大,例如,当放大标签的字体大小时应该增加。
  • 我在原始答案中添加了通过字体大小调整进行标签缩放的建议。也许这适合您的需求?

标签: python pyqt pyqt5


【解决方案1】:

修复平移功能的一种方法是为初始鼠标中键添加鼠标位置更新:

def mousePressEvent(self, event):
    cursor = self.container_widget.cursor().pos()
    print(cursor)
    if event.button() == Qt.MidButton:
        self.setCursor(Qt.OpenHandCursor)
        self.mousepos = event.localPos() # <== add this

否则,mouseMoveEvent 中的增量是根据旧数据计算的,从而导致“奇怪”的行为。

对于zooming part,我可以通过增加标签的字体大小来想一个“解决方法”:

在初始化部分创建一个标签和一个字体大小属性:

self.label = QLabel('Hello world', self.container_widget)
self.font_size = 30
self.label.setStyleSheet(f'color: red; font-size: {self.font_size}px')

用以下“字体大小修饰符”替换缩放功能:

    @QtCore.pyqtSlot()
    def zoom_in(self):
        self.font_size = min(1000, self.font_size + 1)
        self.label.setStyleSheet(f'color: red; font-size: {self.font_size}px')
        self.label.adjustSize()

    @QtCore.pyqtSlot()
    def zoom_out(self):
        self.font_size = max(2, self.font_size - 1)
        self.label.setStyleSheet(f'color: red; font-size: {self.font_size}px')
        self.label.adjustSize()

这至少会造成放大的错觉。

【讨论】:

  • 谢谢,我解决了平移问题,但缩放仍然不起作用。我尝试检查该问题中给出的链接,但没有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-08
  • 2013-12-12
相关资源
最近更新 更多