Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved Drag & Drop d'un Widget

    French
    drag&drop widget drag and drop
    2
    5
    437
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • M
      Morgatte last edited by

      Bonjour,

      J'ai testé pleins de choses pour déplacer/déposer un Widget et rien n'y fait.
      J'ai testé les pages suivantes sans succès jusqu'à maintenant :
      [https://askcodez.com/en-faisant-glisser-un-qwidget-dans-qt-5.html"]https://askcodez.com/en-faisant-glisser-un-qwidget-dans-qt-5.html](link url)
      [https://qt.developpez.com/doc/4.7/dnd/"]https://qt.developpez.com/doc/4.7/dnd/](link url)
      Et autres :
      [https://doc.qt.io/qt-5/examples-draganddrop.html"]https://doc.qt.io/qt-5/examples-draganddrop.html](link url)

      1.png

      J'aimerais pouvoir déplacer le Widget Vert nommé Navire1.
      Son parent est lui-même un Widget (la barre Bleue) nommé TimeLine1

      Je n'arrive pas à Dragger un Widget dans un Widget.

      Auriez vous un code pour une situation similaire ?

      1 Reply Last reply Reply Quote 0
      • SGaist
        SGaist Lifetime Qt Champion last edited by

        Bonsoir,

        En fonction du but de la manœuvre, il est plus simple de générer une image du widget à la bonne taille et d'utiliser QDrag de manière classique, quand le drop est exécuté, déplacer le widget à ce moment là.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply Reply Quote 0
        • M
          Morgatte last edited by Morgatte

          Bonjour,

          Houlà, je n'en suis pas là !
          Oui en lisant j'ai cru comprendre qu'il était possible de faire une copie sous forme d'image du widget à déplacer (QByteArray), mais j'ai des soucis plus basics.

          Que l'on voit la trace du widget en train de se déplacer, c'est super, mais là je n'arrive même pas à déplacer quoique ce soit. En fait dès le départ, j'ai un doute sur le widget sur lequel sont appliqué certaines fonctions.

          En particulier dans cette page link text je vois que mousePressEvent() est appliqué des fois sur MainWindows d'autres fois sur DragWidget.

          Ce n'est pas clair. DragWidget est-il le Widget à déplacer ou bien est-ce MainWindow qui a été renommé pour un second exemple ?

          Moi, j'ai un widget (déplaçable) contenu dans un widget (parent).
          A qui attribue-je ces différentes fonctions ?
          QDragEnterEvent
          QDragLeaveEvent
          QDragMoveEvent
          QDropEvent
          Au parent ou au widget déplaçable ? (ou un mixte ?)

          Merci.

          1 Reply Last reply Reply Quote 0
          • SGaist
            SGaist Lifetime Qt Champion last edited by

            Les deux widgets sont là pour présenter deux cas de figures différents. Ils n'ont aucun lien l'un avec l'autre hormis que les deux font usage de D'n'D.

            Aucun des deux n'est déplacé en fait. Le drag and drop est utilisé en général comme pour le déplacement de fichiers dans l'explorateur.

            L'exemple fridge magnets pourrait être un bon point de départ.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply Reply Quote 0
            • M
              Morgatte last edited by

              J'ai fini par réussir à partir de l'exemple cité ci-dessu.

              Voici le code :

              mainwidget.h

              #ifndef WIDGETPARENT_H
              #define WIDGETPARENT_H
              
              
              
              #include <QObject>
              #include <QtWidgets>
              #include <QPainter>
              #include <QPen>
              
              
              QT_BEGIN_NAMESPACE
              class QDragEnterEvent;
              class QDropEvent;
              QT_END_NAMESPACE
              
              
              
              class MainWidget : public QWidget
              {
                  Q_OBJECT
              public:
                  explicit MainWidget(QWidget *parent = nullptr);
              
              protected:
                  void paintEvent(QPaintEvent *event) override;
              
                  void dragEnterEvent(QDragEnterEvent *event) override;
                  void dragMoveEvent(QDragMoveEvent *event) override;
                  void dropEvent(QDropEvent *event) override;
                  void mousePressEvent(QMouseEvent *event) override;
              
              
              signals:
              
              public slots:
              
              };
              
              
              #endif // WIDGETPARENT_H
              
              

              mainwindow.h

              #ifndef MAINWINDOW_H
              #define MAINWINDOW_H
              
              #include <QObject>
              #include <QWidget>
              
              
              class MainWindow : public QWidget
              {
              public:
                  explicit MainWindow(QWidget *parent = nullptr);
              
              protected:
              
              
              };
              
              
              #endif // MAINWINDOW_H
              
              

              movable_child_widget.h

              #ifndef MOVABLE_CHILD_WIDGET_H
              #define MOVABLE_CHILD_WIDGET_H
              
              #include <QtWidgets>
              #include <QLabel>
              
              
              
              class Movable_Child_Widget : public QLabel
              {
              public:
                  Movable_Child_Widget(const QString &text, QWidget *parent);
                  QString labelText() const;
              
              private:
                  QString m_labelText;
              };
              
              
              #endif // MOVABLE_CHILD_WIDGET_H
              
              

              main.cpp

              #include <QApplication>
              #include "mainwindow.h"
              
              
              
              int main(int argc, char *argv[])
              {
                  QApplication app(argc, argv);
              
              #ifdef QT_KEYPAD_NAVIGATION
                  QApplication::setNavigationMode(Qt::NavigationModeCursorAuto);
              #endif
              
                  MainWindow window;
              
                  bool smallScreen = QApplication::arguments().contains(QStringLiteral("-small-screen"));
                  if (smallScreen)
                      window.showFullScreen();
                  else
                      window.show();
              
                  return app.exec();
              }
              
              

              mainwidget.cpp

              #include "mainwidget.h"
              #include "movable_child_widget.h"
              
              
              static inline QString MemeFamilleDeProgrammes() { return QStringLiteral("application/x-ceTypeDeProgramme"); }
              // MemeFamilleDeProgrammes définit un type personnalisé de données à transmettre au presse papier.
              // Si deux occurences de ce même programme sont lancées, il sera ainsi possible de passer des widgets
              // d'un programme à l'autre.
              
              
              
              
              MainWidget::MainWidget(QWidget *parent)
                  : QWidget(parent)
              {
                  this->setFixedWidth(1000);
                  this->setFixedHeight(100);
              
                  Movable_Child_Widget *newChild = new Movable_Child_Widget("Child widget", this);
                  newChild->setAttribute(Qt::WA_DeleteOnClose);
              
                  QPalette pal = QPalette();
                  this->setGeometry(0, 0, 600, 100);
                  pal.setColor(QPalette::Window, QColor("#CC773C")); this->setAutoFillBackground(true); this->setPalette(pal);
              
                  setAcceptDrops(true);       // <------------------------ Important de le mettre dans le parent du widget à déplacer
              }
              
              
              
              
              
              void MainWidget::paintEvent(QPaintEvent *event)
              {
                  Q_UNUSED(event);
              
              
                  QPainter painter(this);
                  painter.setPen(Qt::blue);
                  //painter.setBrush(QBrush("#539e47"));
                  painter.drawRect(0, 0, this->width()-1, this->height()-1);
              
              
                  // on place les quarts d'heures
                  QPen pen0(Qt::green);
                  pen0.setWidth(1);
                  pen0.setStyle(Qt::DashDotLine);
                  painter.setPen(pen0);
                  for (int i=0; i<=24*4; i++){
                      painter.drawLine(int (i*this->width()/96),int (0.5*this->height()-10), int (i*this->width()/96), int (0.5*this->height()+10));
                  }
              
                  // on place les heures
                  QPen pen1(Qt::blue);
                  pen1.setWidth(3);
                  painter.setPen(pen1);
                  //painter.setPen(Qt::blue);
                  for (int i=0; i<=24; i++){
                      painter.drawLine(int (i*this->width()/24), int (0.5*this->height()-10), int (i*this->width()/24), int (0.5*this->height()+10));
                  }
              
                  //updateGeometry();
              }
              
              
              
              
              
              void MainWidget::dragEnterEvent(QDragEnterEvent *event)
              {
                  if (event->mimeData()->hasFormat(MemeFamilleDeProgrammes())) {
                      if (children().contains(event->source())) {
                          event->setDropAction(Qt::MoveAction);
                          event->accept();
                      } else {
                          event->acceptProposedAction();
                      }
              
                  } else if (event->mimeData()->hasText()) {
                      event->acceptProposedAction();
                  } else {
                      event->ignore();
                  }
              
              }
              
              
              
              void MainWidget::dragMoveEvent(QDragMoveEvent *event)
              {
                  if (event->mimeData()->hasFormat(MemeFamilleDeProgrammes())) {
                      if (children().contains(event->source())) {
                          event->setDropAction(Qt::MoveAction);
                          event->accept();
                      } else {
                          event->acceptProposedAction();
                      }
                  } else if (event->mimeData()->hasText()) {
                      event->acceptProposedAction();
                  } else {
                      event->ignore();
                  }
              
              }
              
              
              
              
              void MainWidget::dropEvent(QDropEvent *event)
              {
                  if (event->mimeData()->hasFormat(MemeFamilleDeProgrammes())) {
                      const QMimeData *mime = event->mimeData();
              
                      QByteArray itemData = mime->data(MemeFamilleDeProgrammes());
                      QDataStream dataStream(&itemData, QIODevice::ReadOnly);
              
                      QString text;
                      QPoint offset;
                      dataStream >> text >> offset;
                      Movable_Child_Widget *newChild = new Movable_Child_Widget(text, this);
                      newChild->move(event->pos() - offset);
                      newChild->show();
                      newChild->setAttribute(Qt::WA_DeleteOnClose);
              
                      if (event->source() == this) {
                          event->setDropAction(Qt::MoveAction);
                          event->accept();
                      } else {
                          event->acceptProposedAction();
                      }
              
                  } else if (event->mimeData()->hasText()) {
                      QStringList pieces = event->mimeData()->text().split(QRegularExpression(QStringLiteral("\\s+")));
                      QPoint position = event->pos();
              
                      for (const QString &piece : pieces) {
                          Movable_Child_Widget *newChild = new Movable_Child_Widget(piece, this);
                          newChild->move(position);
                          newChild->show();
                          newChild->setAttribute(Qt::WA_DeleteOnClose);
              
                          position += QPoint(newChild->width(), 0);
                      }
              
                      event->acceptProposedAction();
                  } else {
                      event->ignore();
                  }
              }
              
              
              
              void MainWidget::mousePressEvent(QMouseEvent *event)
              {
                  Movable_Child_Widget *child = static_cast<Movable_Child_Widget*>(childAt(event->pos()));
                  if (!child)
                      return;
              
                  QPoint hotSpot = event->pos() - child->pos();
              
                  QByteArray itemData;
                  QDataStream dataStream(&itemData, QIODevice::WriteOnly);
                  dataStream << child->labelText() << QPoint(hotSpot);
              
                  QMimeData *mimeData = new QMimeData;
                  mimeData->setData(MemeFamilleDeProgrammes(), itemData);
                  mimeData->setText(child->labelText());
              
                  QDrag *drag = new QDrag(this);
                  drag->setMimeData(mimeData);
              
                  const QPixmap *ch = child->pixmap();     drag->setPixmap(*ch);
              
                  drag->setHotSpot(hotSpot);
              
                  child->hide();
              
                  //if (drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::CopyAction) == Qt::MoveAction)
                  if (drag->exec(Qt::MoveAction))
                      child->close();
                  else
                      child->show();
              }
              

              mainwindow.cpp

              #include "movable_child_widget.h"
              #include "mainwindow.h"
              #include "mainwidget.h"
              
              
              
              
              MainWindow::MainWindow(QWidget *parent)
                  : QWidget(parent)
              {
                  setWindowTitle(tr("Fenêtre principale"));            //
                  QPalette newPalette = palette();                     // Fenêtre principale
                  newPalette.setColor(QPalette::Window, Qt::gray);     //
                  setPalette(newPalette);                              //
                  this->setWindowState(Qt::WindowMaximized);           //
                  this->setFixedSize(2000, 1000);           //
              
              
                  MainWidget *Widget1 = new MainWidget(this);          // Création d'un premier widget
                  Widget1->move(200, 200);                             //
              
                  MainWidget *Widget2 = new MainWidget(this);          // Création d'un second widget
                  Widget2->move(200, 400);                             //
              
              }
              

              movable_child_widget.cpp

              #include "movable_child_widget.h"
              
              
              
              Movable_Child_Widget::Movable_Child_Widget(const QString &text, QWidget *parent)
                  : QLabel(parent)
              {
                  QFontMetrics metric(font());
                  QSize size = metric.size(Qt::TextSingleLine, text);
              
                  QImage image(size.width() + 12, size.height() + 12, QImage::Format_ARGB32_Premultiplied);
                  image.fill(qRgba(0, 0, 0, 0));
              
                  QFont font;
                  font.setStyleStrategy(QFont::ForceOutline);
              
                  QLinearGradient gradient(0, 0, 0, image.height()-1);
                  gradient.setColorAt(0.0, Qt::white);
                  gradient.setColorAt(0.2, QColor(200, 200, 255));
                  gradient.setColorAt(0.8, QColor(200, 200, 255));
                  gradient.setColorAt(1.0, QColor(127, 127, 200));
              
                  QPainter painter;
                  painter.begin(&image);
                  painter.setRenderHint(QPainter::Antialiasing);
                  painter.setBrush(gradient);
                  painter.drawRoundedRect(QRectF(0.5, 0.5, image.width()-1, image.height()-1), 25, 25, Qt::RelativeSize);
              
                  painter.setFont(font);
                  painter.setBrush(Qt::black);
                  painter.drawText(QRect(QPoint(6, 6), size), Qt::AlignCenter, text);
                  painter.end();
              
                  QPushButton *bt = new QPushButton ("bt", this);
                  bt->move(this->width()/2, 0);
              
                  setPixmap(QPixmap::fromImage(image));
              
                  m_labelText = text;
              }
              
              
              QString Movable_Child_Widget::labelText() const
              {
                  return m_labelText;
              }
              
              
              1 Reply Last reply Reply Quote 1
              • First post
                Last post