将 Qpixmap 从一个 window 发送到另一个 window

Sending Qpixmap from one window to another window

我正在编写一个有两个 windows 的程序,我想将 QPixmap 图像从第一个 window 发送到第二个 window。第一个 window 包含一个 QGraphicsView (FirstView) 和一个标签 (Second_View_label),其中两者将被设置为相同的图像。如果用户单击确认按钮,Second_View_label 中的图像应发送到第二个 window 并设置为存在于第二个 window 中的标签,即 (Third_View_label)。 我的问题是图像没有出现在 Third_View_label 中。

代码如下:

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QLabel, QWidget
from PyQt5.QtGui import  QPixmap
import sys    

class First_View(QtWidgets.QGraphicsView):
    Changed_view = QtCore.pyqtSignal(QtGui.QPixmap)

    def __init__(self, parent=None):
        super().__init__(QtWidgets.QGraphicsScene(), parent)      
        self.pixmap_item = self.scene().addPixmap(QtGui.QPixmap())
        self.pixmap_item.setShapeMode(QtWidgets.QGraphicsPixmapItem.BoundingRectShape)
        self.setAlignment(QtCore.Qt.AlignCenter)
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)

    def set_image(self, pixmap):
        self.pixmap_item.setPixmap(pixmap)
        self.fitInView(self.pixmap_item, QtCore.Qt.KeepAspectRatio)
        self.setSceneRect(self.scene().sceneRect())
        self.Changed_view.emit(pixmap)

class Ui_MainWindow(QtWidgets.QMainWindow):
    Changed_view_2 = QtCore.pyqtSignal(QtGui.QPixmap)

    def __init__(self):
        super().__init__()        
        self.resize(1270, 800)
        self.setMinimumSize(QtCore.QSize(1270, 800))
        self.setMaximumSize(QtCore.QSize(1270, 800))
        self.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")      
        self.ConfirmButton = QtWidgets.QPushButton(self.centralwidget)
        self.ConfirmButton.setMinimumSize(QtCore.QSize(200, 60))
        self.ConfirmButton.setMaximumSize(QtCore.QSize(200, 60))
        font = QtGui.QFont()
        font.setPointSize(11)
        font.setWeight(75)
        self.ConfirmButton.setFont(font)
        self.ConfirmButton.setCheckable(True)
        self.ConfirmButton.setObjectName("ConfirmButton")
        self.ConfirmButton.setEnabled(False)
        self.gridLayout.addWidget(self.ConfirmButton, 1, 3, 1, 1)        
        self.BrowesButton = QtWidgets.QPushButton(self.centralwidget)
        self.BrowesButton.setMinimumSize(QtCore.QSize(200, 60))
        self.BrowesButton.setMaximumSize(QtCore.QSize(200, 60))
        font = QtGui.QFont()
        font.setPointSize(11)
        font.setWeight(75)
        self.BrowesButton.setFont(font)
        self.BrowesButton.setCheckable(True)
        self.BrowesButton.setObjectName("BrowesButton")
        self.gridLayout.addWidget(self.BrowesButton, 1, 0, 1, 1)
        self.FirstView = First_View()
        self.FirstView.setMinimumSize(600, 500)
        self.FirstView.setMaximumSize(600, 500)
        self.FirstView.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.FirstView.setFrameShadow(QtWidgets.QFrame.Plain)
        self.gridLayout.addWidget(self.FirstView, 0, 0, 1, 2)        
        self.Second_View_label = QtWidgets.QLabel(self.centralwidget)
        self.Second_View_label.setEnabled(True)
        self.Second_View_label.setMinimumSize(QtCore.QSize(600, 500))
        self.Second_View_label.setMaximumSize(QtCore.QSize(600, 500))
        self.Second_View_label.setFrameShape(QtWidgets.QFrame.Box)
        self.Second_View_label.setFrameShadow(QtWidgets.QFrame.Plain)
        self.Second_View_label.setLineWidth(1)
        self.Second_View_label.setText("")
        self.Second_View_label.setObjectName("Second_View_label")
        self.gridLayout.addWidget(self.Second_View_label, 0, 3, 1, 1)

        self.setCentralWidget(self.centralwidget)
        self.retranslateUi(self)
        QtCore.QMetaObject.connectSlotsByName(self)

        self.messege =" Hi "
        self.BrowesButton.clicked.connect(self.load_image)
        self.FirstView.Changed_view.connect(self.set_image)
        self.ConfirmButton.clicked.connect(self.Open_Second_Window)



    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        self.ConfirmButton.setText(_translate("MainWindow", "Confirm"))
        self.BrowesButton.setText(_translate("MainWindow", "Browes for Image"))


    def load_image(self):
        fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
            None, "Select Image", "", "Image Files (*.png *.jpg *jpeg)"
        )
        if fileName:
            pixmap = QtGui.QPixmap(fileName)
            self.FirstView.set_image(pixmap)

    def set_image(self, pixmap1):
        pixmap = pixmap1.scaled(self.Second_View_label.width(), self.Second_View_label.height(), QtCore.Qt.KeepAspectRatio) # Scale pixmap
        self.Second_View_label.setPixmap(pixmap)
        self.Second_View_label.setAlignment(QtCore.Qt.AlignCenter) 
        self.ConfirmButton.setEnabled(True)
        self.Changed_view_2.emit(pixmap1)


    def Open_Second_Window(self): 
        #self.w = Second_Window(self.messege)
        w = Second_Window()
        self.win = Second_Window()
        self.win.show()
        self.Changed_view_2.connect(w.set_image_view)
        self.hide()



