有什么办法可以在 PyQt5 中显示 360 度图像 Python?

Is there any way to display a 360-degree image in PyQt5 Python?

我希望能够选择 360 度图像并在 PyQt5 中显示它 window 使其可以交互和移动,有什么方法可以做到这一点吗?我完成了选择文件的部分,但似乎无法在 Qlabel 中显示它。

我完成了选择文件的部分,但似乎无法在 Qlabel 中显示它。

我希望图片可以像 Facebook 上显示的 360 度图像那样进行交互

您不能为标签设置像素图,因为它会显示完整的图像。
相反,您需要创建自己的 QWidget,并通过覆盖 paintEvent(实际绘制图像)和鼠标事件进行交互来自己提供 "panning" 实现。

我做了一个非常基本的例子,它不支持缩放(这需要更多的计算)。我使用的源图取自here

.

它创建一个局部像素图,水平重复 3 次以确保您可以无限平移,使用 mouseMoveEvent 通过 QTimer 计算位置并将垂直位置限制为图像高度,同时重置每当 x 坐标超出图像宽度的一半时的水平位置。

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Panoramic(QtWidgets.QWidget):
    def __init__(self, imagePath):
        QtWidgets.QWidget.__init__(self)
        self.setCursor(QtCore.Qt.CrossCursor)
        # keep a reference of the original image
        self.source = QtGui.QPixmap(imagePath)
        self.pano = QtGui.QPixmap(self.source.width() * 3, self.source.height())
        self.center = self.pano.rect().center()
        # use a QPointF for precision
        self.delta = QtCore.QPointF()
        self.deltaTimer = QtCore.QTimer(interval=25, timeout=self.moveCenter)
        self.sourceRect = QtCore.QRect()
        # create a pixmap with three copies of the source;
        # this could be avoided by smart repainting and translation of the source
        # but since paintEvent automatically clips the painting, it should be
        # faster then computing the new rectangle each paint cycle, at the cost 
        # of a few megabytes of memory.
        self.setMaximumSize(self.source.size())
        qp = QtGui.QPainter(self.pano)
        qp.drawPixmap(0, 0, self.source)
        qp.drawPixmap(self.source.width(), 0, self.source)
        qp.drawPixmap(self.source.width() * 2, 0, self.source)
        qp.end()

    def moveCenter(self):
        if not self.delta:
            return
        self.center += self.delta
        # limit the vertical position
        if self.center.y() < self.sourceRect.height() * .5:
            self.center.setY(self.sourceRect.height() * .5)
        elif self.center.y() > self.source.height() - self.height() * .5:
            self.center.setY(self.source.height() - self.height() * .5)
        # reset the horizontal position if beyond the center of the virtual image
        if self.center.x() < self.source.width() * .5:
            self.center.setX(self.source.width() * 1.5)
        elif self.center.x() > self.source.width() * 2.5:
            self.center.setX(self.source.width() * 1.5)
        self.sourceRect.moveCenter(self.center.toPoint())
        self.update()

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.mousePos = event.pos()

    def mouseMoveEvent(self, event):
        if event.buttons() != QtCore.Qt.LeftButton:
            return
        delta = event.pos() - self.mousePos
        # use a fraction to get small movements, and ensure we're not too fast
        self.delta.setX(max(-25, min(25, delta.x() * .125)))
        self.delta.setY(max(-25, min(25, delta.y() * .125)))
        if not self.deltaTimer.isActive():
            self.deltaTimer.start()

    def mouseReleaseEvent(self, event):
        self.deltaTimer.stop()

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.drawPixmap(self.rect(), self.pano, self.sourceRect)

    # resize and reposition the coordinates whenever the window is resized
    def resizeEvent(self, event):
        self.sourceRect.setSize(self.size())
        self.sourceRect.moveCenter(self.center)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = Panoramic('pano.jpg')
    w.show()
    sys.exit(app.exec_())