图形场景Qt中右键单击上下文菜单的响应缓慢
slow response on right click contex menu in graphic scene Qt
我在事件过滤器中设置了一个大菜单,右键单击时有 45-50 个操作
在里面,我发现当我右键单击时,显示菜单的响应很慢
我确实在菜单中尝试了具有 5 个操作的相同代码,并且响应很好。
这种在上下文菜单上编码的方式有问题吗?
事件过滤器
bool Editor::eventFilter(QObject *o, QEvent *e)
{
Q_UNUSED (o);
QGraphicsSceneMouseEvent *me = (QGraphicsSceneMouseEvent*) e;
switch ((int) e->type()){
case QEvent::GraphicsSceneMousePress:{
switch ((int) me->button()){
case Qt::RightButton:{
QGraphicsItem *item = itemAt(me->scenePos());
showContextMenu(item->scenePos().toPoint());
return true;
}
//more cases here//
}
break;
}
}
return QObject::eventFilter(o, e);
}
showContextMenu
void Editor::showContextMenu(const QPoint &pos)
{
QGraphicsItem *item =itemAt(pos);
// Create main effe menu
effeMenu= new QMenu("Menu");
QString menuStyle(
"QMenu {"
"border:10px };"
//more code here
);
effeMenu->setStyleSheet(menuStyle);
AmpMenu=effeMenu->addMenu(QIcon(":/effectImg/img/effePng/amp.png"),"Amp");
Amp1 =AmpMenu->addAction(QIcon(":/effectImg/img/effePng/amp.png"),"Amp 1");
Amp2 =AmpMenu->addAction(QIcon(":/effectImg/img/effePng/amp.png"),"Amp 2");
CabMenu=effeMenu->addMenu(QIcon(":/effectImg/img/effePng/cab.png"),"Cab");
Cab1 =CabMenu->addAction(QIcon(":/effectImg/img/effePng/cab.png"),"Cab 1");
Cab2 =CabMenu->addAction(QIcon(":/effectImg/img/effePng/cab.png"),"Cab 2");
.
.
.
.
//45 actions more
connect(effeMenu, &QMenu::triggered,this,[this,&item](QAction * k){
menuSelection(k,item);
});
您可以通过两种方式提高速度:
1 - itemAt(pos) 成本很高,您要执行两次,一次在事件中,一次在 showContextMenu 中。根据我从您的代码中可以理解的情况,您不需要事件中的项目,只需要在 showMenu 中。
2 - 您正在做的菜单创建很昂贵:所有操作都有像素图。这为 QPixmap、加载、执行、转储分配内存。因为您告诉我们您使用了大约 40 个操作(实际上,这对于一个菜单来说太多了),这可能会花费很多。
我的建议:
为您的菜单创建一个 class,创建它的 一个 实例,为您的菜单将在其上运行的当前 QGraphicsObject 添加一个 setter,并始终使用该对象实例.
不必在每次调用 showContextMenu
时都创建一个新的 QMenu
,您可以使它成为 class 的成员并构建一次。另一方面,没有必要使用信号,您可以简单地使用 QMenu
:
的 exec()
方法
*.h
class Editor: ...{
...
private:
QMenu effeMenu;
}
*.cpp
Editor::Editor(...){
effeMenu.setTitle("Menu");
QString menuStyle(
"QMenu {"
"border:10px };"
//more code here
);
effeMenu.setStyleSheet(menuStyle);
AmpMenu=effeMenu.addMenu(QIcon(":/effectImg/img/effePng/amp.png"),"Amp");
Amp1 =AmpMenu->addAction(QIcon(":/effectImg/img/effePng/amp.png"),"Amp 1");
Amp2 =AmpMenu->addAction(QIcon(":/effectImg/img/effePng/amp.png"),"Amp 2");
CabMenu=effeMenu.addMenu(QIcon(":/effectImg/img/effePng/cab.png"),"Cab");
Cab1 =CabMenu->addAction(QIcon(":/effectImg/img/effePng/cab.png"),"Cab 1");
Cab2 =CabMenu->addAction(QIcon(":/effectImg/img/effePng/cab.png"),"Cab 2");
...
}
void Editor::showContextMenu(const QPoint &pos){
QGraphicsItem *item =itemAt(pos);
QAction *action = menu.exec(pos);
menuSelection(action, item);
}
我在事件过滤器中设置了一个大菜单,右键单击时有 45-50 个操作 在里面,我发现当我右键单击时,显示菜单的响应很慢 我确实在菜单中尝试了具有 5 个操作的相同代码,并且响应很好。 这种在上下文菜单上编码的方式有问题吗?
事件过滤器
bool Editor::eventFilter(QObject *o, QEvent *e)
{
Q_UNUSED (o);
QGraphicsSceneMouseEvent *me = (QGraphicsSceneMouseEvent*) e;
switch ((int) e->type()){
case QEvent::GraphicsSceneMousePress:{
switch ((int) me->button()){
case Qt::RightButton:{
QGraphicsItem *item = itemAt(me->scenePos());
showContextMenu(item->scenePos().toPoint());
return true;
}
//more cases here//
}
break;
}
}
return QObject::eventFilter(o, e);
}
showContextMenu
void Editor::showContextMenu(const QPoint &pos)
{
QGraphicsItem *item =itemAt(pos);
// Create main effe menu
effeMenu= new QMenu("Menu");
QString menuStyle(
"QMenu {"
"border:10px };"
//more code here
);
effeMenu->setStyleSheet(menuStyle);
AmpMenu=effeMenu->addMenu(QIcon(":/effectImg/img/effePng/amp.png"),"Amp");
Amp1 =AmpMenu->addAction(QIcon(":/effectImg/img/effePng/amp.png"),"Amp 1");
Amp2 =AmpMenu->addAction(QIcon(":/effectImg/img/effePng/amp.png"),"Amp 2");
CabMenu=effeMenu->addMenu(QIcon(":/effectImg/img/effePng/cab.png"),"Cab");
Cab1 =CabMenu->addAction(QIcon(":/effectImg/img/effePng/cab.png"),"Cab 1");
Cab2 =CabMenu->addAction(QIcon(":/effectImg/img/effePng/cab.png"),"Cab 2");
.
.
.
.
//45 actions more
connect(effeMenu, &QMenu::triggered,this,[this,&item](QAction * k){
menuSelection(k,item);
});
您可以通过两种方式提高速度:
1 - itemAt(pos) 成本很高,您要执行两次,一次在事件中,一次在 showContextMenu 中。根据我从您的代码中可以理解的情况,您不需要事件中的项目,只需要在 showMenu 中。
2 - 您正在做的菜单创建很昂贵:所有操作都有像素图。这为 QPixmap、加载、执行、转储分配内存。因为您告诉我们您使用了大约 40 个操作(实际上,这对于一个菜单来说太多了),这可能会花费很多。
我的建议: 为您的菜单创建一个 class,创建它的 一个 实例,为您的菜单将在其上运行的当前 QGraphicsObject 添加一个 setter,并始终使用该对象实例.
不必在每次调用 showContextMenu
时都创建一个新的 QMenu
,您可以使它成为 class 的成员并构建一次。另一方面,没有必要使用信号,您可以简单地使用 QMenu
:
exec()
方法
*.h
class Editor: ...{
...
private:
QMenu effeMenu;
}
*.cpp
Editor::Editor(...){
effeMenu.setTitle("Menu");
QString menuStyle(
"QMenu {"
"border:10px };"
//more code here
);
effeMenu.setStyleSheet(menuStyle);
AmpMenu=effeMenu.addMenu(QIcon(":/effectImg/img/effePng/amp.png"),"Amp");
Amp1 =AmpMenu->addAction(QIcon(":/effectImg/img/effePng/amp.png"),"Amp 1");
Amp2 =AmpMenu->addAction(QIcon(":/effectImg/img/effePng/amp.png"),"Amp 2");
CabMenu=effeMenu.addMenu(QIcon(":/effectImg/img/effePng/cab.png"),"Cab");
Cab1 =CabMenu->addAction(QIcon(":/effectImg/img/effePng/cab.png"),"Cab 1");
Cab2 =CabMenu->addAction(QIcon(":/effectImg/img/effePng/cab.png"),"Cab 2");
...
}
void Editor::showContextMenu(const QPoint &pos){
QGraphicsItem *item =itemAt(pos);
QAction *action = menu.exec(pos);
menuSelection(action, item);
}