CustomContextMenu 在给定点不显示 Qt c++

问题描述 投票:0回答:1

我已向标签添加了自定义上下文菜单。一切都很好,只是每次我右键单击时,它都会将其随机放置在屏幕上,并遵循对角线图案,它会到达屏幕的右下角,每次右键单击时都会停留在屏幕右下角。我已经打印了正在传递的 QPoint 对象,它没有给出错误或错误的点。 custom_menu.cpp 文件是

#include "custom_menu.h"
#include <iostream>

Menu::Menu(QWidget *parent) :
    QMenu(parent)
{
    QAction *action1 = addAction("Action1");
    connect(action1, &QAction::triggered, this, &Menu::onAction1Triggered);
}
void Menu::onAction1Triggered(){
    std::cout<<"Working";
}

void Menu::showMenu(const QPoint &pos)
{
    qDebug() << pos;
    exec(mapToGlobal(pos));
}

我的自定义标签类如下

QLabelDragDrop::QLabelDragDrop(QWidget *parent) : QLabel(parent)
{
    setAcceptDrops(true);
    setMouseTracking(true);
}

void QLabelDragDrop::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        drag_start_position = event->pos();
    }
}
void QLabelDragDrop::mouseMoveEvent(QMouseEvent *event){
    {
        if (!(event->buttons() & Qt::LeftButton)) {
            return;
        }
        if ((event->pos() - drag_start_position).manhattanLength() < QApplication::startDragDistance()) {
            return;
        }
        QDrag *drag = new QDrag(this);
        QMimeData *mimeData = new QMimeData;
        mimeData->setImageData(this->pixmap().toImage());
        drag->setMimeData(mimeData);
        QPixmap pixmap(this->size());
        QPainter painter(&pixmap);
        painter.drawPixmap(this->rect(), this->grab());
        painter.end();
        drag->setPixmap(pixmap);
        //drag->setHotSpot(event->pos() - parentWidget()->pos() - this->pos());
        drag->setHotSpot(event->pos()); // - this->pos()
        drag->exec(Qt::MoveAction);
    }
}

作为显示上下文菜单的标签的父级的自定义框架类是

custom_frame::custom_frame(QWidget *parent)
    : QFrame(parent)
{
    setAcceptDrops(true);
}

void custom_frame::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasImage()) {
        event->acceptProposedAction();
    }
}

void custom_frame::dropEvent(QDropEvent *event)
{
    if (event->mimeData()->hasImage()) {
        QLabel *label = qobject_cast<QLabel*>(event->source());
        if (label) {
            label->move(event->position().toPoint());
            event->setDropAction(Qt::MoveAction);
            event->accept();
            update();
        }

    }
}

void custom_frame::paintEvent(QPaintEvent* event) {
    QFrame::paintEvent(event);
    for (int i = 1; i<=label_count; i++){
        char c[] = "label_";
        QString num = QString::number(i);
        QString name = QString::fromUtf8(c, 6);
        QLabel* my_label = this->findChild<QLabel*>(name + num);
        QPainter painter(this);
        painter.setPen(QPen(Qt::black, 2));
        QPoint start = my_label->frameGeometry().center();
        QGroupBox* groupBox = this->findChild<QGroupBox*>("groupBox");
        QPoint end = groupBox->frameGeometry().center();
        painter.drawLine(start, end);
    }
}

mainwindow.cpp文件如下

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QObject::connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::Create_Device);
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::Create_Device(){
    QLabelDragDrop *label = new QLabelDragDrop(ui->frame);
    label->setGeometry(QRect(200,20,80,40));
    ui->frame->label_count++;
    char c[] = "label_";
    QString num = QString::number(ui->frame->label_count);
    QString name = QString::fromUtf8(c, 6);
    QString obj_name = name+num;
    Menu *m_menu = new Menu;
    QPixmap pixmap("C:\\Users\\Farhan Ahmed\\Documents\\untitled\\router.png");
    QPixmap scaledPixmap = pixmap.scaled(QSize(70, 70), Qt::KeepAspectRatio, Qt::SmoothTransformation);    
    label->setObjectName(obj_name);
    //label->setText("New Label");
    label->setPixmap(scaledPixmap);
    label->setContextMenuPolicy(Qt::CustomContextMenu);
    label->setFixedSize(scaledPixmap.size());
    label->setToolTip(obj_name);
    label->setStatusTip(obj_name);
    bool success = connect(label, &QWidget::customContextMenuRequested, m_menu, &Menu::showMenu);
    Q_ASSERT(success);
    label->show();
    ui->frame->update();
}

我知道这是很多代码。我将总结与问题相关的部分。 QDragDropLabel 是在 mainwindow.h 中的 Create_Devices() 函数中创建的。菜单栏也添加在那里。连接的插槽位于 custom_menu.h 中,函数名称为 showMenu() 如果我不移动鼠标并一次又一次执行右键,pos 会打印相同的内容。但自定义菜单每次都会显示在新位置 感谢您提前提供任何帮助。

c++ qt qt-creator qt6
1个回答
1
投票

问题:

CustomContextMenu 在给定点不显示 Qt c++

这是一个错误的陈述,您的菜单恰好出现在您正在喂食的

pos
处。

G.M. 说:

传递给

Menu::showMenu
的 pos 参数是相对于正在请求菜单的小部件的位置,而不是相对于菜单本身。所以
exec(mapToGlobal(pos))
可能是罪魁祸首。

我将添加以下内容:

来自Qt6的文档:mapToGlobal():

将小部件坐标 pos 转换为全局屏幕坐标。例如,mapToGlobal(QPointF(0,0)) 将给出小部件左上角像素的全局坐标。

上下文菜单的默认位置是屏幕的左上角,即(x=0,y=0)。因此,当您传递

pos
时,它将返回菜单的当前全局位置,加上
pos
,即光标相对于标签的当前位置。这就是为什么它总是递增,而如果您不移动光标,该消息会为您提供相同的结果。

如果我被要求用方程式总结问题,我会使用这个:

menu.globalDiagonalAnimation() = menu.globalPos() + cursor.localPos(label)

更正:

所以你的问题应该是:

如何在Qt中的光标位置显示上下文菜单?

解决方案:

哪个答案是简单地使用QCursor::pos():

返回主屏幕光标(热点)在全局屏幕坐标中的位置。

exec(QCursor::pos());

阅读我自己的答案后,我能够了解如何转换位置,这是一个与您尝试执行的解决方案类似的解决方案:

auto *w = static_cast<QLabel*>(parent());

exec(w->mapToGlobal(pos));

必须将标签设置为菜单的父级,然后使用其

mapToGlobal()
,将
pos
转换为全局位置。

静态转换是必要的,因为如果您使用

parent()
,您将得到一个
QObject
,而它没有
mapToGlobal()
作为成员。

© www.soinside.com 2019 - 2024. All rights reserved.