figuring out what causes paintEvent with weird clipRegion in Qt5 - c++

I am working on a big legacy application and there is a custom widget which is being shown on a user action. The problem is that widget is not painted because paintEvent for this widget comes with some weirdly small region. If I ignore it and paint whole widget then everything is ok, but that is just a workaround. I am trying to find a place in code which is responsible for this event but that's not an easy task.
Can you give me some tricks how can I figure out what is the source of this event?

Related

Qt how to redirect widget painting to parent widget?

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);
}
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.
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.

Qt creator: paintEvent of Qwidget

I have some problems. Hope anyone can help me.
I have a Qwidget1 and Qwidget2. Qwidget1 have a widget that promote to Qwidget2. Both Qwidget1 and Qwidget2 have paintEvent. I have writed "qDebug()<< "Update"; " in paint event of Qwidget1. When I run project, I see a word "Update" has been printed a lot of times. So why Qwidget1 execute paint event a lot of times. How can I fix it, just execute paint event when show Qwidget1 at the first time and when I call update.
This is expected behavior. Your code works like it should. From Qt documentation:
A paint event is a request to repaint all or part of a widget. It can
happen for one of the following reasons:
repaint() or update() was invoked,
the widget was obscured and has now been uncovered,
or many other reasons.
There can be any number of situations when a window or its part becomes invalidated and has to be repainted. Such situations include, but are not limited to:
window size change (including minimizing / maximizing / restoring the window);
mouse pointer passing over a widget - it may or may not trigger repaint;
other window moving over the window in question.
When it happens, Windows will send the WM_PAINT message to the application. You could check whether or not the number of WM_PAINT messages received matches the number of paintEvent calls, but I doubt Qt adds any significant overhead.

QT window within window?

I'm setting up a small code editor using QT and following this example. However, i'm curious on how to create windows within windows or widgets within widgets. I'm trying to achieve something similar to these:
http://i.stack.imgur.com/Vn8Ut.png
http://www.hanselman.com/blog/content/binary/Windows-Live-Writer/Download-Visual-Studio-2013-while-your-f_1431E/image_4eb5427c-1ae7-4464-9c26-2282fe8d06c3.png
Is there an example of overlaying widgets like this?
Any alternative soloution for QMessagebox for IOS development (QWidget application only)?
I gave an example of getting another QWidget to be embedded and painted on top of another one. Let me know if you have any questions about how it was done.
The PopUp flag and Qt::Tool options are also relevant.
Be sure to check out: the ToolTip property of a QWidget and the WhatsThis property of QWidget.
http://qt-project.org/doc/qt-5/qwidget.html#toolTip-prop
http://qt-project.org/doc/qt-5/qwidget.html#whatsThis-prop
There are also other ways to make borderless, focusless windows that hover and disappear quickly on command. The Window Flags and Widget Attributes in Qt are very powerful when you are looking to modify Qt Widgets.
When you parent a Widget to another widget, it will draw itself on top of the other. Then you just need to resize and position it properly.
Also subclassing existing widgets can give you more options.
Draw text on scrollbar
Also common Qt::Tools that you will find are QDockWidgets. They are awesome!
Hope that helps.
Take a look at Qt Namespace especially Qt::WA_LayoutOnEntireRect and Qt::WA_StyleSheet. Pass it as a widget attrybutes. The second option looks promising but you have to create style sheet for QWidget.

How to write a scrollable MFC custom control?

I want to write my own chart control which requires scrolling.
I found that there is a CScrollView but nothing like this for a control.
Other toolkits like Cocoa, QT or GTK offer me a base class where i can set a content view which is displayed in a viewport and saves me from writting all of the scrolling code.
The code for custom scrolling isn't that much. Create the scrollbars, write the message handlers and remember one rectangle for the current visible part.
I would just try it. If you have problems, we are here to help :-)

mouse over transparency in Qt

I am trying to create an app in Qt/C++ with Qt4.5 and want the any active windows to change opacity on a mouseover event...
As i understand it, there is no explicit mouseover event in Qt.
However, I got rudimentary functioning by reimplementing QWidget's mousemoveevent() in the class that declares my mainwindow. But the mainwindow's mousemoveevent is not called whenever the mouse travels over any of the group boxes i have created in there (understandbly since QGroupbox has its own reimplementation of mousemoveevent).
So as a cheap work around, I am still using the mousemoveevent of my mainwindow but a query the global mouse position and based on the (x,y) position of the mainwindow (obtained through ->pos()) and the window size (-> size -> rHeight and rWidth), I check if the mouse is within the bounds of the area of the mainwindow and change the opacity thus.
This has had very limited success. The right border works fine, the the left changes opacity 4 pixels early. The top does not work (presumably because the mouse goes through the menubar and title bar) and the bottom changes way too early.
I thought of creating an empty container QWidget class and then place all the rest in there, but i felt that it would still not solve the big issue of the base widget not receiving the mousemoveevent if it has already been implemented in a child widget.
Please suggest any corrections/errors I have made in my method or any alternate methods to achieve this.
p.s. I doubt this matters, but I am working Qt Creator IDE, not Qt integration into VS2008 (it's the same classes anyways - different compiler though, mingw)
Installing event filters for each of your child widgets might do the trick. This will allow your main window to receive child events such as the ones from you group boxes. You can find example code here.
You may be interested in Event filters. QObject proves a way to intercept all events zipping around your application.
http://doc.trolltech.com/4.5/eventsandfilters.html#event-filters
If I understand what you are attempting to do, I would reimplement the widget's enterEvent() and leaveEvent(). The mouse enter event would trigger the fade-in and the leaveEvent would trigger the fade-out.
EDIT: After re-reading several times, I'm still not sure what you are trying to accomplish. Sorry if my suggestion doesn't help. :-)