qt hiding a control on showEvent() - c++

I call show() on a window and it has several controls and all controls are displayed.
One of the controls is a custom control that inherits from QFrame.
I want to hide this control if a particular flag is set. So, I have
void MyCustomControl::showEvent ( QShowEvent * /* evt */ )
{
if (!m_visibleAllowed)
hide();
}
While this hides the control, it makes the control goofy; it looks frozen. When the window is resized, the area where the control is supposed to be does not get refreshed. Searching around forums, the idea that I get is that hiding the control is not supposed to be done on showEvent() is that true? if so then how/where should I try to hide the control. If hiding the control from showEvent() is possible, how can I prevent the control getting frozen.
Thanks for you time.

If the problem is with calling hide() during your show event (I can't confirm that it's explicitly disallowed, but it doesn't sound like a good idea in general) and calling hide from your show event is where you really need to have this code then you could use a single shot timer:
QTimer::singleShot( 0, this, SLOT(hide()) );
which will simply defer the execution of the hide() function until the next round of the event loop.

Maybe you could use a QStackedLayout or a QStackedWidget that has two widgets in the stack: your control, and a "blank" QWidget. If you did that, instead of using show() and hide() on your control, you switch what's on top of the stack.
That way you never try to render a hidden widget - if your control isn't visible, you render the blank QWidget instead - and I suspect this will solve your graphics glitches.
Hope this helps!

Related

Drawing outside of the QPaintEvent handler

We have big QT project where painting procedure often doesn't follow the rule that it should be done in overridden paintEvent method. As result we have warnings about it: Painter not active etc... But all work fine and at first glance I don't see any problems. Could you explain should I worry about it or not? What is the price of the incorrect use of this functionality?
Paint event is sended to the window when it is should be updated, eg when it is shown or something else. For example if widget is covered by another window, and this windows is moved away, then widget should be updated. Common way is to paint on the pixmap and draw this pixmap on the widget in the paint event handler. Or you can update/repaint each time you need to repaint it.
You can use QPainter to draw on pixmap, printer and so on whenever you want, but to draw on windget it must be done in paintEvent.
I found mistake - it is happened when invalid pixmap(I have created pixmap with size 0x0) is used. I have add check on it and now all are okey.

How to stop a paint event from propagating?

I have two widgets, A and B, A has B as its parent.
Inside the A widget, I have a timer to trigger the repaint slot of itself. Thus, the paintEvent of widget A is triggered. However, I found B's paintEvent is also triggered. How could I trigger only A's paintevet?
I have tried to accept A's paintEvent as:
void A::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
paintA();
event->accept();
}
But it doesn't help. What should I do?
When a widget is sent a paint event, so are all of its enabled children. You can work around this by installing an event filter on the child widget and discarding any paint events you don't want.
You can't because Qt must do composition of the widgets.
Options:
Consider making the widget a non-child and display it as a separate "window". You can use Qt::FramelessWindowHint and Qt::WA_TranslucentBackground to make it look as a child widget. This option will give you perfect results as it leaves the composition to the underlying OS, which, at least on Desktop, will not repaint the bottom widget unless requested.
Consider caching. Use QPixmapCache to cache all drawing of your bottom widget to one window-sized pixmap, which will be very fast to draw when needed.

Qt repaint paintEvent called but widget not updating

My paintEvent has access to a pointer whose value changes from time to time and what gets painted depends on these values. With basic debugging I'm sure that this function is being called but the window does not get updated. The new stuff only appears on the window when it loses focus to another application.
If this is about performance I can set a static variable in the paintEvent to check if the pointer has been updated or not to avoid unnecessary repaints. It would be nice if Qt would just paint when I told it to.
I was hoping someone could help me out or point me in the direction of the right documentation. Thanks.
you must call update() method to repaint your widget.

How to get mouse pressed events in the root widget of a hierarchy in Qt

I have the following problem with Qt (no answer on this site seemed to address exactly this problem so I create my own question).
I have an application with a MainWindow class which inherits from QWidget. At a certain point there is a table inside the main window and I want to catch all mouse pressed events outside that table.
My first solution was to reimplement the method
/* virtual */ void MainWindow::mousePressEvent(QMouseEvent *event)
In this method, I check the position of the event and check that it is not within the QRect of the table. Unfortunately, I realized that mousePressEvent() is not always called. I suspect that if I click on another child widget of MainWindow, that widget consumes the event and does not pass it through to the parent.
So the only alternative idea I had was to reimplement the mousePressEvent() method for all the widgets contained in MainWindow. This is of course not feasible, because:
There a lot of them: it would be very complex, time-consuming, error-prone, and difficult to maintain if one had to change all the widget classes that are instantiated inside MainWindow.
Some of the subwidgets are implemented in some library modules developed in a parallel project, so I cannot change those.
In other cases, the subwidgets use Qt classes directly.
Even if I defined custom subclasses for 2 and 3, I would have to make sure that these subclasses are used everywhere instead of the original classes. This might imply again falling back to case 2.
So this alternative solution seems unfeasible to me.
Summarizing: Do you know if there is a simple method to catch all mouse clicks on the main window from within the MainWindow class?
You could do this by installing an event filter in the main window. Take a look at QObject::installEventFilter() in the Qt docs.
You can set the attribute Qt::WA_TransparentForMouseEvents with QWidget::setAttribute to all the child widgets except the table to get the mouse events in the MainWindow (which will only work if the table is a direct child of MainWindow).
Or do the opposite, and add a transparent widget above your whole MainWindow with a hole at the position of the table. And you set/unset the Qt::WA_TransparentForMouseEvents to that widget when you want it to let the clicks pass or to catch them.
The hole can be created with QWidget::setMask() and QRegion::substracted().

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. :-)