python - 放大和缩小小部件

标签 python python-3.x pyqt pyqt5

如何在小部件上使用按键输入制作缩放效果?该小部件位于滚动区域内,并且有一些使用 QPainter 绘制的绘图会随着用户输入而变化。缩放会影响滚动条的长度,距离越近,滚动条越小。最小级别的缩放应该使滚动条与小部件区域一样大,这样小部件中的所有内容都可以被可视化。

MRE:

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QWidget
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter, QPen, QColor
import sys


class Diedrico(QWidget):
    def __init__(self, parent):
        super().__init__(parent)

    def paintEvent(self, event):
        qp = QPainter(self)
        qp.setPen(QPen(QColor(Qt.black), 5))
        qp.drawRect(500, 500, 1000, 1000)


class UiVentana(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(UiVentana, self).__init__(parent)
        self.resize(520, 520)
        self.widget_central = QtWidgets.QWidget(self)
        scrol = QtWidgets.QScrollArea(self.widget_central)
        scrol.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scrol.setGeometry(QtCore.QRect(10, 10, 500, 500))
        scrol.setWidgetResizable(False)

        contenido = QtWidgets.QWidget()
        contenido.setGeometry(QtCore.QRect(0, 0, 2000, 2000))
        scrol.setWidget(contenido)

        self.Diedrico = Diedrico(contenido)
        self.Diedrico.setGeometry(QtCore.QRect(0, 0, 2000, 2000))
        self.setCentralWidget(self.widget_central)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    ui = UiVentana()
    ui.show()
    sys.exit(app.exec_())

最佳答案

您为什么要重新发明轮子?不要想实现缩放功能的逻辑,而是使用已经实现的类。在这种情况下,一个好的选择是将 QGraphicsView 与 QGraphicsScene 结合使用:

注意:快捷键标准放大和缩小与 Ctrl + +Ctrl + -,分别。

from PyQt5 import QtCore, QtGui, QtWidgets


class Diedrico(QtWidgets.QWidget):
    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.black), 5)
        qp.setPen(pen)
        qp.drawRect(500, 500, 1000, 1000)


class UiVentana(QtWidgets.QMainWindow):
    factor = 1.5

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

        self._scene = QtWidgets.QGraphicsScene(self)
        self._view = QtWidgets.QGraphicsView(self._scene)

        self._diedrico = Diedrico()
        self._diedrico.setFixedSize(2000, 2000)
        self._scene.addWidget(self._diedrico)

        self.setCentralWidget(self._view)

        QtWidgets.QShortcut(
            QtGui.QKeySequence(QtGui.QKeySequence.ZoomIn),
            self._view,
            context=QtCore.Qt.WidgetShortcut,
            activated=self.zoom_in,
        )

        QtWidgets.QShortcut(
            QtGui.QKeySequence(QtGui.QKeySequence.ZoomOut),
            self._view,
            context=QtCore.Qt.WidgetShortcut,
            activated=self.zoom_out,
        )

    @QtCore.pyqtSlot()
    def zoom_in(self):
        scale_tr = QtGui.QTransform()
        scale_tr.scale(UiVentana.factor, UiVentana.factor)

        tr = self._view.transform() * scale_tr
        self._view.setTransform(tr)

    @QtCore.pyqtSlot()
    def zoom_out(self):
        scale_tr = QtGui.QTransform()
        scale_tr.scale(UiVentana.factor, UiVentana.factor)

        scale_inverted, invertible = scale_tr.inverted()

        if invertible:
            tr = self._view.transform() * scale_inverted
            self._view.setTransform(tr)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    ui = UiVentana()
    ui.show()
    sys.exit(app.exec_())

更新:

如果您想分别使用+- 进行放大和缩小,只需将快捷方式更改为:

QtWidgets.QShortcut(
    QtGui.QKeySequence(QtCore.Qt.Key_Plus), # <---
    self._view,
    context=QtCore.Qt.WidgetShortcut,
    activated=self.zoom_in,
)

QtWidgets.QShortcut(
    QtGui.QKeySequence(QtCore.Qt.Key_Minus), # <---
    self._view,
    context=QtCore.Qt.WidgetShortcut,
    activated=self.zoom_out,
)

关于python - 放大和缩小小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57713795/

相关文章:

python - 在 python 中打印一个字符串,用偏移量左对齐

python - 以编程方式指定 Django 模型属性

Python Google Drive API,上传内存中的数据而不是磁盘上的文件?

Python3 与输入函数和 CJK 的意外视觉交互

python - 如何以编程方式单击 QTreeWidgetItem

python - Nosetest 和 unittest.expectedFailures

python - 按月对分组

python-3.x - 如何使用 discord.py "temporary ban"某人?

python - emit() 如何知道在 PyQT 中使用哪个 SLOT?

python - 使用 Qt 和 Python 显示一系列缩略图的正确方法