使用 PyQt5 QWidget 不会出现在 QMainWindow 中

QWidget does not appear in the QMainWindow using PyQt5

我想要的是在SINGLEwindow下打开windows的界面,也就是不希望界面多开windows。 我会引导你到我的错误。当我 运行 我的代码时,我得到一个主页,从那里我点击 View/Edit --> View/Edit Processed Slices。在这一点上,这是你应该在 MAIN WINDOW:

中得到的

图片1

我希望界面做的是在我单击蓝色矩形时看到图 2 中的 window。我希望它在同一个主窗口中打开新的小部件 WINDOW

图片2

但是,当我单击它时,会打开一个新的 window,而之前的 window 仍然打开(图 3)。这是我想避免的,我只想要 1 window 而不是 2.

图3

代码如下:

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import cv2
import numpy as np
"""
    MAIN WINDOW
"""
class CancerSegWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        self.title = 'Cancer Segmentation GUI               '
        self.initUI()


    def initUI(self):               

        self.central = HOME()
        self.setCentralWidget(self.central)

        ##
        # ACTIONS
        ##

        ##File
            #Exit
        exitAct = QAction(QIcon('E:\BEATSON_PROJECT\python\GUI\exit.png'), 'Exit', self)    # QAction is an abstraction for actions performed with a menubar, toolbar, or with a custom keyboard shortcut
        exitAct.setShortcut('Ctrl+Q')
        exitAct.setStatusTip('Exit application')                                            # Status tip at the bottom
        exitAct.triggered.connect(self.close)                                               # Triggered signal is emitted. The signal is connected to the close() method of the QMainWindow widget.

            #Home
        HomeAct = QAction(QIcon('E:\BEATSON_PROJECT\python\GUI\home.png'), 'Home', self)    
        HomeAct.setStatusTip('Go Home')                                            
        HomeAct.triggered.connect(self.Home) 

        ## View and Edit

            # Slices

                # Processed Slices
        ProcessedAct = QAction('View / Edit Processed Slices', self)  
        ProcessedAct.triggered.connect(self.Processed_Slices)

        self.statusBar().showMessage('Home')                   # First call statusBar creates a status bar at the bottom
                                                                # Subsequent calls return the statusbar object
        ##
        # main MENU bar 
        ##

        menubar = self.menuBar()                # create a menubar

        # File

        fileMenu = menubar.addMenu('File')              # File  (menu)
        fileMenu.addAction(exitAct)                         # Exit

        # View and Edit                                 

        veMenu = menubar.addMenu('View / Edit')       # View and Edit (menu)
        vesMenu = QMenu('View / Edit Slices',self)            # Slices
        vesMenu.addAction(ProcessedAct)                             # Processed
        veMenu.addMenu(vesMenu)

        ##
        # ICONS
        ##
        toolbar = self.addToolBar('Exit')         
        toolbar.addAction(exitAct)

        toolbarHome = self.addToolBar('Home')
        toolbarHome.addAction(HomeAct)
        ##
        # WINDOW
        ##
        self.setGeometry(0, 30, 1366, 697) 
        self.setWindowTitle(self.title)
        self.setWindowIcon(QIcon('E:\BEATSON_PROJECT\python\GUI\medicine.png'))
        self.show()

    def Home (self):
        self.central = HOME()
        self.setCentralWidget(self.central)

    def Processed_Slices (self):
        self.statusBar().showMessage('Displaying Processed Slices. Click on one Slice to View and Edit it individually') 
        self.central = ProcessedSlices()
        self.setCentralWidget(self.central)
        self.setWindowTitle(self.title + self.central.title)

    def Pre_Edit_Processed (self, SliceNo=1):
        self.statusBar().showMessage('Displaying Automatic Processed Slice' + str(SliceNo) + ' You can redraw it manually or modify the existing contour') 
        self.central = PreEditProcessed(SliceNo)
        self.setCentralWidget(self.central)
        self.setWindowTitle(self.title + self.central.title)

"""
    HOME WINDOW
"""
class HOME (QWidget):
    def __init__(self):
        super().__init__()
        #self.central = QPixmap("E:\BEATSON_PROJECT\python\GUI\Home_.png") 
        self.lbl1 = QLabel(self)
        #self.lbl1.setPixmap(self.central)

