如何制作小部件的屏幕截图并将其粘贴到 QGraphicsView 中?

问题描述

我在表单上有 2 个 QWebEngineView一个 QWebEngineView 小部件,我需要 *(单击按钮 1)* 制作此 QWebEngineView内容的屏幕截图原始 QGraphicsView 边界的一些定义的挫折并将该屏幕截图保存为图像,同时将其保留为对象并将此对象粘贴到第一个 QGraphicsView 和 *(单击 button2 )* 将保存的图像插入第二个 import sys,os from PyQt5.QtCore import Qt from PyQt5.QtGui import QBrush,QPen,QScreen,Qpixmap from PyQt5.QtWidgets import QApplication,qstyleFactory,QMainWindow,QWidget,QVBoxLayout,QLabel from PyQt5.QtWidgets import QGraphicsScene,QGraphicsView,QGraphicsItem,QPushButton from pyqtgraph.Qt import QtCore,QtGui from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtWidgets import QApplication,QDialog class Geometry(QGraphicsView): def __init__(self): QGraphicsView.__init__(self) class CentralPanel(QWidget): def __init__(self): QWidget.__init__(self) self.lblCoords = QLabel('MAP SELECTOR (object image): ') self.lblCoords2 = QLabel('MAP SELECTOR (loaded from file image): ') self.gvwShapes = Geometry() self.gvwShapes2 = Geometry() vbxDsply = QVBoxLayout() vbxDsply.addWidget(self.lblCoords) # Capture coordinates of drawn line at window 1 vbxDsply.addWidget(self.gvwShapes) # add QGraphicsView #1 vbxDsply.addWidget(self.lblCoords2) # Capture coordinates of drawn line at window 2 vbxDsply.addWidget(self.gvwShapes2) # add QGraphicsView #2 self.webEngineView = QWebEngineView() # Add Google maps web window self.webEngineView.load(QtCore.QUrl("https://www.google.com/maps/@36.797966,-97.1413048,3464a,35y,0.92h/data=!3m1!1e3")) vbxDsply.addWidget(self.webEngineView) self.Button1 = QPushButton('Do screenshot of webEngineView save it and paste it into QGraphicsView2',self) # Button to load image to graphics view vbxDsply.addWidget(self.Button1) self.Button1.clicked.connect(self.button_screenshot) self.Button2 = QPushButton('Do screenshot of webEngineView and paste it into QGraphicsView1 ',self) vbxDsply.addWidget(self.Button2) self.Button2.clicked.connect(self.button_load_image) self.setLayout(vbxDsply) self.filename = "image.jpg" def button_screenshot(self): print('Screenshot is taken and saved as an image,Image loaded and inserted into the gvwShapes QGraphicsView1 ') app = QApplication(sys.argv) QScreen.grabWindow(app.primaryScreen(),QApplication.desktop().winId()).save(self.filename,'png') def button_load_image(self): print('Screenshot is taken and inserted into the gvwShapes2 QGraphicsView2') # pix = Qpixmap() # pix.load(self.filename) # pix = Qpixmap(self.filename) # item = QGraphicspixmapItem(pix) # scene = QGraphicsScence(self) # scene.addItem(item) # self.graphicsView.setScene(scene) scene = QtWidgets.QGraphicsScene(self) pixmap = Qpixmap(self.filename) item = QtWidgets.QGraphicspixmapItem(pixmap) scene.addItem(item) self.gvwShapes.setScene(scene) # scene = self.gvwShapes # self.image = QtGui.Qpixmap(self.filename) # self.gvwShapes.add # scene.addItem(QtGui.QGraphicspixmapItem(self.image)) # self.view = self.QGraphicsView # self.view.setScene(self.image) # self.view.show() class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.setGeometry(200,50,700,900) self.setwindowTitle('MAP Selector REV01') self.setStyle(qstyleFactory.create('Cleanlooks')) self.CenterPane = CentralPanel() self.setCentralWidget(self.CenterPane) # Catching exceptions and running a main loop # import traceback def except_hook(exc_type,exc_value,exc_tb): tb = "".join(traceback.format_exception(exc_type,exc_tb)) print("error cached") print("error message:\n",tb) if __name__ == "__main__": MainEventThred = QApplication([]) os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = "--enable-logging --log-level=3" sys.excepthook = except_hook MainApp = MainWindow() MainApp.show() MainEventThred.exec()

编辑: (我想对 QtWebEngineWidgets 内的区域进行屏幕截图并将该区域作为对象保留。第二个问题我需要知道如何以两种不同的方式将此区域粘贴到 QGraphicsView 中:(来自文件)并在不保存的情况下将其显示为对象。2 QGraphicsView 仅用于学习目的,它可能只是一个 QGraphicsView 并且通过点击 button1 屏幕截图正在制作并粘贴为 QGraphicsView 的对象,并通过点击 button2 -screenshot 正在制作(保存作为 png 并加载到 QGraphicsView))

