C++:实现多重继承的最佳实践

4

我将要添加两种图形项(QGraphicsRectItemQGraphicsEllipseItem)到一个 QGraphicsScene 中(该场景已添加到 QGraphicsView)。每个图形项都应该能够与鼠标和键盘事件交互。因此,最初我设计了以下类。

初始设计:

class myQGraphicsRectItem : public QGraphicsRectItem
{
public:
    explicit myQGraphicsRectItem();
private:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void keyPressEvent(QKeyEvent *event);
    void focusOutEvent(QFocusEvent *event);
    //Many events goes here
    void fnCreateRect();
};

class myQGraphicsRectItem : public QGraphicsEllipseItem
{
public:
    explicit myQGraphicsRectItem();
private:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void keyPressEvent(QKeyEvent *event);
    void focusOutEvent(QFocusEvent *event);
    //Many events goes here
   void fnCreateCircle();
};

为了知道如何避免重复的事件声明和定义,我阅读了以下问题的答案: 最终,我设计出以下类:

修改后的设计:

头文件

template <class T>
class myQGraphicsRectItem : public QGraphicsRectItem , public QGraphicsEllipseItem{
     /*commented the below event methods in the base classes*/
     void mousePressEvent(QGraphicsSceneMouseEvent *event);
     void keyPressEvent(QKeyEvent *event);
     void focusOutEvent(QFocusEvent *event);
     //Many events goes here
}

实现文件

template <class T> myGraphicsItem<T>::myGraphicsItem()
{
    this->T::setFlags(QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsFocusable);
    this->T::setFocus();
}     

//**All event function definition goes here....**     

template <class T> QGraphicsItem *myGraphicsItem<T>::fnGetRectObject()
{
    fnCreateRect();
    return (T*)this;
}

调用代码

#include "mygraphicsitem.h"
#include "mygraphicsitem.cpp"

void MainWindow::on_PushButton_clicked()
{
    myGraphicsItem<myQGraphicsRectItem> *rr = new myGraphicsItem<myQGraphicsRectItem>();
    scene->addItem(rr->fnGetRectObject());
}

这个修改后的设计使应用程序按预期工作。但我对这个设计有一些疑问,如下:

  1. 这是处理此场景的最佳实践吗?还是应该使用最初的方法?或者是否有其他更好的方法(编写单个代码来处理事件)?
  2. QGraphicsRectItemQGraphicsEllipseItem都继承自QAbstractGraphicsShapeItem。那么我需要处理虚拟基类概念吗?

2
我认为这应该放在 CR 上。请注意,交叉发布不被视为“良好行为”。 - Simon Kraemer
4
您可以让myQGraphicsRectItem简单地继承自T,从而消除多重继承。 - Jonathan
@Jonathan,正在尝试你所说的概念... - Jeet
1
请记住,由于没有任何*GraphicsItem继承自QObject,因此此代码可以正常工作。从QObject进行多重继承是不起作用的。 - iksemyonov
@Jonathan,它运行良好。我对这种方法感到满意。 - Jeet
@iksemyonov。感谢您分享您的知识。 - Jeet
2个回答

5

哇,这是在过度思考问题的解决方案!

还有其他更好的方法吗(编写单个代码来处理事件)?

对我来说,问题不清楚你想要实现什么,可能是因为尝试了某种解决方案,所以我假设你要使用两个类 QGraphicsRectItemQGraphicsEllipseItem 来编写一个单独的代码块来处理自定义事件,例如鼠标、键盘等。

在这种情况下,Qt 通过调用 installSceneEventFilter 为您提供所需的一切。

只需创建一个从 QGraphicsItem 派生出来的类,并重新实现您想要处理的事件。然后使用 installSceneEventFilter 将此新类添加到其他实例中即可。

class QGraphicsItemEventsFilter : public QGraphicsItem
{
    private:
        void mousePressEvent(QGraphicsSceneMouseEvent *event);
        void keyPressEvent(QKeyEvent *event);
        void focusOutEvent(QFocusEvent *event);
};

实例化过滤器并将其添加到其他类中

QGraphicsItemEventsFilter* pFilter = new QGraphicsItemEventsFilter;

QGraphicsRectItem* pRect = new QGraphicsRectItem;
pRect->installSceneEventFilter(pFilter);

QGraphicsEllipseItem* pEllipse = new QGraphicsEllipseItem;
pEllipse->installSceneEventFilter(pFilter);

现在,pRectpEllipse的所有事件都将由事件过滤器

处理。

1
看了你的回答,是的,我的确想太多了 :) 我需要更多地学习QT。感谢你的时间。 - Jeet

2
从我使用Qt的经验来看,如果您认为必须使用多重继承来处理Qt类和子类,则很可能是错误的 - 这反过来很可能表明您没有完全理解机制。Qt设计得非常好,如果按照预期执行操作,则不需要多重继承。请再次考虑并寻找所需实现的示例。

感谢您分享您的知识。我尝试了Jonathan的评论,并避免了多重继承。 - Jeet
5
虽然这是有用的信息,但它并没有尝试回答问题,最好作为评论发布。 - TheDarkKnight
@TheDarkKnight 如果它为 OP 提供了一个更好、更轻松的工具来完成他们想要做的事情,我不明白为什么它不是一个答案(这并不意味着你的回答不一定更详细和具体)。 - Pekka
1
@Gimby 用词不当 - 一个方法,一个课程变更 - Pekka
@Gimby也许是这样,但试图通过向版主申请删除它来解决它不是答案的问题仍然很愚蠢。如果你不喜欢它,只需将其投票为反对即可。 - Pekka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接