在 Qt 中為 QTreeWidget 添加右鍵上下文選單,並根據點擊節點的角色(根節點/子節點)動態顯示不同動作,是常見 UI 需求。關鍵在於 customContextMenuRequested 信號與 itemAt() 定位節點。
setContextMenuPolicy(Qt::CustomContextMenu)。customContextMenuRequested(QPoint) 到槽函數。itemAt(pos) 獲取點擊項目。setData/data)區分類型,構建不同 QMenu。exec(QCursor::pos()) 彈出選單。// 在構造函數或初始化函數中
ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); // 關鍵!
// 建立根節點並標記角色 0
QTreeWidgetItem* root = new QTreeWidgetItem(ui->treeWidget, QStringList("Connection"));
root->setData(0, Qt::UserRole, QVariant(0)); // 0 = 根節點
// 建立子節點並標記角色 1
QTreeWidgetItem* child = new QTreeWidgetItem(root, QStringList("Table1"));
child->setData(0, Qt::UserRole, QVariant(1)); // 1 = 子節點
void MainWindow::on_treeWidget_customContextMenuRequested(const QPoint& pos) {
QTreeWidgetItem* item = ui->treeWidget->itemAt(pos);
if (!item) return; // 點擊空白區域
QMenu* menu = new QMenu(this);
int role = item->data(0, Qt::UserRole).toInt();
if (role == 0) { // 根節點:資料庫操作
menu->addAction(ui->action_newDB);
menu->addAction(ui->action_openDB);
menu->addAction(ui->action_delDB);
} else { // 子節點:資料表操作
menu->addAction(ui->action_newTable);
menu->addAction(ui->action_openTable);
menu->addAction(ui->action_designTable);
}
menu->exec(QCursor::pos());
// menu 會在 exec 返回後自動刪除(Qt::WA_DeleteOnClose)
}
setContextMenuPolicy(Qt::CustomContextMenu),否則信號不會發射。Qt::UserRole 儲存自定義角色標識,避免靠文字比對,支援國際化與重構。QMenu 在堆上建立,exec() 結束後 Qt 會自動銷毀(內部設有 WA_DeleteOnClose),無需手動 delete。ui->action_xxx),直接 addAction 即可複用圖標、快捷鍵、槽連接。若節點類型超過兩種,可改用 enum 映射到 QMap 配置表,實現數據驅動的選單構建,避免 if-else 膨脹。