PDA

View Full Version : Newbie class design question



qk
21st February 2017, 11:15
Hi,

I'm currently trying to design a program that allows me to add and remove QWidgets(e.g. QPushButtons and QLineEdits) to a QMainWindow at runtime. So far this works pretty well, but now i recognize that my class design isn't that great and results in redundant code. I was hoping that some of you guys might have a better idea.

My QWidgets that I will add to the QMainWindow(more specifically a custom QScreenLayout) all need some special functions for serialization and special mouse events. This is what I've got so far:



class ScreenPushButton : public QPushButton, public DisplayElement
{
Q_OBJECT
public:
ScreenPushButton(QWidget *parent = 0);
~ScreenPushButton();

virtual void serialize(QDataStream &outstream) override;
virtual void deserialize(QDataStream &instream) override;

private:
QPoint offset_;
virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *event) override;
};



class DisplayElement
{
public:
virtual void serialize(QDataStream &outstream) = 0;
virtual void deserialize(QDataStream &instream) = 0;

quint8 dataType() {return dataType_;}

protected:
quint8 dataType_;
};


Now, any other custom widget like for example ScreeLineEdit look quite the same as ScreenPushButton. Serialize() and deserialize() will always differ, but the following part could(and should) be shared among all custom widgets.


private:
QPoint offset_;
virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *event) override;


My first very naive try was to move the definition of the mouse events to DisplayElement but that of course won't work because then these function signatures would be ambiguous. Calling this function could either be a call to QPushButton::mousePressEvent() or a call to DisplayItem::mousePressEvent().

Another problem I stumbled upon is that only the first inherited class can be a Q_OBJECT.

Any ideas how to resolve this issue? Do I need to provide more information?

Kind regards
k

Santosh Reddy
21st February 2017, 11:38
Read about event filters. Instead of implementing the mouse events in the widget, implement the event handling in a separate QObject and install the event filter on all the widgets.


void QObject::installEventFilter(QObject * filterObj)

qk
21st February 2017, 12:32
Read about event filters.

Oooh, that exists? Nice! Thank you so much! I think this might solve my problem.

d_stranz
21st February 2017, 15:43
Another option might be to define a base class derived from QWidget and DisplayElement; this base class implements your mouse event handlers. ScreenPushButton and your other GUI classes singly-inherit from this one. Be sure to include the Q_OBJECT macro in the definitions of these derived classes.

If you go the event filter route, be sure to read carefully the parts about how to handle events you -aren't- interested in. In the alternative approach I suggested, you only implement event handlers for the events you are interested in; with an event filter, you get them all. On the other hand, you can install multiple event filters on the same object, so you could potentially handle the same event in different ways.

anda_skoa
22nd February 2017, 08:35
Another option is delegation.

You create a class that handles the common event processing and each of your classes holds an instance of that and delegates the events it received to that instance.


class DisplayElement
{
protected:
MouseEventHandler m_eventHandler;
};


I would presonally keep the serialization methods out of the widget classes.

Cheers,
_