【问题标题】:How to create a label with drag and drop function and with the clicked signal function QT如何使用拖放功能和点击信号功能 QT 创建标签
【发布时间】:2019-08-26 17:49:05
【问题描述】:

我正在开发一个程序,其中包含一个 MainWindow 和一个来自 QWidget 的名为 Diagrama 的小部件,它是我的主窗口的中心小部件。

在这个图表小部件中,我能够在我在屏幕上单击的位置创建一个标签,并且能够拖放这些相同的标签。

但是现在,我想添加一个功能,每次点击标签时都会获得点击信号。

我知道要启用标签的点击信号功能,我必须创建一个自定义标签的类,但是当我这样做并将类QLabel替换为代码中的customLabel类时,拖动并且 drop 函数停止工作。

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

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

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

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

我放这个是为了让你们知道我有整个过程的功能

现在我不知道该怎么办了。 我虽然我的customLabel 类的函数mousePressEvent 与我的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 类,以在每次单击标签时发出单击信号,但禁用拖放事件

【问题讨论】:

  • 你必须提供你的代码,而不仅仅是你的方法签名。
  • 你想要全部吗?
  • 重现您的问题的最小示例。

标签: c++ qt qt5


【解决方案1】:

点击必须在鼠标释放时注册,而不是鼠标按下。鼠标按下可以演变成不同的东西,这取决于用户下一步做什么。鼠标按下加移动或鼠标按下加长时间延迟演变为拖动操作。

因此您需要同时覆盖 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() 信号。

【讨论】:

    猜你喜欢
    • 2017-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    相关资源
    最近更新 更多