C++ 使用需要不同上下文菜单的树项更好地设计Qt树视图
我有一个QTreeView对象,此树视图的项可以保存三种类型的数据中的一种,每种类型都需要不同的处理。因此,对于这些类型中的每一种,我需要在用户右键单击时使用不同的上下文菜单。我的树对象如下所示:C++ 使用需要不同上下文菜单的树项更好地设计Qt树视图,c++,qt,user-interface,C++,Qt,User Interface,我有一个QTreeView对象,此树视图的项可以保存三种类型的数据中的一种,每种类型都需要不同的处理。因此,对于这些类型中的每一种,我需要在用户右键单击时使用不同的上下文菜单。我的树对象如下所示: MyTreeView::MyTreeView(QWidget* parent): QTreeView(parent) { // some code m_init_item_model(); // some code connect(this, SIGNAL(cu
MyTreeView::MyTreeView(QWidget* parent): QTreeView(parent) {
// some code
m_init_item_model();
// some code
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(make_context_menu(const QPoint&)));
}
void MyTreeView::m_init_item_model() {
m_itemModel = new QStandardItemModel(this);
m_itemModel->setHorizontalHeaderLabels(QStringList()
<< "Item Name" << "Item Type");
this->setModel(m_itemModel);
// some code
}
这是可行的,但我不确定这是否是一个相当好的方法。现在的问题是,当我在程序中添加对更多类型的支持时,我必须回到这一点并添加更多的
if()
s。嗯,对于这些新类型,我需要不同的上下文菜单,所以可能没有其他方法;但是我不是一个有经验的程序员,所以我想看看解决这个问题的不同方法。我想出了一个不太糟糕的解决方案,我认为比我在最初的帖子中提到的方法要好。我想分享我的解决方案,因为我认为它可以帮助别人
首先,我为所有要继承的树项创建了一个基类。基类使用枚举枚举可能的/已注册的树项类型
// base_tree_item.h
#include <QStandardItem>
enum TREE_ITEM{
TYPE1,
TYPE2,
TYPE3,
// etc
TYPE_COUNT
};
class BaseTreeItem: public QStandardItem {
public:
BaseTreeItem() = delete;
BaseTreeItem(TREE_ITEM itemType): m_itemType(itemType) {}
const TREE_ITEM itemType() const { return m_itemType; }
virtual ~BaseTreeItem() {}
private:
TREE_ITEM m_itemType;
};
现在,要构造项目类型专用的自定义上下文菜单:
void TreeView::make_context_menu(const QPoint& pos) {
m_currentPos = pos;
QModelIndex firstIndex= this->indexAt(m_currentPos);
if(firstIndex.isValid()) {
int row = firstIndex.row();
m_currentIndex = firstIndex.sibling(row, 0);
m_currentItem = m_itemModel->itemFromIndex(m_currentIndex);
BaseTreeItem* currentTreeItem =
static_cast<BaseTreeItem*>(m_currentItem);
TREE_ITEM itemType = currentTreeItem->itemType();
switch(itemType) {
case TYPE1:
make_type1_menu(pos);
break;
case TYPE2:
make_type2_menu(pos);
break;
// etc
default:
break;
}
}
}
// some_type1_item.h
#include "base_tree_item.h"
class SomeType1Item: public BaseTreeItem {
public:
SomeType1Item(): BaseTreeItem(TREE_ITEM::TYPE1) { //stuff }
};
void TreeView::make_context_menu(const QPoint& pos) {
m_currentPos = pos;
QModelIndex firstIndex= this->indexAt(m_currentPos);
if(firstIndex.isValid()) {
int row = firstIndex.row();
m_currentIndex = firstIndex.sibling(row, 0);
m_currentItem = m_itemModel->itemFromIndex(m_currentIndex);
BaseTreeItem* currentTreeItem =
static_cast<BaseTreeItem*>(m_currentItem);
TREE_ITEM itemType = currentTreeItem->itemType();
switch(itemType) {
case TYPE1:
make_type1_menu(pos);
break;
case TYPE2:
make_type2_menu(pos);
break;
// etc
default:
break;
}
}
}
void TreeView::make_type1_menu(pos) {
// stuff
MenuType1* newMenu = new MenuType1(//args);
newMenu->exec(mapToGlobal(pos));
}