QTreeWidget контекстное меню

Я огляделся и кажется, что проблема присутствует не только для виджета дерева, но и для других виджетов. Но в моем случае я нашел решение, хотя и неполное. Я добавляю действия в свой виджет дерева, чтобы при щелчке правой кнопкой мыши появлялось всплывающее окно с этими действиями. Однако, когда я добавляю элементы в виджет дерева и щелкаю по ним правой кнопкой мыши, появляется то же самое всплывающее окно. Что я хотел бы сделать, так это то, что когда вы щелкаете правой кнопкой мыши по виджету дерева, появляется всплывающее меню виджета дерева, а когда вы щелкаете правой кнопкой мыши по элементам, появляется другое соответствующее всплывающее меню. Кто-нибудь знает, как это сделать?


person ISTB    schedule 09.01.2013    source источник


Ответы (4)


Сначала вы должны установить для политику контекстного меню значение CustomContextMenu:

treeView->setContextMenuPolicy(Qt::CustomContextMenu);

Затем вы можете подключиться к сигналу QWidget::customContextMenuRequested(const QPoint&) и показать свое контекстное меню.

person hank    schedule 09.01.2013
comment
Кажется, это сложнее, чем я думал. Так что практически мне нужно подключить сигнал customContextMenuRequested к моему слоту? - person ISTB; 09.01.2013
comment
Да, у вас должен быть слот, который будет отображать ваше пользовательское контекстное меню после перехвата этого сигнала. - person hank; 10.01.2013

Во-первых, настройте QTreeWidget для ответа (испускания сигнала) правой кнопкой мыши:

treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);

Во-вторых, подключите сигнал к вашему слоту «MainWindow::prepareMenu»:

connect(treeWidget,&QTreeWidget::customContextMenuRequested,this,&MainWindow::prepareMenu);

В-третьих, создайте контекстное меню в слоте:

void MainWindow::prepareMenu( const QPoint & pos )
{
QTreeWidget *tree = treeWid;

QTreeWidgetItem *nd = tree->itemAt( pos );

qDebug()<<pos<<nd->text(0);


QAction *newAct = new QAction(QIcon(":/Resource/warning32.ico"), tr("&New"), this);
newAct->setStatusTip(tr("new sth"));
connect(newAct, SIGNAL(triggered()), this, SLOT(newDev()));


QMenu menu(this);
menu.addAction(newAct);

QPoint pt(pos);
menu.exec( tree->mapToGlobal(pos) );
}
person ndtc    schedule 07.04.2015
comment
Спасибо, что указали на QTreeWidgetItem *nd = tree->itemAt( pos );! - person zwcloud; 11.09.2018

Для тех, кто предпочитает больше использовать конструктор, вот еще один способ сделать это:

1) Установите политику контекстного меню в пользовательское контекстное меню.

Либо по коду:

ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);

или с помощью графического дизайнера щелкните виджет дерева и установите его с помощью Редактора свойств:

введите описание изображения здесь

2) Создать функцию обработчика

В дизайнере щелкните правой кнопкой мыши виджет дерева и выберите опцию «Перейти к слоту...». Появится окно, подобное этому:

введите описание изображения здесь

Нажмите на опцию «CustomContextMenuRequested (QPoint)». Функция-обработчик будет определена, объявлена ​​и автоматически подключится.

void MainWindow::on_treeWidget_customContextMenuRequested(const QPoint &pos)
{
  // this function will be called on right click
}

Этот шаг также можно выполнить, самостоятельно определив и подключив функцию слота.

3) Создайте параметры в контекстном меню.

введите описание изображения здесь

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

введите описание изображения здесь

Вы можете (необязательно) иметь всплывающую подсказку или значок для действия или сделать его доступным для проверки. Вы можете создать ярлык, например Ctrl+C, для действия копирования.

4) Создайте меню и запустите его

void MainWindow::on_treeWidget_customContextMenuRequested(const QPoint &pos)
{
    QMenu menu(this); // add menu items
    menu.addAction(ui->actionDelete);
    menu.addEdit(ui->actionDelete);
    ...

    ui->actionDelete->setData(QVariant(pos)); // if you will need the position data save it to the action

    menu.exec( ui->treeWidget->mapToGlobal(pos) );
}

5) Создайте функции обработчика для каждого действия

Как и в шаге 2, либо создайте функцию слота и подключите ее вручную, либо щелкните правой кнопкой мыши действие, выберите опцию «Перейти к слотам…» и выберите слот triggered().

введите описание изображения здесь

6) Наконец, примените свою логику в функции слота.

void MainWindow::on_actionEdit_triggered()
{
    QTreeWidgetItem *clickedItem = ui->treeWidget->itemAt(ui->actionDelete->data().toPoint());

    // your logic
}
person t.m.    schedule 26.06.2018

Взгляните на перегрузку QAbstractItemModel и предоставление собственного OnContextMenuRequested. С помощью этой функции вы можете создать разные контекстные меню для разных элементов.

Вот укороченный псевдо-код одного из моих проектов, который может быть полезен:

void MyModel::OnContextMenuRequested(const QModelIndex& index, const QPoint& globalPos)
{
// find 'node' corresponding to 'index'

vector<pair<string,BaseNode*> > actions = node->GetActions(true);
if(actions.size()==0) return;

// the ptr list helps us delete the actions
boost::ptr_list<QObject> actionPtrList;
QList<QAction*> qtActions;
for(unsigned int i=0;i<actions.size();i++)
{
    QAction* act = new QAction(actions[i].first.c_str(),NULL);
    act->setData(qVariantFromValue(actions[i].second));
    actionPtrList.push_back(act);
    qtActions.append(act);
}

// create and show the context menu
QMenu *menu = new QMenu("Item actions",NULL);
actionPtrList.push_back(menu);
QAction* act = menu->exec(qtActions,globalPos);
if(act==NULL) return;

// act on the resulting action 'act'
}
person bulldozers    schedule 09.01.2013
comment
Однако нет причин для этого в модели. Это сигнал от представления, о котором модель обычно не должна знать. - person David Faure; 05.03.2015