Evgenij LegotskojAug. 31, 2015, 10:39 a.m.

Qt/C++ - Lesson 013. QMenu – How to work with context menu in QTableView?

To use the context menu in Qt is used QMenu class. When performing actions that should cause the menu handler is called, which creates the menu and binds handlers to act in this menu.

In this lesson, work with the shortcut menu will be shown in the example code from the tutorial on working with QDataWidgetMapper. In this lesson, the two files from the previous lesson will be modified, but the project will not work if you do not include it as in the previous lesson files that can not be edited.

Project structure for QMenu

Project structure remains the same as in the tutorial, which is based on the lesson. Changes in the code will be subjected to only two files:

  • mainwindow.h
  • mainwindow.cpp

mainwindow.h

Declare additional slots in the header file. This slot to display the shortcut menu, and delete the record. It is also necessary to rewrite the signature slot for editing entries, it will be used as a method of determining the selected entry.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSqlTableModel>

#include <database.h>
#include <dialogadddevice.h>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_addDeviceButton_clicked();
    void slotUpdateModels();
    /* To the slot for editing entries are added to remove the recording SLOT. 
     * Also, add a slot for processing context menu
     * */
    void slotEditRecord();
    void slotRemoveRecord();
    void slotCustomMenuRequested(QPoint pos);

private:
    Ui::MainWindow              *ui;
    DataBase                    *db;
    QSqlTableModel              *modelDevice;

private:
    void setupModel(const QString &tableName, const QStringList &headers);
    void createUI();
};

#endif // MAINWINDOW_H

mainwindow.cpp

This file will need to add the inclusion of the context menu for the tableView. And write a method to handle the shortcut menu and delete the entry from the table and, respectively, from the database. Along the way, we rewrite and method for editing entries.

As a result, you should have an application that is accessed by pressing right mouse button on the entry in the table, a context menu with two options: Edit and Delete . By pressing the Edit item will bring up the dialog box, as is the case with the action double-click from the previous lesson. And by pressing the Delete item is called MessageBox with a question to confirm the deletion, in the case of an affirmative result is produced delete records in the table.

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

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    /* Program code without any changes in lesson on QDataWidgetMapper */
}

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

void MainWindow::setupModel(const QString &tableName, const QStringList &headers)
{
    /* Program code without any changes in lesson on QDataWidgetMapper */
}

void MainWindow::createUI() 
{
    ui->deviceTableView->setModel(modelDevice);
    ui->deviceTableView->setColumnHidden(0, true);
    ui->deviceTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->deviceTableView->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->deviceTableView->resizeColumnsToContents();
    ui->deviceTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->deviceTableView->horizontalHeader()->setStretchLastSection(true);

    // Set the Context Menu
    ui->deviceTableView->setContextMenuPolicy(Qt::CustomContextMenu);

    connect(ui->deviceTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(slotEditRecord()));
    // Connect SLOT to context menu
    connect(ui->deviceTableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotCustomMenuRequested(QPoint)));
}

void MainWindow::on_addDeviceButton_clicked()
{
    /* Program code without any changes in lesson on QDataWidgetMapper */
}

void MainWindow::slotCustomMenuRequested(QPoint pos)
{
    /* Create an object context menu */
    QMenu * menu = new QMenu(this);
    /* Create actions to the context menu */
    QAction * editDevice = new QAction(trUtf8("Редактировать"), this);
    QAction * deleteDevice = new QAction(trUtf8("Удалить"), this);
    /* Connect slot handlers for Action pop-up menu */
    connect(editDevice, SIGNAL(triggered()), this, SLOT(slotEditRecord()));     // Call Handler dialog editing
    connect(deleteDevice, SIGNAL(triggered()), this, SLOT(slotRemoveRecord())); // Handler delete records
    /* Set the actions to the menu */
    menu->addAction(editDevice);
    menu->addAction(deleteDevice);
    /* Call the context menu */
    menu->popup(ui->deviceTableView->viewport()->mapToGlobal(pos));
}

/* Slot to remove records from a table
 * */
