change label from other class in a different file

Viewed 2222

I am creating an application where I have a main window whit a label and then a docked widget that is in another file. I want to change the main windows label from a button at the docked widget. I try to import the main window file but then I can not access to the label. And I also tried to call a function in the main windows that changes the label but then the label does not change. Here is the code:

main_window.py:

import results_window

class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()

        self.define_main_windows()

        self.create_dock_widgets()

    def define_main_windows(self):
        # Define de Main window properties
        self.setMinimumSize(QSize(300, 100))    
        self.setWindowTitle("Python SkyLibris") 
        self.setWindowIcon(QtGui.QIcon("skylibris_icon.png"))
        self.setStyleSheet("QMainWindow {background: 'white';}")

        self.top = 50
        self.left = 0
        self.width = 1300
        self.height = 400
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.result = QLabel("result:")
        self.setCentralWidget(self.result)


    def create_dock_widgets(self):
        # Create dock widgets
        self.results_window = results_window.results_window()
        self.resultsWindowDock = QDockWidget("Results Viewer", self)
        self.resultsWindowDock.setWidget(self.results_window )
        self.resultsWindowDock.setFloating(False)
        self.resultsWindowDock.setVisible(True)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.resultsWindowDock)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle('Fusion')
    mainWin = MainWindow()
    mainWin.show()
    sys.exit(app.exec_())

results_window.py:

import main_window

class results_window(QWidget):

    def __init__(self):
        super(results_window, self).__init__()
        print("init")

        self.label = QLabel()
        self.value = QLineEdit()

        self.bt = QPushButton("Click")
        self.bt.clicked.connect(self.clickMethod)


        self.main_layout = QVBoxLayout()
        self.main_layout.addWidget(self.label)
        self.main_layout.addWidget(self.value)
        self.main_layout.addWidget(self.bt)

        self.setLayout(self.main_layout)

    def clickMethod(self):
        print(self.value.text())
        text = self.value.text()
        main_window.result.setText(text)
2 Answers

You are using the wrong tools, for example your code has a circular import that causes your application to close since it is equivalent to a while True.

In Qt, signals and slots are used to share data asynchronously, as well as contributing to the fact that there is no coupling between classes. In your case, Results_Window must have a signal that transmits that information to the MainWindow, this signal must be emit within clickMethod.

results_window.py

from PyQt5 import QtCore, QtWidgets

class Results_Window(QtWidgets.QWidget):
    resultChanged = QtCore.pyqtSignal(str)

    def __init__(self):
        super(Results_Window, self).__init__()
        print("init")

        self.label = QtWidgets.QLabel()
        self.value = QtWidgets.QLineEdit()

        self.bt = QtWidgets.QPushButton("Click")
        self.bt.clicked.connect(self.clickMethod)

        main_layout = QtWidgets.QVBoxLayout(self)
        main_layout.addWidget(self.label)
        main_layout.addWidget(self.value)
        main_layout.addWidget(self.bt)

    @QtCore.pyqtSlot()
    def clickMethod(self):
        text = self.value.text()
        self.resultChanged.emit(text)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle('Fusion')
    w = Results_Window()
    w.show()
    sys.exit(app.exec_())

main_window.py

from PyQt5 import QtCore, QtGui, QtWidgets
import results_window

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.define_main_windows()
        self.create_dock_widgets()

    def define_main_windows(self):
        self.setMinimumSize(QtCore.QSize(300, 100))    
        self.setWindowTitle("Python SkyLibris") 
        self.setWindowIcon(QtGui.QIcon("skylibris_icon.png"))
        self.setStyleSheet("QMainWindow {background: 'white';}")
        top, left, width, height = 50, 0, 1300, 400
        self.setGeometry(left, top, width, height)
        self.result = QtWidgets.QLabel("result:")
        self.setCentralWidget(self.result)

    def create_dock_widgets(self):
        self.results_window = results_window.Results_Window()
        self.results_window.resultChanged.connect(self.result.setText)
        self.resultsWindowDock = QtWidgets.QDockWidget("Results Viewer", self)
        self.resultsWindowDock.setWidget(self.results_window )
        self.resultsWindowDock.setFloating(False)
        self.resultsWindowDock.setVisible(True)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.resultsWindowDock)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle('Fusion')
    mainWin = MainWindow()
    mainWin.show()
    sys.exit(app.exec_())

I had similar problem in PyQT5 where I was unable to access and set the local variables. After a lot of struggle I found writing to file and reading from file as the best solution. Simply write the desired output to file and access the same info from other file. Works great!

Related