Reputation: 2108
I'm creating some custom qt designer widget plugin for drawing purpose. With these widgets, user can use qt designer for drawing just like Microsoft Visio (hopefully).
As shown in the screenshot below, there are one SvPage object page_0 as the container, it contains one SvArc widget and one SvCircle widget.
Every thing is good, except that when one widget (A) cover other widget (B), user cannot select widget B easily.
To solve this problem, I'm trying to do:
Set the size of each drawing widget (eg. SvArc,SvCircle) to very small (40px * 40 px);
Paint the content of drawing widget direct to its parent widget (SvPage). In SvPage::PaintEvent(QPaintEvent event)
, it iterates all children drawing widgets and call the doPaint(QPainter painter)
method of each children.
3. To refresh the drawing widget automatically (eg, when SvArc widget is moved, its drawing on SvPage should be updated automatically), in the drawing widget's SvArc::PaintEvent(QPaintEvent *event)
, it will trigger the SvPage to update its painting.
But in step 3, there is a problem that it will lead to recursive repaint issue: because SvArc::PaintEvent() trigger SvPage::PaintEvent(), and SvPage::PaintEvent() will then trigger SvArc::PaintEvent() again since SvArc widget is a child widget of SvPage widget.
So, the question is that is it a good idea to redirect widget painting to parent widget? If yes, how to solve the recursive repaint issue? If no, what's the good one?
Code (simplified):
void SvPage::paintEvent(QPaintEvent *event)
{
initPainter();
QList<SvWidget*> widgets = this->findChildren<SvWidget*>();
for (int i = 0; i < widgets.count(); i++)
{
SvWidget* w = widgets.at(i);
w->doPaint(this->painter);
}
destoryPainter();
}
void SvWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
emit signalDoPaint();
}
void SvArc::doPaint(QPainter* painter)
{
painter->drawArc(x, y, w, h, a alen);
}
Upvotes: 0
Views: 1573
Reputation: 98445
I'm creating some custom Qt Designer widget plugin for drawing purpose. With these widgets, user can use Qt Designer for drawing just like Microsoft Visio (hopefully).
The functionality you're reusing in Qt Designer is minimal, and could be easily factored out into a separate project. The only thing of any value for you is the property inspector pane.
For everything else, using widgets is about the most complicated way of implementing it. Use QGraphicsScene
and QGraphicsView
and start with 90% of your functionality already implemented and ready to go.
Implementing a rudimentary vector illustration system in QGraphicsScene
is an afternoon job. You can have something with the functionality of early Corel Draw from Windows 2.x times done in a few days. It's the testament to the power of the scene framework and modern development frameworks in general.
Upvotes: 0
Reputation: 49299
You are messing things up here.
Every widget should be responsible for its own drawing. That's how Qt is designed to work.
You could use a single widget as a manager for some objects, and to draw them, but then those objects don't need to be widgets, they can be simple data representations. In that case, the objects will not concern themselves with any painting, it will be the manager widget that does it.
However that approach will be less efficient. Because when you have multiple independent widgets, the paint engine can easily detect changes and efficiently repaint only the parts that need updating.
In your case you will either have to do a whole lot of redundant repainting, or implement more sophisticated item management, which will be a complex task that will definitely not be worth the effort, if you are even up to it to begin with, which you are probably not.
Your current approach is very bad. I'd suggest to just stick to regular widgets, in their actual sizes, doing their actual painting. It will be much easier for you to implement and manage it, and it will be much easier for the computer to paint it.
As for selecting between overlapping widgets, QWidget
wasn't really designed to facilitate that. Widgets are supposed to be put in layouts, not to overlap. Which is why its childAt()
function can only return a single widget at a given coordinate.
What you should really do is use QGraphicsScene
, QGraphicsView
and QGraphicsItem
. Similarly to widgets, graphics items will handle their own drawing efficiently, the difference is the API was designed for graphics, and when you have overlapping items, QGraphicsScene::items()
will give you a list of all items at that position, so you can chose an item other than the topmost.
Upvotes: 4