我已向标签添加了自定义上下文菜单。一切都很好,只是每次我右键单击时,它都会将其随机放置在屏幕上,并遵循对角线图案,它会到达屏幕的右下角,每次右键单击时都会停留在屏幕右下角。我已经打印了正在传递的 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 会打印相同的内容。但自定义菜单每次都会显示在新位置 感谢您提前提供任何帮助。
CustomContextMenu 在给定点不显示 Qt c++
这是一个错误的陈述,您的菜单恰好出现在您正在喂食的
pos
处。
G.M. 说:
传递给
的 pos 参数是相对于正在请求菜单的小部件的位置,而不是相对于菜单本身。所以Menu::showMenu
可能是罪魁祸首。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()
作为成员。