在 Qt 應用中,為 QTreeWidget(或任意 QWidget 子類)添加右鍵上下文選單是常見需求。本文將完整演示:
setData() 為節點綁定業務標識在 MainWindow 建構函數或 setupUi() 後調用:
ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
缺少此行,customContextMenuRequested 信號永不發射,右鍵無響應。
建立根節點時,將唯一標識存入 Qt::UserRole:
QTreeWidgetItem *root = new QTreeWidgetItem(ui->treeWidget, QStringList("Connection"));
QVariant var(0); // 0 代表根節點類型
root->setData(0, Qt::UserRole, var);
子節點同理,可存入資料庫 ID、表名、枚舉值等任意 QVariant 支持的類型。
void MainWindow::on_treeWidget_customContextMenuRequested(const QPoint &pos)
{
// 1. 獲取點擊位置的項目
QTreeWidgetItem *curItem = ui->treeWidget->itemAt(pos);
if (!curItem) return; // 點擊空白區,直接返回或顯示「新建」菜單
// 2. 讀取業務標識
int nodeType = curItem->data(0, Qt::UserRole).toInt();
// 3. 根據類型構建不同 QMenu
QMenu *popMenu = new QMenu(this);
if (nodeType == 0) { // 根節點:資料庫操作
popMenu->addAction(ui->action_newDB);
popMenu->addAction(ui->action_openDB);
popMenu->addAction(ui->action_delDB);
} else { // 子節點:表操作
popMenu->addAction(ui->action_newTable);
popMenu->addAction(ui->action_openTable);
popMenu->addAction(ui->action_designTable);
}
// 4. 在游標位置彈出(exec() 為阻塞式)
popMenu->exec(QCursor::pos());
}
treeWidgetcustomContextMenuRequested(QPoint) → OKitemAt(pos) 返回整行項目,若需知晓具體欄,可用 header()->logicalIndexAt(pos.x()) 結合 columnAt(pos.x())(Qt 5.10+)。action->setIcon()、action->setShortcut() 統一在 Designer 設定,代碼復用性高。new QMenu(this) 父對象設為 this,隨視窗銷毀自動釋放,無需手動 delete。ui->treeWidget->setCurrentItem(curItem);。QListWidget、QTableWidget、自定義 QWidget,只需啟用策略並連接信號。// MainWindow.h
private slots:
void on_treeWidget_customContextMenuRequested(const QPoint &pos);
// MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); // 必須!
initTreeData(); // 你的節點初始化邏輯
}
void MainWindow::on_treeWidget_customContextMenuRequested(const QPoint &pos)
{
// ... 如前文完整實現 ...
}
Qt 的 CustomContextMenu 機制清晰解耦了「觸發點」與「菜單內容」。核心在於:啟用策略 → 綁定業務數據 → 槽函數按需構建菜單 → exec() 彈出。掌握此模式,即可為任意控件實現豐富、上下文感知的右鍵交互。