Top.Mail.Ru
Уведомления
Очистить все

[Решено] Как создать контекстное меню?

(@rodion-2)
Level 3

Здравствуйте! Пытаюсь создать контекстное меню, которое будет вызываться при нажатии правой кнопки мыши. Проблема в том, что я создал класс, в котором собираюсь реализовать весь список контекстного меню, но теперь у меня не получается добавить его объект в основную программу, где я обрабатываю нажатие кнопок мыши. Подскажите, что я делаю неправильно?

Создаю класс для меню. 

h - файл

#include <QWidget>
#include <QMenu>
#include <QDebug>
#include <QInputEvent>

class ContextMenu : public QWidget
{
    Q_OBJECT

public:
    ContextMenu(QWidget* parent = 0);
    ~ContextMenu()
    {
//        delete menu;
//        delete widget;
        qDebug() << "Destructor of ContextMenu class";
    }

protected:
    void contextMenuEvent(QContextMenuEvent* event) override;

private slots:
    void slotPropertiesGraph();
    void slotItem1();
    void slotItem2();
    void slotItem3();

private:
    QMenu *menu;
    QWidget *widget;
    QAction *propGrahp;
    QAction *item1;
    QAction *item2;
    QAction *item3;
};

cpp - файл

#include "contextmenu.h"

ContextMenu::ContextMenu(QWidget* parent) : QWidget(parent)
{
//    widget = new QWidget;
//    widget->setContextMenuPolicy(Qt::CustomContextMenu);

//    parent->setContextMenuPolicy(Qt::CustomContextMenu);

    menu = new QMenu(this);
    propGrahp = new QAction("Prorerties", this);
    item1     = new QAction("Item1", this);
    item2     = new QAction("Item2", this);
    item3     = new QAction("Item3", this);

    menu->addAction(propGrahp);
    menu->addAction(item1);
    menu->addAction(item2);
    menu->addAction(item3);

    connect(propGrahp, &QAction::triggered, this, &ContextMenu::slotPropertiesGraph);
    connect(item1,     &QAction::triggered, this, &ContextMenu::slotItem1);
    connect(item2,     &QAction::triggered, this, &ContextMenu::slotItem2);
    connect(item3,     &QAction::triggered, this, &ContextMenu::slotItem3);

    qDebug() << "Construtor of ContextMenu class";
}

void ContextMenu::contextMenuEvent(QContextMenuEvent* event)
{
    menu->exec(event->globalPos());
    qDebug() << "contextMenuEvent";

//    connect(widget, &QWidget::customContextMenuRequested, this, &ContextMenu::slotCustomMenuRequested);

}
void ContextMenu::contextMenuEvent(QContextMenuEvent* event)
{
    menu->exec(event->globalPos());
    qDebug() << "contextMenuEvent";

//    connect(widget, &QWidget::customContextMenuRequested, this, &ContextMenu::slotCustomMenuRequested);

}

void ContextMenu::slotPropertiesGraph()
{
    qDebug() << "properties graph!!!";
}

void ContextMenu::slotItem1()
{
    qDebug() << "Item1";
}

void ContextMenu::slotItem2()
{
    qDebug() << "Item2";
}

void ContextMenu::slotItem3()
{
    qDebug() << "Item3";
}

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

void MainWindow::mousePress(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        posCursor = event->pos();
        QWidget *widFocus = QApplication::focusWidget();

        for (QCustomPlot *w : widgetList)
        {
            if (widFocus->objectName() == w->objectName())
            {
                sctRect = new SelectedRect(QRubberBand::Rectangle, w);
                sctRect->setGeometry(QRect(posCursor, QSize()));
                sctRect->show();

                qDebug() << "press";
                qDebug() << "pos: " << event->localPos();
            }
        }
    }
    else if (event->button() == Qt::RightButton)
    {
//        ui->osc->setContextMenuPolicy(Qt::ActionsContextMenu);
//        ui->spectrum->setContextMenuPolicy(Qt::ActionsContextMenu);
        cMenu = new ContextMenu(ui->osc);
        cMenu->setVisible(true);

        qDebug() << "RightButton";
    }
}
Цитата
Создатель темы Размещено : 02.04.2022 23:02
Aveal
(@aveal)
Top level Admin

Привет! Можешь скинуть проект целиком?

ОтветитьЦитата
Размещено : 03.04.2022 11:20
Aveal
(@aveal)
Top level Admin

А вообще вот я накидал простенький пример:

изображение

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H



#include 



QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE



class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void customContextMenuRequestedSlot();

private:
    Ui::MainWindow *ui;
};



#endif // MAINWINDOW_H

MainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"



MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(this, &MainWindow::customContextMenuRequested, this, &MainWindow::customContextMenuRequestedSlot);
}



MainWindow::~MainWindow()
{
    delete ui;
}



void MainWindow::customContextMenuRequestedSlot()
{
    QMenu* menu = new QMenu(this);

    QAction* closeAction = new QAction(("Close"), this);
    connect(closeAction, &QAction::triggered, this, &MainWindow::close);

    menu->addAction(closeAction);
    menu->popup(QCursor::pos());
}

 

 

ОтветитьЦитата
Размещено : 03.04.2022 11:33
(@rodion-2)
Level 3

@aveal Проект я добавил, если еще нужно. А на счет кода, то я сделал класс, в конструкторе которого все это создаю и в него же добавил строку для закрепления меню к позиции курсора (показана ниже). Но мне непонятна суть создания контекстного меню через строку setContextMenuPolicy(Qt::CustomContextMenu), потому что я просто все сделал в конструкторе класса.

menu->popup(QCursor::pos());

Еще появился вопрос по поводу того, как из конструктора контекстного меню брать результат работы тех или иных функций. Например, я хочу сделать на правую кнопку мыши вызов меню, в котором будут всякие разные поля по работе с графиком такие, как cut, properties, zoom, а чтобы не нагружать mainwindow.cpp я хочу всю логику, которая связана с настройкой графика, прописать в отдельном классе (ContextMenu), но как мне потом вставлять тот же измененный цвет графика в обработку правой кнопки мыши уже в сам mainwindow.cpp я не знаю. 

1
3
2
4

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

Может у кого-то есть исходники с простенькой программкой, в которой создается что-то похожее и при этом не запихивается все в один файл mainwindow? Потому что у меня идея только создать кучу переменных, а потом через какие-нибудь сетторы все это брать.

ОтветитьЦитата
Создатель темы Размещено : 03.04.2022 18:44
(@rodion-2)
Level 3

Еще есть идея сделать под каждую настройку сигнал в классе ContextMenu, а уже в главном файле под каждый сигнал сделать соответствующий слот.

ОтветитьЦитата
Создатель темы Размещено : 03.04.2022 21:10
Aveal
(@aveal)
Top level Admin

@rodion-2 Либо все настройки упаковать в структуру, например, и пробрасывать одним слотом, либо через get().

ОтветитьЦитата
Размещено : 04.04.2022 08:51
(@rodion-2)
Level 3

@aveal А вот это отличное решение 

ОтветитьЦитата
Создатель темы Размещено : 05.04.2022 22:17
Поделиться: