PDA

View Full Version : qpushbutton setfocus signal



skuda
21st November 2007, 17:03
Hello all,
i want to enable a button and set focus to it but when i use the setfocus method the button launch signals "pressed()" and "clicked()" so the connected function launch too without press the button, i have workaround actually with a autoincremental number, testing if it is par but how can i really fix this?

jpn
21st November 2007, 17:47
when i use the setfocus method the button launch signals "pressed()" and "clicked()"
Can we see the code? I just wrote a test and it doesn't do anything like that for me with Qt 4.3.2.

skuda
21st November 2007, 18:55
well it is python code but i think it is self-explained:



self.connect(self.cancelButton, SIGNAL("clicked()"), lambda: self.accionBotones("cancel"))
self.connect(self.okButton, SIGNAL("clicked()"), lambda: self.accionBotones("ok"))
self.temporal = 0

def accionBotones(self, accion):
if accion == "cancel":
self.efectivoSpinBox.setFocus()
self.efectivoSpinBox.selectAll()
self.activaBotones(False)
self.temporal = 0
elif accion == "ok":
self.temporal = self.temporal + 1
#print self.temporal
if self.temporal % 2 == 0:
self.guardaDatos()
QDialog.accept(self)

def activaBotones(self, valor):
self.correctoLabel.setEnabled(valor)
self.okButton.setEnabled(valor)
self.cancelButton.setEnabled(valor)
if valor:
self.okButton.setFocus()



when i use activaBotones function with True value in valor variable, the okButton launch the signal clicked so i maintain a number and only launch the relevant code if it is the second exec on the slot (when the user really press the button) i reset too the number if the user press cancel to fix any values

skuda
22nd November 2007, 23:10
any idea on this one? maybe i should fill a bug report in qt?

jpn
23rd November 2007, 08:01
Well, PyQt is not a Trolltech product. :) Anyway, could you write a minimal but complete app we can run ourselves to see the problem?

skuda
23rd November 2007, 09:52
Yes i know it is not a Trolltech product hehehe but i have found 3 bugs in qt 4.3.2 from pyqt and all of them was from qt (i reported it in task tracker) pyqt only wraps the qt libraries so if the problem is inside qt objects usually is a qt problem, here i paste a working example using python 2.5.1, PyQt 4.3.1 and QT 4.3.2, i have found that the problem happens when i come from a spinbox (testing after editingfinished signal that the doublespinbox value is > 50) but if i execute setFocus from other button for example all works ok.



#!/usr/bin/env python2.5
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class TestDlg(QDialog):
def __init__(self, parent=None):
super(TestDlg, self).__init__(parent)
self.testButton = QPushButton()
self.spinBox = QDoubleSpinBox()
self.emitButton = QPushButton()
self.testButton.setText("Test Button")
self.emitButton.setText("Emit Button")
layout = QVBoxLayout()
layout.addWidget(self.testButton)
layout.addWidget(self.spinBox)
layout.addWidget(self.emitButton)
self.setLayout(layout)
self.connect(self.testButton, SIGNAL("clicked()"), self.testButtonPressed)
self.connect(self.spinBox, SIGNAL("editingFinished()"), self.testing)
self.connect(self.emitButton, SIGNAL("clicked()"), self.messageLaunch)

def testing(self):
if self.spinBox.value() > 50:
self.emitButton.setFocus()

def testButtonPressed(self):
self.emitButton.setFocus()

def messageLaunch(self):
QMessageBox.warning(self, "clicked button", "signal clicked() emmited from emitButton", QMessageBox.Ok)

if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
dialog = TestDlg()
dialog.show()
app.exec_()

jpn
23rd November 2007, 10:27
Yes i know it is not a Trolltech product hehehe but i have found 3 bugs in qt 4.3.2 from pyqt and all of them was from qt (i reported it in task tracker) pyqt only wraps the qt libraries so if the problem is inside qt objects usually is a qt problem
Yes, but the point was (as I said in my first post) that I couldn't reproduce the problem with Qt 4.3.2 in the first place.