class Second_Window(QtWidgets.QMainWindow):       
    def __init__(self):
        #print (messege)
        super().__init__()  
        self.resize(1270, 800)
        self.setMinimumSize(QtCore.QSize(1270, 800))
        self.setMaximumSize(QtCore.QSize(1270, 800))
        font = QtGui.QFont()
        self.setFont(font)
        self.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")

        self.Third_View_label = QtWidgets.QLabel(self.centralwidget)
        self.Third_View_label.setEnabled(True)
        self.Third_View_label.setGeometry(QtCore.QRect(50, 60, 600, 500))
        self.Third_View_label.setMinimumSize(QtCore.QSize(600, 500))
        self.Third_View_label.setMaximumSize(QtCore.QSize(600, 500))
        self.Third_View_label.setFrameShape(QtWidgets.QFrame.Box)
        self.Third_View_label.setFrameShadow(QtWidgets.QFrame.Plain)
        self.Third_View_label.setLineWidth(1)
        self.Third_View_label.setText("")
        self.Third_View_label.setObjectName("Third_View_label")
        #self.Third_View_label.setPixmap(pixmap1)

        #self.set_image_view (pixmap1)    # ***** set pixmap to Third_View_label

        self.BackButton = QtWidgets.QPushButton(self.centralwidget)
        self.BackButton.setGeometry(QtCore.QRect(690, 180, 200, 60))
        self.BackButton.setMinimumSize(QtCore.QSize(200, 60))
        self.BackButton.setMaximumSize(QtCore.QSize(200, 60))
        font = QtGui.QFont()
        font.setPointSize(11)
        self.BackButton.setFont(font)
        self.BackButton.setCheckable(True)
        self.BackButton.setObjectName("BackButton")
        self.setCentralWidget(self.centralwidget)

        self.retranslateUi(self)
        QtCore.QMetaObject.connectSlotsByName(self)

        self.BackButton.clicked.connect(self.First_Window)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        self.BackButton.setText(_translate("MainWindow", "Back"))

    def set_image_view (self ,pixmap):   #*********The Problem************
        pixmap = pixmap.scaled(self.Third_View_label.width(), self.Third_View_label.height(), QtCore.Qt.KeepAspectRatio) # Scale pixmap
        self.Third_View_label.setPixmap(pixmap)
        self.Third_View_label.setAlignment(QtCore.Qt.AlignCenter) 

    def First_Window(self):                                             
        self.w = Ui_MainWindow()
        self.w.show()
        self.hide()    


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

