2013-08-18 15 views
6

Muszę stworzyć coś takiego jak interfejs iOS, pole 3x3 ikon, które można przeciągnąć w celu zmiany ich pozycji, a następnie zapamiętywać w pliku XML. Postanowiłem użyć klasy Grid (QWidget jest rodzicem) jako kontenera i moje własne klasy odziedziczone z QWidget jako elementy. Teraz próbuję dowiedzieć się, jak wykonać przeciągnięcie & drop dla QWidget, ale wydaje się, że jesteś w stanie rzucić tylko na QWidget, ale nie można go przeciągnąć. Czy to prawda, czy po prostu jestem opóźniony? Jak mogę to przenieść? x.xPrzeciąganie QWidget w QT 5

+0

Czy po prostu chcesz przenieść to lub przeciągnij/upuść? Po prostu przeniesienie jest łatwiejsze (http://stackoverflow.com/questions/12219727/dragging-moving-a-qpushbutton-in-pyqt), przeciąganie/upuszczanie staje się skomplikowane (http://stackoverflow.com/questions/24582383/qmimedata -stawianie-i-uzyskiwanie-właściwych-mime-typów-dla-dowolnych-widżetów). – neuronet

Odpowiedz

3

Przeciąganie widżetu nie jest takie proste. Mnóstwo kodowania musisz zrobić sam.

Z Qt Docs:

void MainWindow::mousePressEvent(QMouseEvent *event) 
{ 
    if (event->button() == Qt::LeftButton 
     && iconLabel->geometry().contains(event->pos())) { 

     QDrag *drag = new QDrag(this); 
     QMimeData *mimeData = new QMimeData; 

     mimeData->setText(commentEdit->toPlainText()); 
     drag->setMimeData(mimeData); 
     drag->setPixmap(iconPixmap); 

     Qt::DropAction dropAction = drag->exec(); 
     ... 
    } 
} 

Oznacza to, gdy widżet otrzymuje wiadomość, że ma być przeciągnięty, na przykład podobnie jak przy użyciu myszy, musi utworzyć obiekt QDrag.

W obiekcie QDrag można ustawić pixmapę, która reprezentuje przeciągnięty widget. Jeśli ukryjesz widżet w tym miejscu, wygląda na to, że wskaźnik myszy "wziął" widżet.

Dodatkowo potrzebny jest obiekt QMimeData. W tym miejscu możesz umieścić wszystkie rodzaje danych, które opisują Twój widget. W twoim przypadku użyj czegoś, co pozwoli ci zidentyfikować twój widget. Ponieważ, i tu pojawia się trudna część: Musisz wykonać ruchy samodzielnie.

Widżet będący rodzica siatki odbiera zdarzenie upuszczenia i odczytuje dane z mime, który to widget chce przenieść. Z QDropEvent otrzymuje punkt, w którym widżet ma zostać przeniesiony. To właśnie musisz zakodować: Rzeczywiste repozycjonowanie w układzie siatki. I nie zapomnij zaktualizować xml.

+0

a co dopiero pamiętam, który element się poruszał, czytam, na którym innym elemencie został on upuszczony, a następnie zapamiętaj drugi, zastąp go pierwszym i umieść drugi na miejscu pierwszego z addWidget() i removeWidget()? –

+0

@Leonid Bor, obiekt QDrag daje sposób na umieszczenie ikony pod wskaźnikiem myszy. I daje sposób przekazywania danych o przeciągniętym obiekcie do odbiornika kropel. Jeśli możesz uzyskać te informacje w przeciwnym razie ... nie ma problemu. addWidget() i removeWidget() są z pewnością jednym ze sposobów na wykonanie tego ruchu. – Greenflow

0

Wiki Qt zawiera przykład QtQuick opisujący emulację interfejsu ikony iOS za pomocą mniej niż 80 linii kodu.

Możesz go znaleźć here.

+0

thx, ale mój szef ograniczył mnie do korzystania z tego =/ –

+0

Myślę, że jeśli czytasz qml, możesz przetłumaczyć go na układ QGridLayout/QWidget. W końcu qml jest po prostu innym językiem opisującym układ. –

3

zrobić trick następnie można stanie przeciągnąć QWidget również

QPixmap *widgetPixmap = new QPixmap; 
yourWidget->render(widgetPixmap); // rendering the current widget to t_iconTPixmap 

teraz skorzystać z tej widgetPixmap jak pixmapy dla yourDragObject->setPixmap();

przykład

void MainWindow::mousePressEvent(QMouseEvent *event) 
{ 
if (event->button() == Qt::LeftButton 
    && iconLabel->geometry().contains(event->pos())) { 

    QDrag *drag = new QDrag(this); 
    QMimeData *mimeData = new QMimeData; 

    mimeData->setText(commentEdit->toPlainText()); 

    QPixmap *widgetPixmap = new QPixmap; 
    yourWidget->render(widgetPixmap); 

    drag->setMimeData(mimeData); 
    drag->setPixmap(widgetPixmap); 

    Qt::DropAction dropAction = drag->exec(); 
    ... 
    } 
} 
+0

Wystąpił błąd: nie można renderować z nieaktywnym malarzem – wutzebaer