i have found that the problem happens when i come from a spinbox (testing after editingfinished signal that the doublespinbox value is > 50) but if i execute setFocus from other button for example all works ok.
I have ported the test application to C++ and I still can't reproduce the problem. I have attached the C++ version in case anyone else wants to give it a try.

skuda
23rd November 2007, 10:32
wow jpn i have compiled your test and i have the same problem with it that with my pyqt code, if i set the spinbox above 50 and press enter i get the messagebox of the emitted signal from the button, hmmm can be any problem with my qt compilation?

jpn
23rd November 2007, 10:48
wow jpn i have compiled your test and i have the same problem with it that with my pyqt code, if i set the spinbox above 50 and press enter i get the messagebox of the emitted signal from the button, hmmm can be any problem with my qt compilation?
Ahh, that's it! I didn't realize to press enter but only switched focus to other widget (which causes editingFinished() to be emitted as well).. :p Anyway, the "emit button" is the default button of the dialog so that's why it gets clicked by pressing enter. In C++, you would add

emitButton->setAutoDefault(false);
and the problem is gone. Refer to QPushButton docs for more information about "default buttons" and "auto default buttons".

skuda
23rd November 2007, 10:51
Thanks !! i can now delete my super-mega-ugly hack hehehe

skuda
23rd November 2007, 11:13
i now have other problem, with autodefault false if i hit enter the button is not clicked, i have to press space, this is not a problem for me but for my users can be like burn in the hell (aprox.), any idea about how can fix this or should i go to my ugly hack other time? PD: i would like to avoid subclass qpushbutton if possible.

momesana
23rd November 2007, 11:51
Maybe using QPushButton::setDefault(true) in Addition to setAutoDefault(false).

skuda
23rd November 2007, 11:57
if i set default after the setfocus it is automatically clicked because the enter pressed before to set the value in the spinbox and i have two buttons in the same dialog, the two should be accept enter key on focus.

momesana
23rd November 2007, 12:17
Then it may be appropriate to use an event handler for that purpose. Reimplement keyPressEvent(QKeyEvent *)

The C++ version would look like this (both buttons must be implemented as members):


void keyPressEvent(QKeyEvent* event)
{
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
if (testButton->hasFocus()) testButton->animateClick();
if (emitButton->hasFocus()) emitButton->animateClick();
}
QDialog::keyPressEvent(event);
}

skuda
23rd November 2007, 12:34
i have made this:




def keyPressEvent(self, event):
if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return and (self.okButton.hasFocus() or self.cancelButton.hasFocus()):
print "test"
event.accept()
else:
QDialog.keyPressEvent(self, event)



and i still have the same problem, when i press the enter in the doublespinbox, the okButton get the focus and automatically it is clicked.

jacek
23rd November 2007, 13:23
when i press the enter in the doublespinbox, the okButton get the focus and automatically it is clicked.
Only "default" buttons react to return/enter and they disregard the focus in that matter.

Try this:


...
connect(testButton, SIGNAL(clicked()), SLOT(testButtonPressed()));
connect(spinBox, SIGNAL(editingFinished()), SLOT(testing()));
connect(emitButton, SIGNAL(clicked()), SLOT(messageLaunch()));

emitButton->installEventFilter( this );
emitButton->setAutoDefault( false );
emitButton->setDefault( false );

testButton->installEventFilter( this );
testButton->setAutoDefault( false );
testButton->setDefault( false );
}

bool TestDlg::eventFilter( QObject * o, QEvent * e )
{
QPushButton * b = qobject_cast< QPushButton * >( o );
if( b != 0 && e->type() == QEvent::KeyPress ) {
QKeyEvent * ke = static_cast< QKeyEvent * >( e );
if( ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return ) {
b->animateClick();
return true;
}
}
return false;
}

skuda
23rd November 2007, 13:53
yeah, this is the real solution, thanks jacek and too all that have helped this :)