Как создать метку с помощью функции перетаскивания и функции сигнала QT - PullRequest
1 голос
/ 05 апреля 2019

Я разрабатываю программу, которая содержит MainWindow и виджет Diagrama из QWidget, который является центральным виджетом моего главного окна.

В этом виджете Diagrama у меня есть возможность создать меткув положении, в котором я щелкнул по экрану, и возможность перетаскивать капли тех же самых ярлыков.

Но теперь я хочу добавить возможность получать сигнал щелчка по ярлыку каждый раз, когда я нажимаю на него.

Я знаю, что для включения функции сигнала щелчка метки мне нужно создать класс пользовательской метки, но когда я это делаю, я заменяю класс QLabel на класс customLabel вкод, функция перетаскивания перестает работать.

void Diagrama::dragEnterEvent(QDragEnterEvent *event)
{....}

void Diagrama::dragMoveEvent(QDragMoveEvent *event)
{....}

void Diagrama::dropEvent(QDropEvent *event)
{....}

void Diagrama::mousePressEvent(QMouseEvent *event)
{....}

Я ставлю это только для того, чтобы вы, ребята, знали, что у меня есть функция для всего процесса

И теперь я не знаю, чтосделать.Я думаю, что есть конфликт функции mousePressEvent моего customLabel класса и той же функции в моем Diagrama классе.

Как я могу ее решить?


void Diagrama::dragMoveEvent(QDragMoveEvent *event)
{
    if (event->mimeData()->hasFormat("application/x-dnditemdata")) {
        if (event->source() == this) {
            event->setDropAction(Qt::MoveAction);
            event->accept();
        } else {
            event->acceptProposedAction();
        }
    } else {
        event->ignore();
    }
}

void Diagrama::dropEvent(QDropEvent *event)
{
    if (event->mimeData()->hasFormat("application/x-dnditemdata")) {
        QByteArray itemData = event->mimeData()->data("application/x-dnditemdata");
        QDataStream dataStream(&itemData, QIODevice::ReadOnly);

        QPixmap pixmap;
        QPoint offset;
        dataStream >> pixmap >> offset;

        QLabel *newIcon = new QLabel(this);
        newIcon->setPixmap(pixmap);
        newIcon->move(event->pos() - offset);
        newIcon->show();
        newIcon->setAttribute(Qt::WA_DeleteOnClose);

        if (event->source() == this) {
            event->setDropAction(Qt::MoveAction);
            event->accept();
        } else {
            event->acceptProposedAction();
        }
    } else {
        event->ignore();
    }
}

void Diagrama::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    painter.drawImage(0,0,*mImage);
    e->accept();
}

void Diagrama::mousePressEvent(QMouseEvent *event)
{


    if(modo=="trafo")
    {
        if(event->button()==Qt::LeftButton){
            QLabel *child = static_cast<QLabel*>(childAt(event->pos()));
            if (!child)
                return;

            QPixmap pixmap = *child->pixmap();

            QByteArray itemData;
            QDataStream dataStream(&itemData, QIODevice::WriteOnly);
            dataStream << pixmap << QPoint(event->pos() - child->pos());

            QMimeData *mimeData = new QMimeData;
            mimeData->setData("application/x-dnditemdata", itemData);

            QDrag *drag = new QDrag(this);
            drag->setMimeData(mimeData);
            drag->setPixmap(pixmap);
            drag->setHotSpot(event->pos() - child->pos());

            QPixmap tempPixmap = pixmap;
            QPainter painter;
            painter.begin(&tempPixmap);
            painter.fillRect(pixmap.rect(), QColor(127, 127, 127, 127));
            painter.end();

            child->setPixmap(tempPixmap);

            if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction) {
                child->close();
            } else {
                child->show();
                child->setPixmap(pixmap);
            }
        }
        else if(event->button()==Qt::RightButton)
        {

            QLabel *child = new QLabel(this);
            child->setPixmap(QPixmap(url_trafo));
            child->move(event->x(),event->y());
            child->show();

        }

    }
    else if(modo=="linha")
    {
        if(event->button()==Qt::RightButton){
            p_ini=event->pos();
             drawing=true;
            event->accept();}

        else {
            event->ignore();
            drawing=false;
        }
    }

}

Это является причиной событий перетаскивания и добавления метки каждый раз, когда я нажимаю на экран

Я пытался создать класс customLabel, который будет выдавать сигнал щелчка при каждом нажатииметка, но отключить событие перетаскивания

1 Ответ

0 голосов
/ 05 апреля 2019

Клик должен быть зарегистрирован при отпускании мыши, а не при нажатии мыши.Нажатие мыши может эволюционировать в разные вещи, в зависимости от того, что пользователь делает дальше.Нажатие мыши плюс перемещение или нажатие мыши плюс длительная задержка превращаются в операцию перетаскивания.

Таким образом, вам необходимо переопределить как mousePressEvent(), так и mouseReleaseEvent().

в вашем mousePressEvent()Вы должны сэкономить время, когда пресса произошла, а также позицию.Затем вы вызываете QLabel::mousePressEvent() и передаете ему событие, чтобы QLabel все еще мог обнаруживать операции перетаскивания.

В вашем mouseReleaseEvent() вам необходимо сравнить текущее время со временем нажатия.Если разница больше, чем QApplication :: startDragTime , или положение отпускания мыши по сравнению с положением нажатия мыши находится дальше, чем QApplication :: startDragDistance , или положение находится за пределамиметка, то вы не рассматриваете отпуск мыши как щелчок.Наконец, перенаправьте событие в переопределенное QLabel::mouseReleaseEvent(), чтобы базовый класс знал, что событие нажатия мыши завершилось.

Вот пример реализации ClickableQLabel:

#include <QApplication>
#include <QElapsedTimer>
#include <QLabel>
#include <QPoint>

class ClickableQLabel: public QLabel
{
    Q_OBJECT

public:
    explicit ClickableQLabel(QWidget* parent = nullptr)
        : QLabel(parent)
    {}

signals:
    void clicked();

protected:
    void mousePressEvent(QMouseEvent* e) override
    {
        QLabel::mousePressEvent(e);
        if (e->button() != Qt::LeftButton) {
            rerurn;
        }
        mouse_press_time_.start();
        mouse_press_pos_ = e->pos();
        e->accept();
    }

    void mouseReleaseEvent(QMouseEvent* e) override
    {
        QLabel::mouseReleaseEvent(e);
        if (!rect().contains(e->pos(), true)
            || e->button() != Qt::LeftButton
            || !mouse_press_time_.isValid()
            || mouse_press_pos_.isNull()
            || mouse_press_time_.hasExpired(QApplication::startDragTime())
            || (e->pos() - mouse_press_pos_).manhattanLength() >= QApplication::startDragDistance())
        {
            // Not a click.
            return;
        }
        e->accept();
        mouse_press_time_.invalidate();
        mouse_press_pos_ = QPoint();
        emit clicked();
    }

private:
    QElapsedTimer mouse_press_time_;
    QPoint mouse_press_pos_;
};

Если вы хотите сейчасчто-то случится при нажатии на ярлык, подключите сигнал clicked().

...