Problem with eventFilter and Key_Return in a QDialog with buttons

1

I have the following code where I try to use eventFilter :

class Ticket(QDialog):
    def __init__(self):

        QDialog.__init__(self)
        uic.loadUi("ticket.ui",self)
        self.D_Aceptar.clicked.connect(self.productos) #QPushButton

    def total(self,total1):
        global n
        n = total1
        tr = round(n, 2)
        self.l_total.setText(str(tr)) #lineEdit que recive el valor
        self.pago.setFocus() # QLineEdit
        self.pago.installEventFilter(self)

    def eventFilter(self,obj,event):
        if obj is self.pago and event.type() == QEvent.KeyPress:
            if event.key() == Qt.Key_Return:
                self.calculo()
        return QDialog.eventFilter(self,obj,event)

    def calculo(self):
        pago = float(self.pago.text())
        operacion = pago-n
        opf =round(operacion, 2)
        op = str(opf)
        self.cambio.setText('$ {}'.format(op))


    def prductos_specifico_bar(self,bar_code,sucursal):
        new_total = 0
        ref  = db.reference('/Productos_Bar/'+str(bar_code))
        r0 = ref.get()
        total = 0
        try:
            for key in r0.items():
                if sucursal == 1:
                    if key[0] == 'exe1':
                        val = key[1]
                        total = val
                        if total == 0:
                            self.cambio.setText('Producto sin inventario')
                            break
                        else:
                            new_val = total-1

                            ref.update({
                                'exe1':new_val
                            })
                elif sucursal == 2:
                    if key[0] == 'exe2':
                        val = key[1]
                        total = val
                        if total == 0:
                            self.cambio.setText('Producto sin inventario')
                            break
                        else:
                            new_val = total-1

                            ref.update({
                                'exe2':new_val
                            })
                elif sucursal == 3:
                    if key[0] == 'exe3':
                        val = key[1]
                        total = val
                        if total == 0:
                            self.cambio.setText('Producto sin inventario')
                            break
                        else:
                            new_val = total-1

                            ref.update({
                                'exe3':new_val
                            })
        except:
            pass

    def producto_especifico_id(self,identi,sucursal):
        try:
            if int(identi) > 4:
                self.prductos_specifico_bar(identi, sucursal)
            else:
                ref  = db.reference('/Productos_Bar')
                r1 = ref.get()
                for key in r1.items():
                    res1 = key[1]['id']
                    if res1 == identi:
                        new_ref = key[0]
                        self.prductos_specifico_bar(new_ref,sucursal)
                        break
                    else:

                        self.l_codigo.setText('ID no existe')
                        break
        except:
            self.l_codigo.setText("No se coloco un valor valido")

    def productos(self):
        for i in lista1:
            self.producto_especifico_id(i, sucursal_id)

Theoretically, when the event within self.pago equals key_return you must execute the self.calculo() method.

The problem is that, however, it also executes the slot associated with the self.D_Aceptar button that is self.productos

What I'm missing or wrong?

    
asked by Revsky01 30.07.2018 в 20:00
source

1 answer

1

Your button is configured as the default button which is activated when press the ENTER key within the dialog, which typically indicates that the user has completed the configuration, accepts and closes the dialog.

The button set to default in QDialog has two differential properties:

  • It is activated when the ENTER key is pressed in the dialog, so the corresponding slot is called if it has one associated with the signal connect as commented.

  • It will be shown with an extra frame, so (depending on the style of the GUI) it will be highlighted, even if it does not have the focus.

There are two properties of QPushButton that come into play:

  • default : indicates whether a button is or not the default button, so we can configure a button as the default button or not using the default argument during the instantiation or later using the QPushButton.setDefault(bool) method. Since there can only be one default button simultaneously in a QDialog , if we define several with this property only the first will be taken into account (as long as the property does not change).

  • autodefault : yes in QDialog no button has default=True , the first one that accepts this role thanks to the property QPushButton.autoDefault , is automatically set as default when the dialog is displayed.

    By default it is False , except when you instantiate a QPushButton with your parent being a QDialog , then the property autodefault is True by default.

    You can also specify it by instantiating via argument autodefault or later using the QPushbutton.setAutoDefault(bool) method.

By the name of the button I suspect that this is precisely its function so if you want to preserve it, what you can do is simply avoid the propagation of the event when the ENTER occurs within QLineEdit returning True :

def eventFilter(self, obj, event):
    if obj is self.pago and event.type() == QEvent.KeyPress:
        if event.key() == Qt.Key_Return:
            self.calculo()
            return True
    return QDialog.eventFilter(self, obj, event)

Keep in mind that this will only prevent the button from being activated if the ENTER occurs in self.pago (I say it in case you have more widgets in the QDialog that must also respond to it) event).

If you want to avoid having a button like default you can simply specify it in all the buttons of the QDialog:

btn = QtWidgets.QPushButton(default=True, autoDefault=False)

or QDesigner in the button properties:

In this case you could simply use the QLineEdit.returnPressed() simplemente signal.

    
answered by 30.07.2018 / 21:23
source