QTable und TabOrder

Alles rund um die Programmierung mit Qt
Antworten
Gartenzwerg
Beiträge: 33
Registriert: 19. Oktober 2004 08:10

QTable und TabOrder

Beitrag 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
ArneStocker
Beiträge: 300
Registriert: 3. November 2004 16:15
Wohnort: Berlin

Beitrag 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 :roll:

Gruss Arne
Gartenzwerg
Beiträge: 33
Registriert: 19. Oktober 2004 08:10

Beitrag 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?
ArneStocker
Beiträge: 300
Registriert: 3. November 2004 16:15
Wohnort: Berlin

Beitrag 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
Gartenzwerg
Beiträge: 33
Registriert: 19. Oktober 2004 08:10

Beitrag 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
ArneStocker
Beiträge: 300
Registriert: 3. November 2004 16:15
Wohnort: Berlin

Beitrag 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
Gartenzwerg
Beiträge: 33
Registriert: 19. Oktober 2004 08:10

Beitrag 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
ArneStocker
Beiträge: 300
Registriert: 3. November 2004 16:15
Wohnort: Berlin

Beitrag von ArneStocker »

... vor dem Reden schwingen hätte ich eigentlich in die Doku schauen sollen (peinlich ... :oops:)

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
Gartenzwerg
Beiträge: 33
Registriert: 19. Oktober 2004 08:10

Beitrag von Gartenzwerg »

das entspräche dann meiner ersten Lösung ...
ArneStocker
Beiträge: 300
Registriert: 3. November 2004 16:15
Wohnort: Berlin

Beitrag 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
Gartenzwerg
Beiträge: 33
Registriert: 19. Oktober 2004 08:10

Beitrag 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
ArneStocker
Beiträge: 300
Registriert: 3. November 2004 16:15
Wohnort: Berlin

Beitrag 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
Gartenzwerg
Beiträge: 33
Registriert: 19. Oktober 2004 08:10

Beitrag von Gartenzwerg »

danke, jetzt funktioniert es endlich!

Gartenzwerg
Antworten