谁能告诉我我做错了什么!! 谢谢

您的代码中存在几个问题,我会尽力解决。


首先:从不 使用 Qt Designer 文件的 pyuic 输出编写代码。

pyuic 实用程序生成的内容应始终用作导入模块,并且 永远不要 对其进行编辑,也不应将其用作程序的起点。将其视为 资源 文件(作为图像,或 json 数据);请参阅有关此的 documentation

这有多种原因,最重要的是每当您编辑在 Designer 上创建的 ui 文件时,您都必须将您的代码与新生成的 py 文件,这可能会导致一些意想不到的结果,或者在大多数情况下,由于您编写的逻辑代码与您对 GUI 所做的修改之间的差异而令人头疼。


您正在将 Changed_view_2 信号连接到将在 Open_Second_Window 函数 returns:

后立即删除的对象
    def Open_Second_Window(self): 
        #self.w = Second_Window(self.messege)
        w = Second_Window() # <-- this window will be deleted at the end
                            # of this function!
        self.win = Second_Window()
        self.win.show()
        # since "w" will be deleted, the signal won't do anything
        self.Changed_view_2.connect(w.set_image_view)
        self.hide()

您正在连接到一个已经发出的信号,因此永远不会收到。

class Ui_MainWindow(QtWidgets.QMainWindow):
    Changed_view_2 = QtCore.pyqtSignal(QtGui.QPixmap)

    def __init__(self):
        super().__init__()
        # ...
        self.FirstView.Changed_view.connect(self.set_image)
        # the second window doesn't exist yet! You're just connecting the signal
        # to *create* and open it afterwards.
        self.ConfirmButton.clicked.connect(self.Open_Second_Window)


    def set_image(self, pixmap1):
        pixmap = pixmap1.scaled(self.Second_View_label.width(), self.Second_View_label.height(), QtCore.Qt.KeepAspectRatio) # Scale pixmap
        self.Second_View_label.setPixmap(pixmap)
        self.Second_View_label.setAlignment(QtCore.Qt.AlignCenter) 
        self.ConfirmButton.setEnabled(True)
        # at this point, the second window doesn't exist yet; even assuming that
        # you correctly connect the "Changed_view_2" signal to the
        # "set_image_view" slot of the "self.w" window in your code, there's
        # no "self.w" at this point yet, so no object will receive this signal
        self.Changed_view_2.emit(pixmap1)

固定代码的可能解决方案

最简单的解决方案是在 __init__ 中创建 Second_Window 并将 Changed_view_2 信号连接到它的 set_image_view 方法。
然后,点击ConfirmButton后,会正确隐藏当前的window,会显示第二张图片(已设置) Changed_view_2 信号发出后):

class Ui_MainWindow(QtWidgets.QMainWindow):
    Changed_view_2 = QtCore.pyqtSignal(QtGui.QPixmap)

    def __init__(self):
        super().__init__()        
        # ...
        self.win = Second_Window()
        self.Changed_view_2.connect(self.win.set_image_view)

    # ...

    def set_image(self, pixmap1):
        pixmap = pixmap1.scaled(self.Second_View_label.width(), self.Second_View_label.height(), QtCore.Qt.KeepAspectRatio) # Scale pixmap
        self.Second_View_label.setPixmap(pixmap)
        self.Second_View_label.setAlignment(QtCore.Qt.AlignCenter) 
        self.ConfirmButton.setEnabled(True)
        # at this point "self.win" exists, and its "set_image_view" will correctly
        # process the following signal
        self.Changed_view_2.emit(pixmap1)

    def Open_Second_Window(self): 
        self.win.show()
        self.hide()