How the function emit () works in python

1

I'm starting in python, today the teacher explained us about the function emit and I use the following example:

from PyQt5.QtWidgets import QMainWindow,QApplication
from PyQt5 import uic
from PyQt5 import QtCore
import threading

class Principal(QMainWindow):
    final  = QtCore.pyqtSignal(object)
    def __init__(self):
        QMainWindow.__init__(self)
        uic.loadUi("new.ui",self)

        self.boton.clicked.connect(self.setNumero)
        self.final.connect(self.fFinal)

    def setNumero(self):
        n = 1
        self.frame.setStyleSheet("background:red;")
        self.label.setText(str(n))
        threading.Thread(target=self.obtenerTamaño,args=(self.frame,)).start()

    def obtenerTamaño(self,tamaño):
        print(tamaño.geometry())
        self.final.emit(tamaño)

    def fFinal(self,frame):
        print(self.label.text())
        print(frame.geometry())



app = QApplication([])
p = Principal()
p.show()
app.exec_()

new.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>731</width>
        <height>533</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>MainWindow</string>
      </property>
      <widget class="QWidget" name="centralwidget">
       <widget class="QPushButton" name="boton">
        <property name="geometry">
         <rect>
          <x>80</x>
          <y>70</y>
          <width>75</width>
          <height>23</height>
         </rect>
        </property>
        <property name="text">
         <string>Inicio</string>
        </property>
       </widget>
       <widget class="QFrame" name="frame">
        <property name="geometry">
         <rect>
          <x>180</x>
          <y>70</y>
          <width>301</width>
          <height>301</height>
         </rect>
        </property>
        <property name="frameShape">
         <enum>QFrame::StyledPanel</enum>
        </property>
        <property name="frameShadow">
         <enum>QFrame::Raised</enum>
        </property>
       </widget>
       <widget class="QLabel" name="label">
        <property name="geometry">
         <rect>
          <x>76</x>
          <y>150</y>
          <width>71</width>
          <height>31</height>
         </rect>
        </property>
        <property name="text">
         <string/>
        </property>
       </widget>
      </widget>
     </widget>
     <resources/>
     <connections/>
    </ui>

But I'm not clear about the following:

because this line final = QtCore.pyqtSignal(object) is declared before the method __init__ and then used as self.final .

I hope and someone can explain to me how this works. as far as I understood this is to be able to execute 2 processes on different work threads. but I hope someone with more experience can support me

    
asked by Mystic_Force 11.12.2018 в 00:30
source

1 answer

4

Although the title of the question is " How the function emit() in Python " works, what you ask at the end is something else: " why final is declared before the method __init__ and then it is used as self.final ?

There is no relationship between the two questions, so I will answer the second one, because the first one is not mentioned again outside the title (I suggest changing it).

When you put sentences that look like variable assignments within the body of a class, but outside the body of any of its methods, such as:

class Principal(QMainWindow):
    final  = QtCore.pyqtSignal(object)

What you are declaring is a class attribute . This attribute is very similar to an object attribute (which is what you initialize from within one of its methods with a syntax such as self.atributo=algo ), with the following characteristics:

  • It can be accessed without the need to instantiate any object, with the syntax Clase.atributo . In your case it would be Principal.final .
  • You can also access it through an object of that class, with the syntax objeto.atributo (in your case it would be p.final , since p is an instance of Principal .
  • From any of the methods of the object you can access the attribute of the class to read it , also using self.atributo (this is the way in which your example uses it within __init__() , where self.final appears).
  • If you access any of the above to read it , you get the same value. All the objects created from that class, have automatically in self.atributo the value that has been initialized in the class. Not only the value, they are all references to the same data. All objects share that data.
  • If you make Clase.atributo=otra_cosa , that is, modify the class attribute, all objects of that class (even those that have already been created) will see that new value when they try to access self.atributo .
  • And the most important thing because it always ends up causing problems. If an object modifies the attribute using objeto.atributo = otra_cosa or self.atributo = otra_cosa , that change affects only that object , because in that case python will create a new object attribute different from the class attribute (although with the same name). That is, from that moment Clase.atributo and objeto.atributo (for that object) are no longer the same variable.

You can try running and experimenting with the following code to understand it.

class Cosa:
   # Atributo de clase
   atributo = 1

   # Mostrar el atributo de objeto y de clase
   def mostrar(self):
       print("Atributo de objeto:", self.atributo)
       print("Atributo de clase:", Cosa.atributo)

   # Intento de cambiar el atributo de clase a través de self,
   # creará un nuevo atributo de objeto con el mismo nombre
   def cambiar(self, nuevo_valor):
       self.atributo = nuevo_valor

# Sin instanciar objetos, se pueden ver los atributos de clase
print(Cosa.atributo)  # Sale 1

# Instanciando un objeto, también se puede intentar acceder
# a su atributo. Mostrará el de clase
obj_cosa = Cosa()
print(obj_cosa.atributo)  # Sale 1

# De hecho, el de objeto y el de clase son el mismo
print(obj_cosa.atributo is Cosa.atributo)  # True

# Así que no es de extrañar este resultado
obj_cosa.mostrar()  # Muestra dos veces 1

# Pero intentemos cambiar el atributo de la clase
Cosa.atributo = 2

# ¿Qué mostrará ahora esto?
obj_cosa.mostrar()  # Muestra dos veces 2. El objeto no tiene atributo, usa el de clase

# Y si intentamos cambiar el atributo del objeto?
obj_cosa.atributo = 3

# Ahora se ha creado uno nuevo, Cosa.atributo y obj_cosa.atributo ya no son lo mismo
print(obj_cosa.atributo is Cosa.atributo)  # False

# Por tanto ya no nos extraña esto
obj_cosa.mostrar()  # Muestra 3 y 2

# El atributo de objeto se podría haber cambiado así
obj_cosa.cambiar(5)

# Con igual resultado que si hubiéramos hecho obj_cosa.atributo = 5
obj_cosa.mostrar()  # Sale 5 y 2
    
answered by 11.12.2018 / 10:03
source