void MainWindow::slotRemoveRecord()
{
    /* We find out which of the lines has been selected
     * */
    int row = ui->deviceTableView->selectionModel()->currentIndex().row();
    /* Check that the line was chosen
     * */
    if(row >= 0){
        /* We are asking the question, whether really delete the record. 
         * If yes - delete entry
         * */
        if (QMessageBox::warning(this,
                                 trUtf8("Удаление записи"),
                                 trUtf8("Вы уверены, что хотите удалить эту запись?"),
                                 QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
        {
            /* If the answer is do a rollback of actions and close the dialog box without deleting the entry
             * */
            QSqlDatabase::database().rollback();
            return;
        } else {
            /* Otherwise, we make the removal of records. 
             * Upon successful remotely update the table.
             * */
            if(!modelDevice->removeRow(row)){
                QMessageBox::warning(this,trUtf8("Уведомление"),
                                     trUtf8("Не удалось удалить запись\n"
                                            "Возможно она используется другими таблицами\n"
                                            "Проверьте все зависимости и повторите попытку"));
            }
            modelDevice->select();
            ui->deviceTableView->setCurrentIndex(modelDevice->index(-1, -1));
        }
    }
}

/* Slot update data representation model
 * */
void MainWindow::slotUpdateModels()
{
    modelDevice->select();
    ui->deviceTableView->resizeColumnsToContents();
}

/* Method for activating dialogue adding entries 
 * to the edit mode with the transmission of the selected row index
 * */
void MainWindow::slotEditRecord()
{
    /* Also, create a dialogue and connect it 
     * to signal the completion of the form slot refresh data representation model, 
     * but send as parameters recording line
     * */
    DialogAddDevice *addDeviceDialog = new DialogAddDevice(ui->deviceTableView->selectionModel()->currentIndex().row());
    connect(addDeviceDialog, SIGNAL(signalReady()), this, SLOT(slotUpdateModels()));

    /* Runs dialog box
     * */
    addDeviceDialog->setWindowTitle(trUtf8("Редактировать Устройство"));
    addDeviceDialog->exec();
}

Result

As a result, you have learned to call the context menu for the object QTableView and generally work with the class QMenu. Also, as a bonus issue was consecrated in parallel to remove records from a table, and a database with data representation model. Example QMenu behavior shown in the following video:

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate
AC

Доброго дня.
У меня вопрос по поводу нового синтаксиса.
Никак не могу разобраться с подключением СЛОТ-а

connect(ui->deviceTableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotCustomMenuRequested(QPoint)));

... делаю

connect(ui->deviceTableView, QOverload<const QPoint &>::of(&QWidget::customContextMenuRequested),
        this, QOverload<const QPoint &>::of(&MainWindow::slotCustomMenuRequested));

... но с ошибкой.

Добрый день. Если у вас нет перегрузок сигналов или слотов, то QOverload Вам не нужен

connect(ui->deviceTableView, &QWidget::customContextMenuRequested, this, &MainWindow::slotCustomMenuRequested);

Ошибка при компиляции? Или QtCreator подсвечивает что-то красным без компиляции? И почему не привели текст ошибки? Экстрасены в отпуске.

AC

Спасибо за ответ. Да перегрузок сигналов нет.

t

Добрый день,
в строке 49 файла mainwindow.cpp создаётся меню и оно будет создаваться каждый раз при его вызове. Т.е. каждый раз будет выделяться память под QMenu. Это же утечка памяти или Qt как то сам освобождает память при выходе их слота slotCustomMenuRequested?

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Timeweb

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting
ZK

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:60points,
  • Rating points-1
V

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:70points,
  • Rating points1
V

C++ - Тест 003. Условия и циклы

  • Result:71points,
  • Rating points1
Popular publications in the last 90 Days
Last comments
RS

Django - Tutorial 007. Adding Pagination based on django-bootstrap3

а как быть если нет базы и запроса в БД, а данные приходят по запросу в api стороннего сервера, а клиент серверное приложение на django и я хочу реализовать пагинацию на стороне django. В апи я …
e
  • ethen
  • Aug. 28, 2021, 3:49 p.m.

Release of the C++/Qt and QML application deployment utility CQtDeployer v1.5.0

Благодарю. Действительно, подменил файлы от версии 4.0, и все заработало)

Release of the C++/Qt and QML application deployment utility CQtDeployer v1.5.0

На данный момент Qt Installer Framework не поддерживает Windows 7 смотрите баг #2224
  • 4X_Pro
  • Aug. 26, 2021, 7:32 a.m.

Распознавание изображений на Python с помощью TensorFlow и Keras

Понимаю. А ещё понимаю, что не потратить время нельзя. День всё равно пройдёт, и вопрос только в том, на что он будет потрачен: на то, что приносит в жизни удовольствие или нет. Насчёт заст…
KS

Qt/C++ - Lesson 023. Moving QGraphicsItem on QGraphicsScene with mouse help

здравствуйте! Подскажите, пожалуйста, как можно на Вашем примере реализовать вывод контекстного меню при нажатии на квадрат правой кнопкой мыши с целью решения задач: изменить объект и удалить? …
Now discuss on the forum
EK

HTTP server на Qt

Мой файл webapp1.ini [listener];host=192.168.0.100port=8080minThreads=4maxThreads=100cleanupInterval=60000readTimeout=60000maxRequestSize=16000maxMultiPartSize=10000000…

QScrollArea dynamically add QCheckBoxes

Всё правильно. Это просто спамер, который отправился в вечный бан.
a
  • ad40
  • Sept. 15, 2021, 3:32 a.m.

Qt proxyModel

Добрый день! Разобрался с задачей! (иногда отвлеченное участие приводит к нахождению решения , так что не могу не выразить благодарность участникам данного форума) Все оказаолось дов…
JaM

Update data | Django, Ajax

Привет, добрался я к реализации системы общения, тут как раз получилось что попал на ваши статейки, все работает как часы, но осталась одна маленькая деталь, как обновлять сообщения в диалоге и …
DCh

Вызов функции Python с Qml

Всем здравствуйте. Незамысловатая задача появилась у меня - вызвать функцию Python с Qml. Смотрел уроки на этом сайте, но что-то я не понимаю. Сверял код Qt C++, вроде как всё также, …
About
Services
© EVILEG 2015-2021
Recommend hosting TIMEWEB