enter image description here

这是我的代码

<Item Key="ValidTokenIssuerPrefixes">https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000,https://login.microsoftonline.com/11111111-1111-1111-1111-111111111111</Item>

解决方法

为您的 QGraphicsViews 设置场景。

self.gvwShapes = Geometry()
self.gvwShapes2 = Geometry()
self.gvwShapes.setScene(QGraphicsScene())
self.gvwShapes2.setScene(QGraphicsScene())

使用 QWidget.grab() 将其渲染为 QPixmap 并使用 QGraphicsScene.addPixmap() 将其添加到场景中。您可以使用 QRect 指定区域。

def button_screenshot(self):
    pixmap = self.webEngineView.grab(QRect(180,100,300,280))
    pixmap.save(self.filename)
    self.gvwShapes2.scene().addPixmap(pixmap)

def button_load_image(self):
    self.gvwShapes.scene().addPixmap(QPixmap(self.filename))
,

在 QWebEngineView 中裁剪图像

如果你想实现QWebEngineView截图的裁剪,那么你必须使用QWebEngineView的focusProxy()上的一个QRubberBand(它是渲染网页的小部件,接收之后创建的鼠标事件)显示视图)

from functools import cached_property
import sys

from PyQt5.QtCore import pyqtSignal,QEvent,QObject,QPoint,QRect,QSize,QUrl
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication,QLabel,QRubberBand
from PyQt5.QtWebEngineWidgets import QWebEngineView


class RubberBandManager(QObject):
    pixmap_changed = pyqtSignal(QPixmap,name="pixmapChanged")

    def __init__(self,widget):
        super().__init__(widget)
        self._origin = QPoint()
        self._widget = widget

        self.widget.installEventFilter(self)

    @property
    def widget(self):
        return self._widget

    @cached_property
    def rubberband(self):
        return QRubberBand(QRubberBand.Rectangle,self.widget)

    def eventFilter(self,source,event):
        if self.widget is source:
            if event.type() == QEvent.MouseButtonPress:
                self._origin = event.pos()
                self.rubberband.setGeometry(QRect(self._origin,QSize()))
                self.rubberband.show()
            elif event.type() == QEvent.MouseMove:
                self.rubberband.setGeometry(
                    QRect(self._origin,event.pos()).normalized()
                )
            elif event.type() == QEvent.MouseButtonRelease:
                rect = self.rubberband.geometry()
                pixmap = self.widget.grab(rect)
                self.pixmap_changed.emit(pixmap)
                self.rubberband.hide()
        return super().eventFilter(source,event)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    view = QWebEngineView()
    view.load(
        QUrl(
            "https://www.google.com/maps/@36.797966,-97.1413048,3464a,35y,0.92h/data=!3m1!1e3"
        )
    )
    view.show()
    rubberband_manager = RubberBandManager(view.focusProxy())

    label = QLabel()
    label.hide()

    def on_pixmap_changed(pixmap):
        label.setPixmap(pixmap)
        label.adjustSize()
        label.show()

    rubberband_manager.pixmap_changed.connect(on_pixmap_changed)

    ret = app.exec()
    sys.exit(ret)

在 QGraphicsView 中显示图像

要显示图像,您必须使用 QGraphicsPixmapItem 加载 QPixmap。

import sys

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap,QPainter,QPalette
from PyQt5.QtWidgets import (
    QApplication,QGraphicsView,QGraphicsScene,QGraphicsPixmapItem,)


class ImageViewer(QGraphicsView):
    def __init__(self,parent=None):
        super().__init__(parent)
        self.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
        self.setAlignment(Qt.AlignCenter)
        self.setBackgroundRole(QPalette.Dark)

        scene = QGraphicsScene()
        self.setScene(scene)

        self._pixmap_item = QGraphicsPixmapItem()
        scene.addItem(self._pixmap_item)

    def load_pixmap(self,pixmap):
        self._pixmap_item.setPixmap(pixmap)
        self.fitToWindow()

    def fitToWindow(self):
        self.fitInView(self.sceneRect(),Qt.KeepAspectRatio)

    def resizeEvent(self,event):
        super().resizeEvent(event)
        self.fitToWindow()


if __name__ == "__main__":
    app = QApplication(sys.argv)

    view = ImageViewer()
    view.resize(640,480)
    view.show()

    pixmap = QPixmap("image.jpg")
    view.load_pixmap(pixmap)

    ret = app.exec()
    sys.exit(ret)

前面的小部件用于从文件加载图像:pixmap = QPixmap("/path/of/image") 或使用 RubberBandManager 的 pixmap_changed 信号提供的 QPixmap。