我有一个QTreeView对象,这个树视图的项目可以包含三种类型的数据之一,每种数据都需要不同的处理。因此,对于这些类型中的每一种,我在用户右键单击时需要不同的上下文菜单。我的树对象看起来像这样:
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
}
我目前如何处理不同的上下文菜单,每次右键单击一个项目时,我会查看该QStandardItem
项下"Item Type"
的名称,然后我将其传递给它通过if()
s的过滤器调用不同的函数,为不同类型的项目创建不同的上下文菜单。我的方法如下:
void MyTreeView::make_context_menu(const QPoint& pos) {
m_currentPos = pos;
QModelIndex firstIndex= this->indexAt(m_currentPos);
if(firstIndex.isValid()) {
if(firstIndex.parent() == QModelIndex()) { // if it's a top level item
int row = firstIndex.row();
m_currentIndex = firstIndex.sibling(row, 0);
m_currentItem = m_itemModel->itemFromIndex(m_currentIndex);
QModelIndex flTypeIndex = firstIndex.sibling(row, 1);
QStandardItem* fileTypeItem =
m_itemModel->itemFromIndex(flTypeIndex);
QString fileType = fileTypeItem->text();
if(fileType == "Type A") m_make_typeA_context_menu();
if(fileType == "Type B") m_make_typeB_context_menu();
}
}
}
这有效,但我不确定这是否是一种相当好的方式。现在的问题是,当我在程序中添加对更多类型的支持时,我将不得不回到这个并添加更多if()
。好吧,我需要为这些新类型提供不同的上下文菜单,所以也许别无他法;但我不是一个经验丰富的程序员,所以我希望在这个问题上看到不同的方法。
答案 0 :(得分:0)
我想出了一个不太可怕的解决方案,我认为比我在原帖中提到的方法更好。我想分享我的解决方案,因为我认为它可以帮助某人。
首先,我为所有继承的树项创建了一个基类。基类使用枚举来枚举可能/已注册的树项类型。
// 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;
};
现在,每个树项都将继承此基类,并且必须使用类型枚举构造基类。例如,
// 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;
}
}
}
对我而言,这似乎是一个更整洁的解决方案。为了做到这一点,可以构建从QMenu派生的类来为每个类型创建菜单对象,如MenuType1,MenuType2等,然后可以使用它们进一步整理:
void TreeView::make_type1_menu(pos) {
// stuff
MenuType1* newMenu = new MenuType1(//args);
newMenu->exec(mapToGlobal(pos));
}