简体   繁体   中英

How can I inherit between classes in pyqt?

In order to track progress, this is the third question about practicing with different classes in PyQt5 .Here are the links to my previous questions: opening a new window , Open a file from main window to a new window in PyQt5 (in different files) .

I'm trying to work with two classes, one with one button and when it's pressed it will load a file and show the text in a QTextEdit in other class.

In the first questions I was suggested that as an alternative to work with more classes, they can inherit from QMainWindow so I looked for more info for doing this: PyQt class inheritance

The second question code did worked but it would show both windows at the same time, so this question: PyQt: How to hide QMainWindow guided me to write this code (I attatch this here because it's a little bit different from the one in the link, plus I apply what it says in the answer):

import sys, os
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton

class Dialog_02(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Dialog_02, self).__init__(parent, QtCore.Qt.Window)

        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        myBoxLayout = QVBoxLayout()

        Button_02 = QPushButton ("Show Dialog 01")
        myBoxLayout.addWidget(Button_02)

        self.setLayout(myBoxLayout)
        self.setWindowTitle('Dialog 02')

        Button_02.clicked.connect(self.closeAndReturn)

    def closeAndReturn(self):
        self.close()
        self.parent().show()


class Dialog_01(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Dialog_01, self).__init__()

        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        myBoxLayout = QVBoxLayout()

        Button_01 = QPushButton ("Show Dialog 02")
        myBoxLayout.addWidget(Button_01)

        self.setLayout(myBoxLayout)
        self.setWindowTitle('Dialog 01')

        Button_01.clicked.connect(self.callAnotherQMainWindow)

    def callAnotherQMainWindow(self):
        self.hide()
        self.dialog_02 = Dialog_02(self)
        self.dialog_02.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    dialog_1 = Dialog_01()
    dialog_1.show()
    sys.exit(app.exec_())

In this code I'm not inheriting, but it works fine.

The issue is that when I try to follow the same syntax in the original question code, it won't run, I'm not sure I'm getting inheritances fine.

import sys
import os
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtWidgets import QPushButton, QVBoxLayout, QTextEdit, QHBoxLayout, QLabel, QMainWindow, QAction, QFileDialog

class SecondWindow(QWidget):
    def __init__(self, Window):
        super(SecondWindow, self).__init__(parent, QtCore.Qt.Window)

        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        self.text = QTextEdit(self)
        self.btn_return= QPushButton("Return")
        self.init_ui()

    def init_ui(self):
        v_layout = QVBoxLayout(self)
        v_layout.addWidget(self.text)
        v_layout.addWidget(self.btn_return)
        self.setLayout(v_layout)
        self.setWindowTitle('Opened Text')

        self.btn_return.clicked.connect(self.closeAndReturn)

    def closeAndReturn(self):
        self.close()
        self.parent().show()

class Window(QMainWindow):

    textChanged = QtCore.pyqtSignal(str)

    def __init__(self, *args):
        super(Window, self).__init__()

        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        self.img = QLabel()
        self.load_file= QPushButton('Load')

        self.width = 400
        self.height = 150        

        self.init_ui()

    def init_ui(self):
        self.img.setPixmap(QtGui.QPixmap("someimage.png"))


        h_layout = QHBoxLayout()
        v_layout = QVBoxLayout()
        h_final = QHBoxLayout()

        h_layout.addWidget(self.img)

        v_layout.addWidget(self.load_file)

        h_final.addLayout(h_layout)
        h_final.addLayout(v_layout)

        self.load_file.clicked.connect(self.loadafile)

        self.setLayout(h_final)
        self.setWindowTitle('Main Window')
        self.setGeometry(600,150,self.width,self.height)

    @QtCore.pyqtSlot()
    def loadafile(self):
        filename = QFileDialog.getOpenFileName(self, 'Open File', os.getenv('HOME'))
        with open(filename[0], 'r') as f:
            file_text = f.read()
            self.textChanged.emit(file_text)

        self.hide()
        self.dialog_02 = SecondWindow(self)
        self.dialog_02.show()

def main():
    app = QApplication(sys.argv)
    main = Window()
    s = SecondWindow(main)
    main.textChanged.connect(s.text.append)
    main.show()



    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

You are coupling many classes: What happens if at a moment SecondWindow does not have a parent? Well, your code will have problems and you will have to modify it a lot so that it works correctly. So first it is to design the behavior of each class, for example SecondWindow has to warn the other windows that it was clicked, it has to have a method that updates the text. Similarly, Window must notify that there is new text available.

On the other hand QMainWindow already has a predefined layout so you must create a centralwidget where you place the other widgets.

import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class SecondWindow(QtWidgets.QWidget):
    closed = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(SecondWindow, self).__init__(parent, QtCore.Qt.Window)
        self.text = QtWidgets.QTextEdit()
        self.btn_return= QtWidgets.QPushButton("Return")
        self.init_ui()

    def init_ui(self):
        v_layout = QtWidgets.QVBoxLayout(self)
        v_layout.addWidget(self.text)
        v_layout.addWidget(self.btn_return)
        self.setWindowTitle('Opened Text')
        self.btn_return.clicked.connect(self.close)
        self.btn_return.clicked.connect(self.closed)

    @QtCore.pyqtSlot(str)
    def update_text(self, text):
        self.text.setText(text)
        self.show()

class Window(QtWidgets.QMainWindow):
    textChanged = QtCore.pyqtSignal(str)

    def __init__(self, *args):
        super(Window, self).__init__()
        self.img = QtWidgets.QLabel()
        self.load_file= QtWidgets.QPushButton('Load')
        self.width = 400
        self.height = 150        
        self.init_ui()

    def init_ui(self):
        self.img.setPixmap(QtGui.QPixmap("someimage.png"))
        self.load_file.clicked.connect(self.loadafile)
        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        h_layout = QtWidgets.QHBoxLayout(central_widget)
        h_layout.addWidget(self.img)
        h_layout.addWidget(self.load_file)
        self.setWindowTitle('Main Window')
        self.setGeometry(600,150,self.width,self.height)

    @QtCore.pyqtSlot()
    def loadafile(self):
        filename, _ = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', os.getenv('HOME'))
        if filename:
            with open(filename, 'r') as f:
                file_text = f.read()
                self.textChanged.emit(file_text)
                self.close()

def main():
    app = QtWidgets.QApplication(sys.argv)
    main = Window()
    s = SecondWindow()
    main.textChanged.connect(s.update_text)
    s.closed.connect(main.show)
    main.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM