Estoy desarrollando una app que simula un POS (Punto de venta por su siglas en inglés).La estructura del proyecto contiene una ventana principal la cual aloja en sí un QStackedlayout en el quese guardan las ventanas de la aplicación. Una de las paginas o ventanas de la aplicación (Ver la imagen), la más importante, está constituida por un QToolBox que contiene las categorías de productos a despachar y un QFrame, en este último se incrustaron algunos QLineEdits a fin de poblarlos con la información de determinada tarjeta al ser clickeada.La tarjeta y los otros widgets fueron desarrollados en QDesigner y posteriormente se les realizó algunas modificaciones personales. Esta tarjeta es la plantilla o clase que se instanciará en cada pagina (o QWidget) del QToolBox según su categoría. Es decir, según el numero de productos por categoría, así será el numero de tarjetas por pagina en el QToolBox.La situación problema es que necesito que cada una de las tarjetas sean estilo botón, de modo que pueda clicarlas y así poblar los QLineEdits del QFrame Adjunto el código de la tarjeta que en realidad se llama topcone_cad.pyCódigo de la tarjeta
from qt_core import *
from model.producto import Producto
class TopCone(QWidget): prodClicked = pyqtSignal(Producto) def __init__(self,prod: Producto, parent=None): super(TopCone, self).__init__() self.item=prod self.parent=parent self.setObjectName("TopCone") self.resize(200, 100) self.setMinimumSize(QSize(200, 100)) self.setMaximumSize(QSize(200, 100)) self.setStyleSheet("#TopCone{border-radius:6px;}") self.main_layout = QVBoxLayout(self) self.main_layout.setContentsMargins(3, 3, 3, 3) self.main_layout.setSpacing(2) self.main_layout.setObjectName("main_layout") #self.main_frame = QFrameClickable(self) self.main_frame = QFrame(self) self.main_frame.setFrameShape(QFrame.Shape.Panel) self.main_frame.setFrameShadow(QFrame.Shadow.Raised) self.main_frame.setObjectName("main_frame") self.main_frame.setStyleSheet(f""" #main_frame{{ border-radius:4px; border:2px solid #385723; background-color: #FFF7E1; }} #main_frame:hover{{ border:4px solid #385723; background-color: #FFF2CC; }}""") self.card_layout = QHBoxLayout(self.main_frame) self.card_layout.setContentsMargins(3, 3, 3, 3) self.card_layout.setSpacing(2) self.card_layout.setObjectName("card_layout") self.pxConeImg = QLabel(parent=self.main_frame) self.pxConeImg.setMinimumSize(QSize(70, 79)) self.pxConeImg.setMaximumSize(QSize(70, 79)) self.pxConeImg.setScaledContents(True) self.pxConeImg.setAlignment(Qt.AlignmentFlag.AlignCenter) self.pxConeImg.setObjectName("pxConeImg") self.pxConeImg.setStyleSheet("background-color:transparent;") self.card_layout.addWidget(self.pxConeImg) final= self.item.Codigo[2:] match final: case '11'|'12'|'13': self.pxConeImg.setPixmap(QPixmap(AppConfig().PosIcon('11'))) case '21' | '22' | '23': self.pxConeImg.setPixmap(QPixmap(AppConfig().PosIcon('12'))) case _: self.pxConeImg.setPixmap(QPixmap(AppConfig().PosIcon('13'))) self.verticalLayout = QVBoxLayout() self.verticalLayout.setSpacing(9) self.verticalLayout.setObjectName("verticalLayout") self.txtTopConeName = QLabel(parent=self.main_frame) self.txtTopConeName.setMinimumSize(QSize(0, 60)) self.txtTopConeName.setMaximumSize(QSize(16777215, 60)) font = QFont() font.setPointSize(16) font.setBold(True) self.txtTopConeName.setFont(font) self.txtTopConeName.setStyleSheet("color: rgb(0, 85, 0);background-color:transparent") self.txtTopConeName.setAlignment(Qt.AlignmentFlag.AlignCenter) self.txtTopConeName.setWordWrap(True) self.txtTopConeName.setObjectName("txtTopConeName") self.verticalLayout.addWidget(self.txtTopConeName) self.txtTopConePrice = QLabel(parent=self.main_frame) self.txtTopConePrice.setMinimumSize(QSize(0, 30)) self.txtTopConePrice.setMaximumSize(QSize(16777215, 30)) font = QFont() font.setPointSize(13) font.setBold(True) self.txtTopConePrice.setFont(font) self.txtTopConePrice.setAlignment(Qt.AlignmentFlag.AlignCenter) self.txtTopConePrice.setWordWrap(True) self.txtTopConePrice.setObjectName("txtTopConePrice") self.txtTopConePrice.setStyleSheet("background-color:transparent; color:rgb(0,0,88);") self.verticalLayout.addWidget(self.txtTopConePrice) self.card_layout.addLayout(self.verticalLayout) self.main_layout.addWidget(self.main_frame) self.txtTopConeName.setText(self.item.Nombre) self.txtTopConePrice.setText(f"$ {int(self.item.Precio)}") if self.item.ProdImage is not None: foto =QPixmap() foto.loadFromData(self.item.ProdImage, "PNG", Qt.AutoColor) self.pxConeImg.setPixmap(foto) QMetaObject.connectSlotsByName(self) def enterEvent(self, event: QEnterEvent) -> None: self.txtTopConeName.setStyleSheet("color: rgb(255, 0, 0);background-color:transparent") def leaveEvent(self, a0: QEvent) -> None: self.txtTopConeName.setStyleSheet("color: rgb(0, 85, 0);background-color:transparent") def mousePressEvent(self, a0: QMouseEvent | None) -> None: self.main_frame.setStyleSheet(f""" #main_frame{{ border:3px solid #F8C10C; background-color: #003300; color:#FFF7E1; }}""") self.txtTopConeName.setStyleSheet("color:#FFF7E1;background-color:transparent") self.prodClicked.emit(self.item) def mouseReleaseEvent(self, a0: QMouseEvent | None) -> None: self.main_frame.setStyleSheet(f""" #main_frame{{ border-radius:4px; border:2px solid #385723; background-color: #FFF7E1; }} #main_frame:hover{{ border:4px solid #385723; background-color: #FFF2CC; }}""") self.txtTopConeName.setStyleSheet("color: rgb(0, 85, 0);background-color:transparent")Finalmente adjunto el código del controlador donde se cargan variables y obviamente la vista... from qt_core import *from view.pages.page_pos import Ui_Formfrom model.producto import Productofrom model.item import Itemfrom model.dbman import DbManfrom view.widgets.card_tile import DipTilefrom view.widgets.topcone_card import TopConefrom model.factura import Facturaclass PosCtrl(QWidget): def __init__(self) -> None: super(PosCtrl, self).__init__() self.ui = Ui_Form() self.ui.setupUi(self) # Variables de clase self.NroFactura="" self.tipoServicio="ConsES" # self.ui.btnEditRow.clicked.connect(self.cargarItem) self.ui.rbtnDelivery.clicked.connect(lambda: self.asignarServicio('domicilio')) self.ui.rbtnInPlace.clicked.connect(lambda: self.asignarServicio("en_sitio")) self.ui.rbtnCarryHome.clicked.connect(lambda: self.asignarServicio("llevar")) # self.lista_conos: Producto =list() self.lista_toppings=list() self.lista_bebidas=list() self.lista_salsas=list() self.pedido_actual:Item=list() self.factura = Factura() self.load_conos() self.load_salsas() def asignarServicio(self, val): match val: case 'domicilio': #activateClientAddress(True) self.tipoServicio="ConsAD" case 'en_sitio': self.tipoServicio="ConsES" case 'llevar': self.tipoServicio="ConsAS" @pyqtSlot(Producto) def load_item_from_display(self, p:Producto): self.ui.txtInvoiceDetail = p.Nombre self.ui.txtInvoiceUnitPrice= p.Precio self.ui.txtInvoiceProdCode= p.Codigo def cargarItem(self): print("Me estoy cargando los items")#Metodo para quitar las tarjetas del grid del scrollarea def setTileContainerEmpty(self): for i in reversed(range(self.tileBox.count())): widgetToRemove = self.tileBox.itemAt(i).widget() # remove it from the layout list self.tileBox.removeWidget(widgetToRemove) # remove it from the gui widgetToRemove.setParent(None) def load_conos(self): self.lista_conos.clear() self.lista_conos = DbMan().cargarProductosxCategoria('conos') pos=list() cant=len(self.lista_conos) if cant>0: pos=self.posItems(cant, 3) for xp in range(cant): xItem=self.lista_conos[xp] cono = TopCone(xItem) self.ui.layout_conos.addWidget(cono,pos[xp].x, pos[xp].y) else: pass # def load_toppings(self): # self.lista_toppings.clear() # categoria= "toppings" # self.lista_conos = DbMan().cargarListaProductos(categoria) # pos=list() # cant=len(self.lista_toppings) # if cant>0: # pos=self.posItems(cant, 4) # for xp in range(cant): # tarjeta = QItemTile(self.lista_productos[xp],self) # self.tileBox.addWidget(tarjeta,pos[xp].x, pos[xp].y) # self.scrollArea.setWidget(self.tileContainer) # else: # pass # def load_bebidas(self): # self.lista_conos.clear() # categoria= "conos" # self.lista_conos = DbMan().cargarListaProductos(categoria) # pos=list() # cant=len(self.lista_conos) # if cant>0: # pos=self.posItems(cant, 4) # for xp in range(cant): # tarjeta = QItemTile(self.lista_productos[xp],self) # self.tileBox.addWidget(tarjeta,pos[xp].x, pos[xp].y) # self.scrollArea.setWidget(self.tileContainer) # else: # if self.cbxTiendaCategorias.currentText()!="Seleccione una categoría" or self.cbxTiendaCategorias.currentText()!="No hay categorías disponibles": # pass #MsgBox().iMsg("Carga de Productos para Salida","No existen productos disponibles en esta categoría",2) def load_salsas(self): self.lista_salsas.clear() self.lista_salsas = DbMan().cargarProductosxCategoria('salsas') cant=len(self.lista_salsas) if cant>0: pos=list() pos=self.posItems(cant, 4) for xp in range(cant): gravy = self.lista_salsas[xp] dip = DipTile(gravy,self) self.ui.layout_salsas.addWidget(dip,pos[xp].x, pos[xp].y) else: pass def posItems(self, cant, cols=4): col=cols fil=cant//col nPos=[CardPosition(x,y) for x in range(fil) for y in range(col)] if cant%col!=0: nPos.extend([CardPosition(fil, k) for k in range(cant%col)]) return nPosclass CardPosition: def __init__(self,x=0, y=0): self.__x=x self.__y=y @property def x(self): return self.__x @property def y(self): return self.__y
Como pueden ver, incluí en la tarjeta en código para emitir la señal de que se ha hecho click a fin que se pueda conectar algun elemento (Quizá la misma tajeta) con esta señal y poder pasar los datos al QFrame. y poder continuar el código. Es en realidad en lo que estoy estancado. Así mismo adjunto el código de la ventana (o página) que contiene el QToolBox y el QFrame y el codigo del controlador.
He tratado de hacerlo buscando al padre de la ventana que contiene los widgets qtoolbox y qframe pero me da como resultado qscrollarea.
Qué puedo hacer? Por favor!!!