On Thursday 23 January 2003 19:46, me wrote:
> Problem: reimplemented QSpinBox don't get focus events and doesn't behave
> correctly on up/down cursor key events (value doesn't change).
Also, manually editing the QSpinBox value doesn't generate a valueChanged
signal, nor does it revert invalid values.
> Therefore, I'm going to translate this app to c++ in order
> to check this behaviour of Qt directly soon.
Done, attached. Looks like the c++ version doesn't generate focus events,
either, but behaves correctly on cursor keys and manual editing. Consequently
both actions generate a valueChanged signal, unlike the py version.
> Interesting side note: I needed to prepare the event() handlers not to
> call the base class in order to avoid an attribute error during
> qApp.quit(). Phil, it appears, that the QSpinBox base class disappears
> while subclassed SpinBox event() handler is active. This doesn't look right
> to me.
While making both versions functional identical, I've rewritten the event
decoder qEvent(), but couldn't believe my eyes: during qApp.quit() the
value of the global defined qEventDict{} in the .py script is replaced
with a None value somewhere under the covers! Please remove the try/except
statement in qEvent, uncomment the print statement and look yourself:
close app
PushButton event: <type 'NoneType'>
Traceback (most recent call last):
File "sbtest.py", line 121, in event
print "PushButton event:", qEvent(t)
File "sbtest.py", line 79, in qEvent
if t in qEventDict.keys():
AttributeError: 'NoneType' object has no attribute 'keys'
SpinBox event: <type 'NoneType'>
Traceback (most recent call last):
File "sbtest.py", line 96, in event
print "SpinBox event:", qEvent(t)
File "sbtest.py", line 79, in qEvent
if t in qEventDict.keys():
Something is definitely going wrong here.
TIA,
Pete
#!/usr/bin/env python
# sbtest v0.1: investigate QSpinBox strangeness
#
# Copyright 2002 Hans-Peter Jansen <[EMAIL PROTECTED]>
#
# This program is placed under the GNU General Public License V.2
import sys
from qt import *
qEventDict = {
0: "None",
1: "Timer",
2: "MouseButtonPress",
3: "MouseButtonRelease",
4: "MouseButtonDblClick",
5: "MouseMove",
6: "KeyPress",
7: "KeyRelease",
8: "FocusIn",
9: "FocusOut",
10: "Enter",
11: "Leave",
12: "Paint",
13: "Move",
14: "Resize",
15: "Create",
16: "Destroy",
17: "Show",
18: "Hide",
19: "Close",
20: "Quit",
21: "Reparent",
22: "ShowMinimized",
23: "ShowNormal",
24: "WindowActivate",
25: "WindowDeactivate",
26: "ShowToParent",
27: "HideToParent",
28: "ShowMaximized",
29: "ShowFullScreen",
30: "Accel",
31: "Wheel",
32: "AccelAvailable",
33: "CaptionChange",
34: "IconChange",
35: "ParentFontChange",
36: "ApplicationFontChange",
37: "ParentPaletteChange",
38: "ApplicationPaletteChange",
39: "PaletteChange",
40: "Clipboard",
42: "Speech",
50: "SockAct",
51: "AccelOverride",
52: "DeferredDelete",
60: "DragEnter",
61: "DragMove",
62: "DragLeave",
63: "Drop",
64: "DragResponse",
70: "ChildInserted",
71: "ChildRemoved",
72: "LayoutHint",
73: "ShowWindowRequest",
80: "ActivateControl",
81: "DeactivateControl",
82: "ContextMenu",
83: "IMStart",
84: "IMCompose",
85: "IMEnd",
86: "Accessibility",
87: "Tablet"
}
def qEvent(t):
try:
if t in qEventDict.keys():
return qEventDict[t]
except:
pass
return "Unknown";
probmsg = """\
Problem: reimplemented QSpinBox below
don't get focus events and doesn't behave
correctly on up/down cursor keys!\
"""
class SpinBox(QSpinBox):
def __init__(self, minValue, maxValue, step = 1, parent = None, name = None):
self.lastval = None
QSpinBox.__init__(self, minValue, maxValue, step, parent, name)
def event(self, e):
t = e.type()
print "SpinBox event:", qEvent(t)
# this seems to be necessary because of races with qApp.quit()
if QSpinBox:
return QSpinBox.event(self, e)
else:
return 0
def focusInEvent(self, e):
self.lastval = self.value()
print "SpinBox focusInEvent", self.lastval
QSpinBox.focusInEvent(self, e)
def focusOutEvent(self, e):
v = self.value()
print "SpinBox focusOutEvent", v, self.lastval
if self.lastval != v:
emit(SIGNAL("valueChanged(int)"), (v))
QSpinBox.focusOutEvent(self, e)
class PushButton(QPushButton):
def __init__(self, text = None, parent = None, name = None):
QPushButton.__init__(self, text, parent, name)
def event(self, e):
t = e.type()
print "PushButton event:", qEvent(t)
# this seems to be necessary because of races with qApp.quit()
if QPushButton:
return QPushButton.event(self, e)
else:
return 0
def focusInEvent(self, e):
print "PushButton focusInEvent"
return QPushButton.focusInEvent(self, e)
def focusOutEvent(self, e):
print "PushButton focusOutEvent"
return QPushButton.focusOutEvent(self, e)
class sbTest(QWidget):
def __init__(self, parent = None, name = None, fl = 0):
QWidget.__init__(self, parent, name, fl)
self.setCaption("QSpinBox test")
self.value = 42
vbox = QVBoxLayout(self, 4, -1, "vbox")
qb = PushButton("Quit", self, "qb")
vbox.addWidget(qb)
l = QLabel(probmsg, self, "tl")
vbox.addWidget(l)
sb = SpinBox(1, 200, 1, self, "sb")
sb.setValue(self.value)
vbox.addWidget(sb)
self.connect(sb, SIGNAL("valueChanged(int)"), self.changed)
self.connect(qb, SIGNAL("clicked()"), self.closeEvent)
def changed(self, v):
print "sb changed:", v
self.value = v
def closeEvent(self, e = None):
print "close app"
qApp.quit()
#sys.exit(0)
if __name__ == "__main__":
a = QApplication(sys.argv)
QObject.connect(a,SIGNAL("lastWindowClosed()"),a,SLOT("quit()"))
w = sbTest()
a.setMainWidget(w)
w.show()
a.exec_loop()
/*
# sbtest v0.1: investigate QSpinBox strangeness
#
# Copyright 2002 Hans-Peter Jansen <[EMAIL PROTECTED]>
#
# This program is placed under the GNU General Public License V.2
*/
#include <qapplication.h>
#include <qpushbutton.h>
#include <qspinbox.h>
#include <qwidget.h>
#include <qlayout.h>
#include <qlabel.h>
char probmsg[] = "Problem: reimplemented QSpinBox below\n"
"don't get focus events and doesn't behave\n"
"correctly on up/down cursor keys!";
char *qEvent(int t) {
switch (t) {
case 0: return "None";
case 1: return "Timer";
case 2: return "MouseButtonPress";
case 3: return "MouseButtonRelease";
case 4: return "MouseButtonDblClick";
case 5: return "MouseMove";
case 6: return "KeyPress";
case 7: return "KeyRelease";
case 8: return "FocusIn";
case 9: return "FocusOut";
case 10: return "Enter";
case 11: return "Leave";
case 12: return "Paint";
case 13: return "Move";
case 14: return "Resize";
case 15: return "Create";
case 16: return "Destroy";
case 17: return "Show";
case 18: return "Hide";
case 19: return "Close";
case 20: return "Quit";
case 21: return "Reparent";
case 22: return "ShowMinimized";
case 23: return "ShowNormal";
case 24: return "WindowActivate";
case 25: return "WindowDeactivate";
case 26: return "ShowToParent";
case 27: return "HideToParent";
case 28: return "ShowMaximized";
case 29: return "ShowFullScreen";
case 30: return "Accel";
case 31: return "Wheel";
case 32: return "AccelAvailable";
case 33: return "CaptionChange";
case 34: return "IconChange";
case 35: return "ParentFontChange";
case 36: return "ApplicationFontChange";
case 37: return "ParentPaletteChange";
case 38: return "ApplicationPaletteChange";
case 39: return "PaletteChange";
case 40: return "Clipboard";
case 42: return "Speech";
case 50: return "SockAct";
case 51: return "AccelOverride";
case 52: return "DeferredDelete";
case 60: return "DragEnter";
case 61: return "DragMove";
case 62: return "DragLeave";
case 63: return "Drop";
case 64: return "DragResponse";
case 70: return "ChildInserted";
case 71: return "ChildRemoved";
case 72: return "LayoutHint";
case 73: return "ShowWindowRequest";
case 80: return "ActivateControl";
case 81: return "DeactivateControl";
case 82: return "ContextMenu";
case 83: return "IMStart";
case 84: return "IMCompose";
case 85: return "IMEnd";
case 86: return "Accessibility";
case 87: return "Tablet";
default: return "Unknown";
}
}
class SpinBox : public QSpinBox {
Q_OBJECT
public:
SpinBox(int minValue, int maxValue, int step = 1, QWidget *parent = 0, const char *name = 0)
: QSpinBox(minValue, maxValue, step, parent, name) {
lastval = -1;
}
protected:
bool event(QEvent *e) {
int t = e->type();
qDebug("SpinBox event: %s", qEvent(t));
return QSpinBox::event(e);
}
void focusInEvent(QFocusEvent *e) {
lastval = value();
qDebug("SpinBox focusInEvent: %d", lastval);
QSpinBox::focusInEvent(e);
}
void focusOutEvent(QFocusEvent *e) {
int v = value();
qDebug("SpinBox focusOutEvent: %d (%d)", v, lastval);
QSpinBox::focusOutEvent(e);
}
private:
int lastval;
};
class PushButton : public QPushButton {
Q_OBJECT
public:
PushButton(const QString &text, QWidget *parent, const char *name = 0)
: QPushButton(text, parent, name){};
protected:
bool event(QEvent *e) {
int t = e->type();
qDebug("PushButton event: %s", qEvent(t));
return QPushButton::event(e);
}
void focusInEvent(QFocusEvent *e) {
qDebug("PushButton focusInEvent");
QPushButton::focusInEvent(e);
}
void focusOutEvent(QFocusEvent *e) {
qDebug("PushButton focusOutEvent");
QPushButton::focusOutEvent(e);
}
};
class sbTest : public QWidget {
Q_OBJECT
public:
sbTest(QWidget *parent = 0, const char *name = 0, WFlags f = 0)
: QWidget(parent, name, f) {
setCaption("QSpinBox test");
value = 42;
QVBoxLayout *vbox = new QVBoxLayout(this, 4, -1, "vbox");
PushButton *qb = new PushButton("Quit", this, "qb");
vbox->addWidget(qb);
QLabel *l = new QLabel(probmsg, this, "tl");
vbox->addWidget(l);
SpinBox *sb = new SpinBox(1, 200, 1, this, "sb");
sb->setValue(value);
vbox->addWidget(sb);
connect(sb, SIGNAL(valueChanged(int)), SLOT(changed(int)));
connect(qb, SIGNAL(clicked()), SLOT(closeEvent()));
}
public slots:
void changed(int v) {
qDebug("sb changed: %d", v);
value = v;
}
void closeEvent() {
qDebug("close app");
qApp->quit();
}
private:
int value;
};
#include "sbtest.moc"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
sbTest w;
a.setMainWidget(&w);
w.show();
return a.exec();
}
######################################################################
# Automatically generated by qmake (1.03a) Fri Jan 24 12:40:01 2003
######################################################################
TEMPLATE = app
CONFIG -= moc
CONFIG += qt warn_on thread
# Input
SOURCES += sbtest.cpp