Здравствуйте! Пытаюсь создать контекстное меню, которое будет вызываться при нажатии правой кнопки мыши. Проблема в том, что я создал класс, в котором собираюсь реализовать весь список контекстного меню, но теперь у меня не получается добавить его объект в основную программу, где я обрабатываю нажатие кнопок мыши. Подскажите, что я делаю неправильно?
Создаю класс для меню.
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"; } }
Привет! Можешь скинуть проект целиком?
А вообще вот я накидал простенький пример:
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()); }
@aveal Проект я добавил, если еще нужно. А на счет кода, то я сделал класс, в конструкторе которого все это создаю и в него же добавил строку для закрепления меню к позиции курсора (показана ниже). Но мне непонятна суть создания контекстного меню через строку setContextMenuPolicy(Qt::CustomContextMenu), потому что я просто все сделал в конструкторе класса.
menu->popup(QCursor::pos());
Еще появился вопрос по поводу того, как из конструктора контекстного меню брать результат работы тех или иных функций. Например, я хочу сделать на правую кнопку мыши вызов меню, в котором будут всякие разные поля по работе с графиком такие, как cut, properties, zoom, а чтобы не нагружать mainwindow.cpp я хочу всю логику, которая связана с настройкой графика, прописать в отдельном классе (ContextMenu), но как мне потом вставлять тот же измененный цвет графика в обработку правой кнопки мыши уже в сам mainwindow.cpp я не знаю.
Чтобы лучше было понятно о чем я говорю, добавил картинки. На них есть контекстное меню с полем properties, которое вызывает новую форму, а она все настройки после нажатия OK передает графику.
Может у кого-то есть исходники с простенькой программкой, в которой создается что-то похожее и при этом не запихивается все в один файл mainwindow? Потому что у меня идея только создать кучу переменных, а потом через какие-нибудь сетторы все это брать.
Еще есть идея сделать под каждую настройку сигнал в классе ContextMenu, а уже в главном файле под каждый сигнал сделать соответствующий слот.
@rodion-2 Либо все настройки упаковать в структуру, например, и пробрасывать одним слотом, либо через get().