Страницы

Поиск по вопросам

четверг, 23 января 2020 г.

Вытягивания виджетов

#cpp #qt #gui #qt5 #интерфейс


Я работаю в qt5. Эта кнопка("addButton")  отвечает за создание этих кнопок("GreenButton")
. В слоте addButton создается GreenButton:

void SearchForm::on_AddButtonButton_pressed()
{
     Editor.pobj = new GreenButton(this);
}


Код GreenButton:

QPoint delta;

    void mousePressEvent(QMouseEvent* e)
        {
            delta.rx()   = e->pos().x();
            delta.ry()   = e->pos().y();
        }

        void mouseMoveEvent(QMouseEvent* e)
        {

            setGeometry(
                    geometry().x()  + e->pos().x() - delta.x(),
                    geometry().y()  + e->pos().y() - delta.y(),
                    width(),
                    height()
            );
        }

        explicit GreenButton(QWidget *parent = 0 ) 
        {


            setGeometry(QCursor::pos().x() - parent->geometry().x() - 8,
                        QCursor::pos().y() - parent->geometry().y() - 8,
                        111,
                        111
            );
            show();
            QMouseEvent event1(QEvent::MouseButtonPress,  this->pos(), Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);

            QApplication::sendEvent(this, &event1);
        }


GreenButton создается , перемещается мышью. Как сделать чтобы при нажатии на addButton
и не отпускании ее перемещался GreenButton?
Я думал поможет искуственное создание событий, но не помогло:

QMouseEvent event1(QEvent::MouseButtonPress,  this->pos(), Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);
QApplication::sendEvent(this, &event1);

    


Ответы

Ответ 1



Т.к. у нас есть форма, на которой размещена «добавляющая кнопка», и на ту же форму мы добавляем другие кнопки, предлагаю воспользоваться следующей стратегией: Устанавливаем фильтр сообщений на нашу «добавляющую» кнопку. Будем ловить нажатие и перемещение мыши. Во время нажатия будем создавать новую кнопку и запоминать её. Во время появления события перемещения, будем перемещать нашу кнопку. Всё это довольно просто реализовать: MainWindow.h: #pragma once #include class QPushButton; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget* parent = 0); bool eventFilter(QObject* obj, QEvent* event); private: QPushButton* m_CurrentButton; }; MainWindow.cpp: #include #include #include #include #include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { auto widget = new QWidget(this); auto addButton = new QPushButton("add", widget); setCentralWidget(widget); addButton->installEventFilter(this); } bool MainWindow::eventFilter(QObject* obj, QEvent* event) { if (event->type() == QEvent::MouseButtonPress) { auto mouseEvent = static_cast(event); m_CurrentButton = new QPushButton("new", centralWidget()); auto localPoint = mapFromGlobal(mouseEvent->globalPos()); m_CurrentButton->move(localPoint); m_CurrentButton->show(); return true; } if(event->type() == QEvent::MouseMove) { auto mouseEvent = static_cast(event); auto localPoint = mapFromGlobal(mouseEvent->globalPos()); m_CurrentButton->move(localPoint); return true; } return QObject::eventFilter(obj, event); } На базе этого кода, Вы можете адаптировать свой код.

Ответ 2



Сначала решение: class MyForm: public QWidget { QTimer * Ticker ; QPushButton * MovingButton; public: MyForm(QWidget * parent = nullptr) : QWidget (parent ) , Ticker (nullptr) , MovingButton(nullptr) { Ticker = new QTimer(this); connect(Ticker, &QTimer::timeout, this, &MyForm::moveButton); } ~MyForm() { stopMoving(); } public slots: void addPressed() { MovingButton = new QPushButton(this); // настраиваем новую кнопку MovingButton->show(); // Начинаем перемещение через пол секунды Ticker->setSigngleShot(true); Ticker->setInterval(500); Ticker->start(); } void addReleased() { stopMoving(); // останавливаем движение } void moveButton() { if(MovingButton) { if(Ticker->singleShot()) // ускоряем таймер до 30 мс { Tciker->setSignleShot(false); Ticker->setInterval(30); } // двигаем кнопку MovingButton->move(MovingButton->pos() + QPoint(8,8)); } } private: void stopMoving() { MovingButton = nullptr; Ticker->stop(); } }; Здесь addPressed() и addReleased() слоты которые должны быть подключены с сигналам кнопки AddButton pressed() и released() соответственно. Работает код следующим образом: В обработчике нажатия addPressed() создаем новую кнопку и запоминаем указатель на нее в MovingButton, потом стартуем таймер Ticker на пол секунды по окончании которого выполняем перемещение. Пол секунды нужно для того чтобы была пауза перед началом движения. В обработчике таймера Ticker moveButton() ускоряем таймер до 30 мс а также перемещаем текущую кнопку MovingButton если таковая имеется. В обработчике отпускания addRelease() просто зануляем указатель на перемещаемую кнопку MovingButton и останавливаем таймер Ticker - таким образом останаваливаем движение.

Ответ 3



предложу необычный вариант: - AddButton сделать наследником от GreenButton - Как только AddButton кликнули, что означает добавление, AddButton меняет своё рисование, на рисование предка. То есть, начинает рисоваться, как GreenButton. - Новый AddButton на месте старого можно сделать как в начале таскания, так и по его окончанию - зависит от сценария

Комментариев нет:

Отправить комментарий