Seite 1 von 1
QTable und TabOrder
Verfasst: 27. November 2004 16:02
von Gartenzwerg
Hi,
ich habe eine Tabelle von einer QTable abgeleitet und beim Betätigen der Tabulator-Taste wechselt die Tabelle den Zellenfokus wie folgt:
Zelle(0,0)->Zelle(0,1)->Zelle(0,2)->...->Zelle(0,n)->Stop
Nach dem Aktivieren der letzten Zelle kommt man mit der Tabulator-Taste nicht mehr weiter. Jedoch soll die Tabelle jetzt wie folgt die Zellen wechseln:
Zelle(0,0)->Zelle(0,1)->Zelle(0,2)->...->Zelle(0,n)->
Zelle(1,0)->Zelle(1,1)->Zelle(1,2)->...->Zelle(1,n)->
...
Zelle(m,0)->Zelle(m,1)->Zelle(m,2)->...->Zelle(m,n)
Um das Stoppen am Reihenende zu verhindern habe ich folgendes geschrieben:
Code: Alles auswählen
bool CategoryTable::event(QEvent* ev)
{
switch(ev->type())
{
case QEvent::KeyPress:
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(ev);
if((keyEvent->key() == Qt::Key_Tab)&&(currentColumn()>=(numCols()-1))&&(currentRow()<(numRows()-1)))
{
setCurrentCell(currentRow()+1,0);
return true;
}
}
break;
return QTable::event(ev);
}
Jedoch muss man nun am Ende der Reihe doppelt die Tabulator-Taste drücken, um in die nächste Reihe/erste Spalte zu gelangen. Außerdem funktioniert auch diese Lösung nur bei QTableItems. QCheck- bzw. QComboTableItems geben den Fokus gar nicht ab. (wenn sie sich in der letzten Spalte befinden)
Wie kann ich zu einer funktionstüchtigeren Lösung gelangen?
Gartenzwerg
Verfasst: 27. November 2004 16:58
von ArneStocker
Hi Gartenzwerg,
QCheck- bzw. QComboTableItems geben den Fokus gar nicht ab. (wenn sie sich in der letzten Spalte befinden)
Hast Du es schon mal mit ...
->setFocus() versucht ?
Bekommst Du in Deiner abgeleiteten TableKlasse überhaupt ein KeyEvent, wenn der Focus noch auf dem ComboTableItem liegt ? Andernfalls könntest Du vielleicht mit
ComboTableItem->installEventFilter(...) einen Eventfilter setzen und die (Key) Events durchfiltern.
... nur so eine Überlegung
Gruss Arne
Verfasst: 27. November 2004 17:06
von Gartenzwerg
nein, ich bekomme kein event von einem QCombo- oder QCheckTableItem.
An einen EventFilter hatte ich auch schon gedacht, aber es können ziemlich viele Combo- und Checkboxen werden, die müsste ich dann ja alle prüfen oder wie?
Verfasst: 28. November 2004 12:22
von ArneStocker
Du müsstest wohl für jedes eingebaute QComboTableItem einmal die Methode QComboTableItem->installEventFilter(..) aufrufen. Das Prüfen machst Du dann in der abgeleiteten Klasse von QTable (oder was auch immer Deine Monitorklasse ist). Und da macht es keine Mehrarbeit, weil es grundsätzlich egal es, wessen Nachrichten gerade geprüft werden
Code: Alles auswählen
void QMyTable::eventFilter(QObject *pObject, QEvent *pEvent)
{
if (pEvent->type() == QEvent::KeyPress)
{
// nur wenn Du wissen möchstest welches QTableItem gerade den Event bekommen soll(te)
if (pObject == pCrazyItem)
{
.. blabla
}
}
}
Gruss Arne
Verfasst: 28. November 2004 12:49
von Gartenzwerg
muss ich dann ein Zeiger auf jedes QComboTableItem speichern, damit ich diesen auf events im eventFilter prüfen kann?
Ungefähr so?
Code: Alles auswählen
void QMyTable::eventFilter(QObject *pObject, QEvent *pEvent)
{
if (pEvent->type() == QEvent::KeyPress)
{
if (pObject == pQComboTableItem1)
{
.. blabla
}
else if (pObject == pQComboTableItem2)
{
.. blabla
}
...
}
}
Da die Anzahl der Reihen variabel ist, müsste ich das in einer Schleife organisieren. Aber vom Prinzip müsste ich jeden Zeiger prüfen?
Gartenzwerg
Verfasst: 28. November 2004 15:24
von ArneStocker
muss ich dann ein Zeiger auf jedes QComboTableItem speichern
.. eigentlich nicht, Du willst doch nur auf das TabKeyEvent reagieren, dafür ist es doch egal, welchem QComboTableItem du den Focus klaust ... oder
Ausserdem hast Du (wenn Du den zuvor den Typ von PObject prüfst) in pObject bereits einen Zeiger auf Dein ComboItem. Welche Zusatzinformation willst Du denn dann noch abfragen oder wie willst Du individuell auf jeden Zeiger reagieren ?
gruss Arne
Verfasst: 28. November 2004 21:01
von Gartenzwerg
sorry, aber mir fällt gerade auf, dass man einen eventFilter nur für von QObject abgeleitete Klassen installieren kann. QTableItem ist aber nur von Qt abgeleitet. Gibt es eine andere Möglichkeit?
Gartenzwerg
Verfasst: 29. November 2004 09:28
von ArneStocker
... vor dem Reden schwingen hätte ich eigentlich in die Doku schauen sollen (peinlich ...

)
Da aber irgendjemand (etwas) die Key events bearbeiten muss, kommt eigentlich nur noch die QMyTable Klasse in Frage. Der Aufruf von event(QEvent *pEvent) erfolgt vor der Auswertung und Bearbeitung der Basisklasse (weshalb man wegen der Ereignisse, die man nicht bearbeiten möchte die Basisklasse aufrufen sollte)
bevor ich jetzt aber noch mal theoretisch voll daneben liege werde ich mir das ganze mal selbst kompilieren (allerdings erst in ein bis zwei Tage)
Gruss (und sorry) Arne
Verfasst: 1. Dezember 2004 20:43
von Gartenzwerg
das entspräche dann meiner ersten Lösung ...
Verfasst: 3. Dezember 2004 15:57
von ArneStocker
ich bin leider immer noch nicht dazu gekommen, nachzubauen. Wenn ich es richtig verstanden habe, funktionierte die 1. Lösung nur eingeschränkt.
Möglicherweise reagiert das TabWidget nicht auf KeyPress sondern auf KeyRelease. Vielleicht solltest Du die KeyRelease - Tab events (natürlich nur in Deinen Spezialfällen) herausfiltern.
Gruss Arne
Verfasst: 5. Dezember 2004 08:22
von Gartenzwerg
Hi,
danke für den Tipp, Qt::Key_Tab wird tatsächlich übers keyReleaseEvent abgefangen:
Code: Alles auswählen
// Tastaturereignisse abfangen um TAB-Reihenfolge zu aendern
void CategoryTable::keyReleaseEvent(QKeyEvent* event)
{
// Wenn TAB-Taste gedrueckt, letzte Spalte aktiv und noch mehrere Reihen vorhanden
if((event->key() == Qt::Key_Tab)&&(currentColumn()>=(numCols()-1))&&(currentRow()<(numRows()-1)))
{
// aktive Zelle auf naechste Reihen erste Spalte setzen
setCurrentCell(currentRow()+1, 0);
}
QTable::keyReleaseEvent(event); // Aufruf der Implementation von QTable
}
Nun gibt es aber folgendes Problem:
Beim Wechsel von der vorletzten Spalte auf die letzte per Tabulator überspringt er die letzte Spalte und fokusiert gleich die erste Spalte der nächsten Reihe. Wie kann ich dies verhindern? D.h. wie kann ich dafür sorgen, dass er erst in die nächste Reihe springt, wenn man in der letzten Spalte die Tabulator-Taste gedrückt hat?
Gartenzwerg
Verfasst: 5. Dezember 2004 13:32
von ArneStocker
das dürfte damit zusammenhängen, dass mal KeyPress und mal KeyRelease ausgewertet wird. Die sauberste Version ist, dass Du nur auf KeyPress reagierst, Dir in einem zur Klasse gehörenden Flag den KeyPress Zustand merkst und bei (passendem) KeyRelease wieder freigibst.
also sinngemäß
Code: Alles auswählen
if ((..keyPress) && ( .. tab))
{
... m_tabKeyPress = true;
... umschalten des Focus
return true;
}
if (( .. keyRelease && ( .. tab))
{
m_tabKeyPress = false;
return true;
}
Gruss Arne
Verfasst: 5. Dezember 2004 14:55
von Gartenzwerg
danke, jetzt funktioniert es endlich!
Gartenzwerg