mouse over transparency in Qt - c++

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

Related

figuring out what causes paintEvent with weird clipRegion in Qt5

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?

How to force Qt update the widget under mouse?

On Windows 7 to be specific, while I don't think it matters.
We have all seen this issue in countless desktop applications, especially games that tend not to use OS-supplied controls: when the screen changes programmatically under a motionless mouse cursor (as opposed to user moving the cursor to a new widget), they go out of sync. Either the cursor does not change or the widget is not painted as it should be with the cursor inside it - obviously the widget's mouse enter event is not triggered. If you shake the mouse a bit without even leaving the widget, the thing fixes itself.
Sadly, Qt 5.7 shares this widespread problem. The first solution to come to mind is to move the mouse programmatically to (0, 0) and back by Windows means. However, it's not cross-platform(ish). Any better ideas?
I don't know if your question is still actual
You can override method underMouse() with following code:
bool MyWidget::underMouse()
{
return rect().contains(mapFromGlobal(QCursor::pos()));
}
Events moveEvent or resizeEvent in the rest panels will be definitely triggered when splitter resizes panel. All you need is check if widget is under mouse and then invoke enterEvent() manually
I found two solutions.
The first one is a simple hack: Call widget->hide() and then immediately widget->show(). This will reevaluate and update the widget's visual state depending on whether it is under mouse cursor or not, even if the cursor has not moved. But I would not recommend this solution because it might have some unwanted side effects. Though I have not encountered any yet.
The second solution is better because it does not look like a hack and it probably does not have any side effects:
widget->setAttribute(Qt::WA_UnderCursor, qApp->widgetAt(QCursor::pos()) == widget);
widget->update();
The code is assumed to be called from widget's parent. But you can adjust it and calle it from any other place. Note: it is better to use QApplication::widgetAt() than widget->rect().contains(), which is suggested in another answers, because in the latter case we would get false positives for widgets which are overlayed by other widgets.
What is actually complicated, is to find the place in code from where you should call this. Because there can be many sources of the widget's motion - moving withing its parent, moving of parent(s), resizing, resizing of parent(s), scrolling etc. This is probably the reason why this would be too complicated to implement this to standard Qt widget library. It would be probably a performance killer in some scenarios. (my guess)
Just to show my usage: I am moving a whole container widget which contains many child widgets. Subsequently one of the child widgets may get under the cursor after the container is moved. So I call:
containerWidget->move(dx, dy); // this moves the container
for (QWidget *child : containerWidget->findChildren<QWidget*>())
{
child->setAttribute(Qt::WA_UnderMouse, qApp->widgetAt(QCursor::pos()) == child);
child->update();
}

Qt - Make QMainWindow to non resizible in Qt Designer

Is it there a way to set a QMainWindow to be non-resizible in Qt Designer? I am seeing lots of coding examples but I want to do as much UI customization in Qt Designer as I can. So far I can only get this by setting the minimum size and maximum size to be equal, but still there is the resize arrow in the corner of the window and a "maximize" button on the top of the window.
When you select the QMainWindow, the properties of the object does contain a field for sizePolicy, both horizontal and vertical, as mentioned by the answer of #jester and you can set those to fixed.
I have found that doesn't always work and was never sure why (perhaps to due to layouts), but as you've found out, if you set the minimumSize and maximumSize fields to the same value, it does what you want.
As for the resize arrow and maximize button, I have never been able to do that from Qt Creator (designer), so I would say it's not possible. However, just one line of code is all you should need in the constructor of your class: -
setWindowFlags(Qt::Window | Qt::CustomizeWindowHint);
By default, the window flags include Qt::WindowMaximizeButtonHint. By setting the above flags, you're stating that you want to customise the window to include the specified elements. This will also remove the minimise button, so if you want that too, you should add Qt::WindowMinimizeButtonHint
I am not using Qt Designer; I am just writing a subclass of QMainWindow made from scratch. The solution I found for having a non-resizable window is to call setFixedSize on the QMainWindow after you have set up all your widgets and layouts. If you have set things up well, then you don't have to pick a size manually; you can just get the size from sizeHint. The line of code I used inside my subclass of QMainWindow is:
setFixedSize(sizeHint());
I tested this in Qt 5.5 on Windows 8.1 and everything looks fine: the maximize button gets disabled but the other buttons are still there, and the cursor does not indicate the possibility of resizing when the user moves it to the border.
use the setFixedSize property for the QMainWindow. In designer, if I remember correctly, you can set the horizontal and vertical sizePolicy to Fixed.
Sadly there is no option to do that; in VS you may find an option in the editor, to remove the mouse trigger that resize the window; but for some reason, QT5 does not have one.
I tried to use sizePolicy and set it as fixed for mainWindow; but this does nothing for both the horizontal and vertical policy.
To solve the problem, I did set my mainwindow minimum and maximum size as the same values; and when you run the application, the mouse cursor won't be enabled for resizing.
It is an ugly way to do something so simple, but this is the only way I found in QT designer, without use code.
I solved the problem of Qt5 which is displaying mouse arrow resize window even with window having fixed size, but in Python, but you can make modifications for C++.
MainWindow.setWindowFlags(QtCore.Qt.MSWindowsFixedSizeDialogHint)
It's an old post but I want to help if someone need it.
I found a way (not so beautiful) but it works directly from QTDesigner.
You can lock the resize by writing the values of height and width also inside "MinimumSize" and "MaximumSize" property.
Oviously also set "Fixed" on vertical and horizontal as told by other users.
This will remove the button to enlarge the window.

QWidget Transformation

I am writing an application using Qt and would like to have a "Metro Style" interface. Everything is finished except I don't know how to make the widget appear and disappear. For instance, in WPF you can animate (UIElement.RenderTransform).(TranslateTransform.Y) so that Y becomes zero or negative. How can I move the QWidget in a QGridLayout so that it can hide?
Example:
After doing some research I figured out a way to do this. Instead of letting Qt do the layout I simply handled it myself via move and set width/height functions. Overriding resizeEvent made it so I could update the values in case the window was resized. Additionally I used setMask to ensure that the widget did not leak over to unwanted locations in the UI.

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