Seite 1 von 2
Drag & Drop zwischen QTreeWidget's
Verfasst: 20. Juni 2007 16:48
von NoRulez
Hey @all,
bin vor kurzem auf den QT Zug aufgesprungen und muss sagen es klappt soweit alles und bin sehr zufrieden damit, bis auf das Drag & Drop zwischen 2 QTreeWidget oder eben im selben QTreeWidget.
Habe auch schon in der Doku und im Forum des öfteren von diesen 4 Methoden gelesen:
Code: Alles auswählen
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
void mousePressEvent(QMouseEvent *event);
Jedoch springt kein Breakpoint im Code an (Debug-Mode).
Im
bekomme ich nur das QEvent::DragEnter - Event.
ich würde mir gerne wenn ich zum Draggen anfange einige Informationen über das Item holen und wenn danach das Drop event ausgelöst wird ebenfalls.
Kann mir da jemand helfen?
Vielen Dank im Voraus
Lg NoRulez
Verfasst: 20. Juni 2007 16:55
von upsala
Verfasst: 20. Juni 2007 17:15
von NoRulez
Die Doku habe ich schon gelesen, vielleicht habe ich was übersehen.
Wenn ich das ganze für das Hauptfenster implementiere
Code: Alles auswählen
void MyMainWindow::dragEnterEvent(QDragEnterEvent *event) {
}
bekomme ich auch dieses Event,
nur komme ich mit TreeViews nicht weiter
Muss ich da das komplette QTreeWidget subclassen?
Verfasst: 20. Juni 2007 18:36
von upsala
Nein, aber du must Drag & Drop in der View freischalten.
Aus der Doku, gilt natürlich auch für eine View:
Code: Alles auswählen
QListWidget *listWidget = new QListWidget(this);
listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
listWidget->setDragEnabled(true);
listWidget->setAcceptDrops(true);
listWidget->setDropIndicatorShown(true);
Verfasst: 20. Juni 2007 19:01
von NoRulez
Das habe ich ja alles freigeschalten, ich möchte nurmehr auf die DragEnter usw. reagieren können.
Im Moment kann ich die Items kopieren, ohne das ich jedoch noch eine Funktion implementiert habe. UND das ist mein Problem. Ich muss wenn ich daten per drag and drop ziehe auch im hintergrund noch andere sachen machen. diese kann ich jedoch nur wenn ich die Events abfangen kann.
Lg
Verfasst: 21. Juni 2007 07:30
von macman
NoRulez hat geschrieben:Muss ich da das komplette QTreeWidget subclassen?
Ja. Ist nicht soviel wie es aussieht und Du hast hinterher die volle Kontrolle. Mach es, Du wirst es nicht bereuen.
Verfasst: 21. Juni 2007 07:49
von @udisello
Hallo,
leite doch einfach das QTreeWidget ab und überschreibe dort deine Events, dann kannst du auch selbst festlegen. wann und wie das Drag Event startet und welche Daten übertragen werden. Nicht viel Aufwand, aber großer Nutzen.
im Header z.B.:
Code: Alles auswählen
void mousePressEvent( QMouseEvent* pEvent );
void mouseMoveEvent( QMouseEvent* pEvent );
void dropEvent( QDropEvent* pEvent );
void dragEnterEvent( QDragEnterEvent* pEvent );
void dragMoveEvent( QDragMoveEvent* pEvent );
und in deiner cpp:
Code: Alles auswählen
void YourClass::mousePressEvent( QMouseEvent* pEvent )
{
if( pEvent->button() == Qt::LeftButton )
{
m_StartPoint = pEvent->pos();
}
QTreeWidget::mousePressEvent( pEvent );
}
void YourClass::mouseMoveEvent( QMouseEvent* pEvent )
{
if( pEvent->buttons() & Qt::LeftButton )
{
int iDistance = ( pEvent->pos() - m_StartPoint ).manhattanLength();
if( iDistance >= QApplication::startDragDistance() )
StartDrag();
}
QTreeWidget::mouseMoveEvent( pEvent );
}
void YourClass::StartDrag()
{
QMimeData* pMimeData = new QMimeData;
pMimeData->setText( "whatyouwant" );
QDrag* pDrag = new QDrag( this );
pDrag->setMimeData( pMimeData );
if( pDrag->start( Qt::CopyAction ) )
DoSomething();
}
void YourClass::dropEvent( QDropEvent* pEvent )
{
if( pEvent->mimeData()->hasText() )
{
DoSomething();
pEvent->setDropAction( Qt::CopyAction );
pEvent->accept();
}
}
void YourClass::dragEnterEvent( QDragEnterEvent* pEvent )
{
//hier Bedingungen, wann Drag akzepiert wird
pEvent->setDropAction( Qt::CopyAction );
pEvent->accept();
}
void YourClass::dragMoveEvent( QDragMoveEvent* pEvent )
{
//hier Bedingungen, wann Drag akzepiert wird
pEvent->setDropAction( Qt::CopyAction );
pEvent->accept();
}
Verfasst: 21. Juni 2007 10:06
von NoRulez
Vielen Dank,
nur macht es einen Unterschied wenn ich die QTreeWidgets mit dem Designer erzeugt habe?
Theoretisch wird dann die Sub-Klasse ja nicht aufgerufen oder?
Würde gerne beim Designer bleiben. Aber wie gesagt bin noch neu bei QT, vielleicht geht das ja irgendwie.
Lg
Verfasst: 21. Juni 2007 10:16
von macman
Ja, das geht. Im Designer Rechtsklick auf dein TreeWidget, 'Als Platzhalter für benutzerdefinierte Klasse', und in dem Dialog gibst Du dann nur noch deinen Klassennamen und die Header-Datei an.
Verfasst: 22. Juni 2007 13:37
von NoRulez
In der Methode
kann man ja mittels
die Source und Target Widget's bekommen mein Problem ist jetzt nur das das Target nicht meinem wirklichen TreeWidget entspricht
Sprich ich übergebe im Konstruktor meine 2 TreeWidgets (tree1 und tree2)
theoretisch müsste ja eines der beiden anspringen
Code: Alles auswählen
if(pEvent->target() == tree1)
DoSomthing1();
else if(pEvent->target() == tree2)
DoSomthing2();
Wie finde ich am besten raus von wo nach wo ich dragge?
Lg NoRulez[/code]
Verfasst: 22. Juni 2007 14:21
von @udisello
Nur nochmal die Frage, Du erstellst dir ein Widget und legst dort die zwei TreeWidgets ( deine abgeleitete Klasse ) an? In der abgeleiteten Klasse hast Du dann z.B. das dropEvent, welches ausgelöst wird, wenn du ein Element auf das TreeWidget ziehst. Dann einfach:
Code: Alles auswählen
void YourClass::dropEvent( QDropEvent *pEvent )
{
YourClass *pSource = qobject_cast< YourClass* >( pEvent->source() );
if( pSource && pSource != this )
{
DoSomething();
pEvent->accept();
}
}
Wie Du siehst, hast Du dann einen Pointer auf die Quelle (pSource) und einen auf das Ziel (this).
Berichtige mich bitte wer es besser weiß, aber QDropEvent hat kein target()??? Es gibt nur
QWidget * QDrag::target () const
Returns the target of the drag and drop operation. This is the widget where the drag object was dropped.
Das kannst Du dann in der Funktion
Code: Alles auswählen
void YourClass::StartDrag()
{
QMimeData* pMimeData = new QMimeData;
pMimeData->setText( "whatyouwant" );
QDrag* pDrag = new QDrag( this );
pDrag->setMimeData( pMimeData );
if( pDrag->start( Qt::CopyAction ) )
DoSomething( with pDrag->target() );
}
abfangen
Verfasst: 22. Juni 2007 19:52
von NoRulez
Sorry meinte es eh so
Code: Alles auswählen
void YourClass::StartDrag()
{
QMimeData* pMimeData = new QMimeData;
pMimeData->setText( "whatyouwant" );
QDrag* pDrag = new QDrag( this );
pDrag->setMimeData( pMimeData );
if( pDrag->start( Qt::CopyAction ) )
DoSomething( with pDrag->target() ); // pDrag->target() ist weder tree1 noch tree2
}
pDrag->target() ist weder tree1 noch tree2
ich frage das ganze so ab
Code: Alles auswählen
if(pDrag->target() == (QWidget*)this->tree1)
BLABLABLA_1
else if(pDrag->target() == (QWidget*)this->tree2)
BLABLABLA_2
Lg NoRulez
Verfasst: 22. Juni 2007 22:05
von NoRulez
OK ich habe das ganze nochmals angeschaut, pDrag->target() ist NULL wieso bekomme ich da nicht den Drag-Target?
ich habe für beide Tree's folgendes im Hauptfenster eingestellt:
Code: Alles auswählen
tree1->setSelectionMode(QAbstractItemView::SingleSelection);
tree1->setDragEnabled(true);
tree1->setAcceptDrops(true);
tree1->setDropIndicatorShown(true);
tree2->setSelectionMode(QAbstractItemView::SingleSelection);
tree2->setDragEnabled(true);
tree2->setAcceptDrops(true);
tree2->setDropIndicatorShown(true);
Mit QAbstractItemView::ExtendedSelection funktioniert es auch nicht
Lg NoRulez
Verfasst: 25. Juni 2007 09:18
von @udisello
Also ich glaube, wir reden noch aneinander vorbei. Du sollst eine neue Klasse erstellen, die du von QTreeWidget ableitest. Dort überschreibst du die Funktionen, die ich gepostet habe. In deinem MainWindow erstellst du dir dann zwei Objekte( tree1, tree2 ) deiner neuen Klasse. Dann brauchst du theoretisch das target() gar nicht mehr, da das dropEvent an "zwei unterschiedlichen Stellen" eintritt.
Verfasst: 26. Juni 2007 16:13
von NoRulez
So jetzt ist alles klar und funktioniert prima
Danke vielmals
Habe nur noch ein winziges Problem.
Beim Drag and Drop scheint es von haus aus so zu sein das er einen Blauen balken als Drag Image hat. Kann man den irgendwie überschreiben/zeichnen?
Lg NoRulez