"""
    PROCESSED SLICES WINDOW
"""
class ProcessedSlices(QWidget):
    def __init__(self):
        super().__init__()
        self.title = ('- Processed Slices')
        self.initUI()


    def initUI(self): 

        ##
        #CHECKBOXES
        ##

        # Slice 1 
                                                    #CheckBox
        self.cb1 = QCheckBox('Slice 1', self)              
        self.cb1.move(1270, 115)
        self.cb1.toggle()
        self.cb1.stateChanged.connect(self.OpenSlice1)

                                                 #Pixmap (Image) 1
        pixmap1 = QPixmap(310, 330)         # Contour
        pixmap1.fill(Qt.blue)
        #pixmap1 = QPixmap("E:\BEATSON_PROJECT\python\GUI\Processed_Slice_1.png") 
        self.lbl1 = QLabel(self)
        self.lbl1.setGeometry(QRect(QPoint(10,0),QPoint(310,330))) # 
        self.lbl1.setPixmap(pixmap1)

        ##
        # SET GRID to obtain the mouse position
        ##

        grid = QGridLayout()
        self.text = "x: {0},  y: {1}".format(0, 0)          # display the x and y coordinates of a mouse pointer in a label widget

        self.label = QLabel(self.text, self)                # x and y coordinates are displayd in a QLabel widget
        grid.addWidget(self.label, 0, 1270, Qt.AlignTop)


        self.setLayout(grid)


        ##
        #WINDOW
        ##

        #self.setGeometry(0, 25, 1365, 700)
        #self.setWindowTitle('Processed Slices')
        self.show()


    def OpenSlice1(self, state):
        self.lbl1.setVisible(state == Qt.Checked)


    def mousePressEvent(self, e):                                     # The e is the event object. it contains data about the event that was triggered
        x = e.x()                                                     # in our case, a mouse CLICK                                          
        y = e.y()                                                     #  x() and y() methods we determine the x and y coordinates of the mouse pointer
        text = "None selected x: {0},  y: {1}"

        if ( x >= 10 and x <= 310 and y >= 0 and y <= 330 and self.cb1.isChecked()):
            text = "Slice 1 x: {0},  y: {1}".format(x, y)
            self.close()
            self.CSW = CancerSegWindow()
            self.CSW.Pre_Edit_Processed(1)

        self.label.setText(text)

"""
    PROCESSED SLICES CHECK WINDOW
"""
class PreEditProcessed(QWidget):
    def __init__(self, SliceNo=1):
        super().__init__()
        self.title = ('- Check Processed Slices')
        self._SliceNo = SliceNo
        self.initUI()

    def initUI(self):
        #self.draw = Draw(self)
        #self.draw._windows = 1

        # Button to clear both image and drawing
        self.button = QPushButton('Discard and segment MANUALLY ', self)            
        #self.button.clicked.connect(self.editManually)

        # Button to modify contour
        self.BmodContour = QPushButton('Modify existing contour ', self)            
        #self.BmodContour.clicked.connect(self.modContour)

        # Button to finish and compare
        self.BFinish = QPushButton('Finish ', self)         
        #self.BFinish.clicked.connect(self.Finish)

        # Arrange Layout

        self.layout = QVBoxLayout(self)                         
        #self.layout.addWidget(self.draw)       # Show Slice
        self.layout.addWidget(self.button)      # Manually
        self.layout.addWidget(self.BmodContour) # Modify contour
        self.layout.addWidget(self.BFinish)     # Finish and compare

        self.setGeometry(0, 25, 1365, 700)
        self.setWindowTitle('Check Slices')
        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = CancerSegWindow()
    sys.exit(app.exec_())

注意代码的相关部分在classProcessedSlices:

里面
def mousePressEvent(self, e):                                     
        x = e.x()                                                     
        y = e.y()                                                     
        text = "None selected x: {0},  y: {1}"

        if ( x >= 10 and x <= 310 and y >= 0 and y <= 330 and self.cb1.isChecked()):
            text = "Slice 1 x: {0},  y: {1}".format(x, y)
            self.close()
            self.CSW = CancerSegWindow()
            self.CSW.Pre_Edit_Processed(1)

您的问题是您正在函数 mousePressEvent(self, e).

中创建 class CancerSegWindow() 的另一个实例

最好的方法是使用 pyqtSignal().

您必须在 ProcessedSlices 中声明 pyqtSignal(int) class:

class ProcessedSlices(QWidget):
    #here declare signal
    signal = pyqtSignal(int)
    def __init__(self):
    # more code....

并在您的 mousePressEvent(self, e) 中发出信号:

def mousePressEvent(self, e):                                     # The e is the event object. it contains data about the event that was triggered
    x = e.x()                                                     # in our case, a mouse CLICK                                          
    y = e.y()                                                     #  x() and y() methods we determine the x and y coordinates of the mouse pointer
    text = "None selected x: {0},  y: {1}"

    if ( x >= 10 and x <= 310 and y >= 0 and y <= 330 and self.cb1.isChecked()):
        text = "Slice 1 x: {0},  y: {1}".format(x, y)
        self.close()
        self.signal.emit(1) # emit signal with SliceNo=1

    self.label.setText(text)

最后,将其捕获到您的 Processed_Slices():

def Processed_Slices (self):
    self.statusBar().showMessage('Displaying Processed Slices. Click on one Slice to View and Edit it individually') 
    self.central = ProcessedSlices()
    self.central.signal.connect(self.Pre_Edit_Processed) #connect signal
    self.setCentralWidget(self.central)
    self.setWindowTitle(self.title + self.central.title)