-1

I want to call a function which uses an ui object created by Qt Designer from a separate file and I cannot seem to be able to figure out how to do that. This is to help me on a larger project I'm working on.

As of now I am getting the error

AttributeError: type object 'QMainWindow' has no attribute 'label'

My first file - main.py

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt5.QtCore import Qt

from PyQt5.uic import loadUi

class MainPage(QMainWindow):
    
 
    def __init__(self):
        
        
        QMainWindow.__init__(self)
        
        loadUi("layout.ui",self)
        
        from display_label_func import DISPLAY_LABEL
        

        self.setWindowTitle("Example")
        
    
        self.pushButton.clicked.connect(DISPLAY_LABEL.display_words)
        
        
        

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    win = MainPage()
    win.show()
    sys.exit(app.exec_())

My 2nd file - display_label_func

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import*



class DISPLAY_LABEL(QMainWindow):
    
    def __init__(self):
        
        QMainWindow.__init__(self)
        
    
    
    def display_words(self):
        
        
        
            QMainWindow.label.setText('1.E4 is best by test')
            

My ui file - layout.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>595</width>
    <height>452</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
     <widget class="QWidget" name="widget" native="true">
      <property name="styleSheet">
       <string notr="true">background-color: rgb(33, 33, 33);</string>
      </property>
      <widget class="QLabel" name="label">
       <property name="geometry">
        <rect>
         <x>110</x>
         <y>80</y>
         <width>381</width>
         <height>161</height>
        </rect>
       </property>
       <property name="font">
        <font>
         <pointsize>20</pointsize>
         <weight>75</weight>
         <bold>true</bold>
        </font>
       </property>
       <property name="styleSheet">
        <string notr="true">background-color: rgb(255, 255, 255);
color: rgb(255, 0, 0);</string>
       </property>
       <property name="text">
        <string/>
       </property>
      </widget>
     </widget>
    </item>
    <item row="1" column="0">
     <widget class="QPushButton" name="pushButton">
      <property name="text">
       <string>Button</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>595</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

How would I go about resolving this and get it to work?

Also, if I define and set a variable in the display_label_func file could I use that variable in subsequent files all part of the same gui?

Thanks.

daniel ajj
  • 83
  • 9
  • What is the point of `DISPLAY_LABEL`? Do you *actually* use that class, or is it just intended as a "container" for the function? I'm supposing it's the second case, which makes subclassing from QMainWindow a bit pointless. In any case, you can't directly access members of instances from external modules, you must pass a reference to an object that has access to the target. I suggest you to do some research and improve your knowledge about classes, instances and methods, as you seem lacking some important basic aspects of OOP. – musicamante Jan 20 '22 at 09:09
  • I'll be honest in saying that my knowledge of OOP here is lacking. I don't know if using a class is necessary or if the function can stand alone in the separate file. I tried to do some research on the issue all throughout yesterday and I really got no where. I'm here hoping an example would do the trick. This is a reproduction of an actual problem I'm facing at the moment. – daniel ajj Jan 20 '22 at 09:15
  • The only way to achieve that in a separate module is to pass a reference to the widget (or any object that can provide that reference), but then it would be almost pointless in most cases: just do it in the main script. So, the actual question is: why do you want to use an external module to set the label text? You ask if you can define a variable in the other file and use that for the label text, which can be done, but, then again, what would be the point of having the function in a separate module? You can just import that variable. – musicamante Jan 20 '22 at 13:28
  • By the way, your research shouldn't be focused on your current problem, as it's too specific and won't help understanding the *actual* problem: if you want to know why a mathematical operation gives you a wrong result, you don't research about that wrong result, but about how that operation works. Your research should focus on the way OOP works and what are/how to use classes and instances; you cannot ignore those aspects if you want to use Python and PyQt, and while you don't need to be an expert on the subject, a basic knowledge and understanding is mandatory. – musicamante Jan 20 '22 at 13:39
  • I really don't know where to begin. The reason I want to have the function in a separate module is because the project I'm currently working on has gotten to large and I would like to split it. So this is an example of that problem not the actual problem. – daniel ajj Jan 20 '22 at 15:00
  • The OOP concepts you need are [Mixin](https://en.wikipedia.org/wiki/Mixin) and [Object Composition](https://en.wikipedia.org/wiki/Object_composition). I suggest you read some tutorials on the subject and get a basic understanding of the various pros and cons before proceeding any further: e.g. [RealPython: Inheritance and Composition: A Python OOP Guide](https://realpython.com/inheritance-composition-python/) and [The Composition Over Inheritance Principle](https://python-patterns.guide/gang-of-four/composition-over-inheritance/). – ekhumoro Jan 20 '22 at 17:46

1 Answers1

0

The problem is that you are using a second class. Just define your display_words method in your MainPage class then use it, like so :

class MainPage(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        loadUi("layout.ui",self)
        self.setWindowTitle("Example")
        self.pushButton.clicked.connect(self.display_words)  # when the `pushButton` of this window gets clicked, the `display_words` of this instance (self) will be called
    def display_words(self):
        QMainWindow.label.setText('1.E4 is best by test')

There is no need for a second class.

Lenormju
  • 4,078
  • 2
  • 8
  • 22