I want to know how can I open a popup menu when I right click on the table items. In the popup menu some actions like add and delete should be given, which will create a new row or delete the selected row.
I am a new in the Qt world, so if anybody can give me the full details (with code if possible) then I will be really grateful towards him/her.
Thank you.
My goal: Only in the area of QListWidget
and only if you click on an item, the menu with Delete will be opened.
Edit : Ok I solved the problem with the QListWidget
and the menu. Now the following must be accomplished:
If you click on an item with the right mouse button, and then click Delete, then the item will be deleted.
My code:
void ProvideContextMenu(const QPoint &); // MainWindow.h
// In MainWindow.cpp
ui->listFiles->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->listFiles, SIGNAL(customContextMenuRequested(const QPoint &)),
this, SLOT(ProvideContextMenu(const QPoint &)));
void MainWindow::ProvideContextMenu(const QPoint &pos)
{
QPoint item = ui->listFiles->mapToGlobal(pos);
QMenu submenu;
submenu.addAction("ADD");
submenu.addAction("Delete");
QAction* rightClickItem = submenu.exec(item);
if (rightClickItem && rightClickItem->text().contains("Delete") )
{
ui->listFiles->takeItem(ui->listFiles->indexAt(pos).row());
}
}
Edit2 : Ok I solved the whole problem :D. I uploaded my code, if somebody needs something like that it can help him/her.
Firstly you need to create slot for opening context menu:
void showContextMenu(const QPoint&);
At constructor of your class, which used QListWidget
, set context menu policy to custom and connect QListWidget::customContextMenuRequested(QPoint)
signal and showContextMenu()
slot like this:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setupUi(this);
listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
connect(listWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
}
Then need to realize context menu opening:
void MainWindow::showContextMenu(const QPoint &pos)
{
// Handle global position
QPoint globalPos = listWidget->mapToGlobal(pos);
// Create menu and insert some actions
QMenu myMenu;
myMenu.addAction("Insert", this, SLOT(addItem()));
myMenu.addAction("Erase", this, SLOT(eraseItem()));
// Show context menu at handling position
myMenu.exec(globalPos);
}
After this we need to realize slots for adding and removing QListWidget
elements:
void MainWindow::eraseItem()
{
// If multiple selection is on, we need to erase all selected items
for (int i = 0; i < listWidget->selectedItems().size(); ++i) {
// Get curent item on selected row
QListWidgetItem *item = listWidget->takeItem(listWidget->currentRow());
// And remove it
delete item;
}
}
As you can see we iterate all selected items (for set multiple selection mode use setSelectionMode()
method) and delete it by ourself, because docs says that
Items removed from a list widget will not be managed by Qt, and will need to be deleted manually.
Adding some items is easier, my solution with static variable for different item caption looks like:
void MainWindow::addItem()
{
static int i = 0;
listWidget->addItem(QString::number(++i));
}
To simplify your code use Qt5 sytax for signals and slots. It eliminates the need to create intermediate slots.
I hope it helps to you.
It's much simpler than the accepted answer. You don't need to deal with creating a context menu or cursor positions or any of that. Instead of Qt::CustomContextMenu
, use Qt::ActionsContextMenu
and just add your actions directly to the widget:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
ui->setupUi(this);
// you can create the actions here, or in designer
auto actInsert = new QAction("Insert", this);
auto actDelete = new QAction("Delete", this);
// you can set up slot connections here or in designer
connect(actInsert, SIGNAL(triggered()), this, SLOT(addItem()));
connect(actDelete, SIGNAL(triggered()), this, SLOT(eraseItem()));
// and this will take care of everything else:
listWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
listWidget->addActions({ actInsert, actDelete });
}
void MainWindow::addItem () {
...; // add an item
}
void MainWindow::eraseItem () {
...; // erase an item
}
Everything above except addActions
(I think) can also be done in Designer.
Alternatively, if you don't want to add actual slot functions for whatever reason, you can do everything in a lambda on connect, too:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
ui->setupUi(this);
// you can create the actions here, or in designer
auto actInsert = new QAction("Insert", this);
auto actDelete = new QAction("Delete", this);
connect(actInsert, &QAction::triggered, [=]() {
...; // add an item
});
connect(actDelete, &QAction::triggered, [=]() {
...; // erase an item
});
// and this will take care of everything else:
listWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
listWidget->addActions({ actInsert, actDelete });
}
The signal/slot option is more organized and flexible, but the lambda option is good for short highly specialized bits of code (or binding to functions that aren't slots).
This works for context menus on any widget. Also, the same QAction
can be used on multiple widgets.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With