1

Tengo el siguiente código:

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


class Primera(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        uic.loadUi("Inicio.ui",self)
        self.preview_alta #QpushButton

class image_anadir(Primera):
    def __init__(self):
        pr = Primera()
        pr.preview_alta.clicked.connect(lambda:print("add"))

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

Dentro de la clase Primera que hereda de QMainWindow tengo un botón self.preview_alta, pero necesito ocupar ese botón en la clase image_anadir.

Sin embargo, no ejecuta la acción que le indico dentro de la clase image_anadir.

¿En qué me equivoqué?

FJSevilla
  • 55,603
  • 7
  • 35
  • 58
Mystic_Force
  • 503
  • 2
  • 13

1 Answers1

2

Creo que tienes algo de confusión con el paradigma y conceptos de la POO, básicamente tienes dos problemas:

  • En ningún momento instancias la clase image_añadir, solo creas un objeto de Primera (p = Primera), por lo que para empezar nada de lo que hagas en image_añadir se va a ver en ningún sitio porque no la instancias. Ten en cuenta que una clase por si sola es solo un esquema o plantilla que se usa para crear objetos y que la herencia solo trabaja en una dirección, la clase hija hereda las características de la clase (o clases) padre pero nunca a la inversa.

  • A la hora de crear tu clase image_añadir te quedas entre un intento de herencia y uno de composición sin completar ninguna de las dos, si vas a usar herencia no instancies a la clase padre dentro del inicializador de la clase hija.

    La clase image_añadir al heredar de Primera obtiene sus métodos y atributos incluidos el __init__ y preview_alta.

    Ahora bién, en tu clase hija sobreescribes el inicializador (__init__) heredado del padre, para poder hacer uso de los atributos definidos en el inicializador de la clase superior tienes que llamarlo explícitamente en el inicializador de clase derivada. Esto permitirá que todas las tareas necesarias para inicializar correctamente la instancia se lleven a cabo y que todos los atributos definidos en el inicializador de la clase padre sean inicializados correctamente y pasen a estar disponibles en la clase derivada (como la carga del .ui, sin la cual el atributo preview_alta no existirá). Es exactamente lo mismo que has hecho en Primera con QMainWindow.__init__(self). Con ello puedes usar tu botón heredado como harías en Primera:

    self.preview_alta.clicked.connect(lambda:print("add")):


import sys
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5 import uic



class Primera(QMainWindow):
    def __init__(self):
        super().__init__()
        uic.loadUi("Inicio.ui", self)


class ImageAnadir(Primera):
    def __init__(self):
        super().__init__()  # Primera.__init__(self)
        self.preview_alta.clicked.connect(lambda: print("add"))


app = QApplication(sys.argv)
w = ImageAnadir()           # Instancia de la subclase.
w.show()
sys.exit(app.exec_())

super permite hacer referencia a la clase padre y llamar al método __init__ de la misma como también hace Primera.__init__(self), tiene especial utilidad en casos de herencia múltiple. Para más información puede ser útil:

¿Qué es y que utilidad tiene super en POO?

Como recomendación, considera nombrar las clases comenzando por mayúscula y usando CamelCase como se recomienda en PEP 8 -- Style Guide for Python Code, esto diferencia las clases de métodos/funciones y variables.


Edición:

En referencia al comentario, que la clase esté o no definida en otro módulo no tiene importancia en cuanto a usar herencia o composición. Imaginemos que Principal está definida en un módulo llamado interfaz.py, suponiendo que esté en el mismo directorio que el script donde definimos ImageAnadir, basta con importar la clase con:

from interfaz import Principal

para poder usarla.

En cuanto a un ejemplo de composición, la composición a grandes rasgos quiere decir que nuestra clase instancia otras clases y maneja estos objetos para implementar las funcionalidades deseadas.

El usar herencia o composición (o agregación...) va a depender de nuestro caso concreto. Imaginemos que tenemos la clase Mamifero y la clase Gato, lo lógico es que Gato herede de Mamífero porque un gato es un mamífero (y lo será siempre). Si tenemos una clase Barco y una clase Vela lo lógico es usar composición porque un barco tiene una vela que usa para navegar, no es una vela, es más, un barco puede no tener una vela y seguir siendo un barco. Si, son ejemplos muy claros y en la realidad los límites no están tan claros siempre, peros esas dos verbos (ser y tener) son de gran ayuda.

Dado que no tengo ni idea de que intentas hacer, solo voy a dejar un ejemplo muy simple de composición con tus clases, que no se si tendrán en realidad algún sentido dada la falta de contexto:

import sys
from PyQt5.QtWidgets import  QApplication
from interfaz import Primera



class ImageAnadir:                 # No hereda de Principal
    def __init__(self): 
        self._interfaz = Primera() # Instancia un objeto de la clase Principal
        self._interfaz.preview_alta.clicked.connect(self.obtener_imagen)

    def obtener_imagen(self):
        print("Imágen obtenida...")

    def abrir_ventana(self):
        self._interfaz.show()


app = QApplication(sys.argv)
im = ImageAnadir()
im.abrir_ventana()
sys.exit(app.exec_())
FJSevilla
  • 55,603
  • 7
  • 35
  • 58