Qt: Setting up buttons on a splash screen - c++

I have a splash screen set up like so, (the QApplication was declared earlier):
QSplashScreen *splash = new QSplashScreen;
splash->setPixmap( QPixmap("image.png" ) );
splash->show();
What I would like to know ifs if there is a way in Qt that allows buttons to be attached to the splash screen. I would like to have some sort of user interaction on the splash screen itself.

Since QSplashScreen class inherits from QWidget class, you probably can access the most of capabilities a QWidget provides e.g. adding child widgets.
However, you should be aware of the following notice pointed to by the doc.
Since the splash screen is typically displayed before the event loop has started running, it is necessary to periodically call QApplication::processEvents() to receive the mouse clicks.
Therefore after registering the click event of that button you should periodically call QApplication::processEvents() or (qApp->processEvents()) during your app initialization to allow the app to handle click events.

Related

Non-clickable QPushButton

I've been trying to make a Qt test app to put two different 'scenes' in, using one main widget which is the window which can hide and show the two other widgets which are the different scenes. In scene 1, there is a QPushButton, which is connected to a signal which is connected to showing scene 2. However, when I click the button, nothing happens. I tried running in debug mode, and the first slot isn't fired, AND the animation of pushing the button down isn't triggering. Is this something to do with the fact that the button is inside a widget inside a widget? I'll add the code if necessary.

Detect widget change in QStackedWidget

I have a GUI that is to be put on a screen that has hardware buttons which map onto function keys. When a top row key is pressed the idea is that the screen will change to a different view of the data with the side buttons mapping into the view currently displayed and displaying corresponding information on screen (button, or label).
I have a top-level widget that contains these buttons and a stacked widget with the different data view (widgets) inside. I can navigate within the stacked widget from the QMainWindow but I cannot work out how the widget knows it no longer has focus so I can pause updates to the data, and given one of these views is video data I don't want it to be constantly updating in the background. Is it reasonable here for the MainWindow to just disconnect all signals, change the widget and then make new connections or is there a better Qt approach? I didn't necessarily want such tight coupling as the view itself knows what it should display on the buttons, not the main window.
I tried overriding focusInEvent(QFocusEvent* e) in the children of the stacked widget but it is never called.
Your QStackedWidget has a signal currentChanged(int index), this signal is fired everytime the current displayed widget on the QStackedLayout changes, can't you use this signal to toggle a flag on the widget displaying video to not to render it?
Whent he currentWidget is the video widget you can resume the rendering of the data( imaghe ) supplied to it, else you can simply discard the data given to it and save CPU cycles by not rendering it?
Am I missing something here?

How to change UI without opening a new window in Qt?

In my program, I'm moving from QMainWindow to QDialog on a press of a button.
I want to do the same without opening a new window and be able to move between the UI's.
The Target device will have a very small touchscreen, so I want my UI to sit still and require minimal repositioning.
Please point me in the right direction or give me an example on How-to.
To do that, you can use a QStackedWidget.
From the documentation:
The QStackedWidget class provides a stack of widgets where only one widget is visible at a time.
Instead of opening a new window, push its content on top of the stack and pop it when you want to (let me say) close the window.
Each widget is a page of your application and no separate window is required. You can design them as you would design a central widget of a normal window or dialog.

How to Layer independent widgets in Qt?

I'm creating an application using Qt which consists of a widget that is used as the background of the application, and a user control interface that is floating above.
A similar example is google maps, where the map is on the background and the controls are on top of the background.
But the thing is that the background widget can be changed to a different widget (there's a widget that displays a map, another widget that displays video feed, ...)
And the same thing happens for the buttons in the user control interface, they are not directly related to the current background and can be change dinamically.
I've tried using a QStackedLayout, using two layers, the background widget and the user control interface. But you cannot interact with the background layer because all the clicks are blocked by the widget in the front.
Any suggestions?
You could place a filter on the event stream to your interface widgets using the QObject::installEventFilter() function, and intercept all the incoming mouse-click events. Once you have captured these events, use the filter function to delegate them to either the background widget, or deliver them to the front interface buttons. You would most likely have to use the (x,y) coordinates of the mouse-click to determine if an event should go to the background widget, or one of the foreground button widgets.
Another option is to create a derived class from QAbstractButton (or whatever QWidget you're using for your buttons), and re-implement the event functions for mouse-clicks on that widget (i.e., QAbstractButton::mousePressEvent(), etc.). When a mouse-click arrives, check to see if the mouse was over the button, and if it wasn't, send the event to the background widget via a signal or QCoreApplication::sendEvent().
Your question is too generic to give you a especific answer, but the most obvious solution is to implement classes that inherits from QWidget for each possible component of you system. In your example I can visualize 2 distinct components: Background and Controls. Background would store all the image data, like maps and videos, while the Controls would have the buttons to interact with the system. You can even break the Background into different classes to manage image or video. I recommend using a central GUIController class that inherits from QObject to manage all the interface interactions, like connecting the signals/slots or implementing any animations, this way you can add/manage multiple widgets without going trough different .cpp's.
EDIT: With your comment, seems that your main problem is that your mouse events are not propagating to your widgets as you expected. Probably the reason for this is that you are not setting the parent/children relationships between the components. Make sure that you are calling the default QWidget constructor in your custom widgets classes like above:
CustoWidget(QWidget *parent = 0, Qt::WFlags flags = 0) : QWidget(parent, flags)
{
//your code here
}
When creating the Controller class, sets the right relationships between the components. In the context of your system, seens to me that all components will be added as Background children, so it would looks like below:
class Controller : public QObject
{
public:
Controller(QObject *parent = 0, Qt::WFlags flags = 0) : QObject(parent, flags)
{
wdg_back_= new BackWidget(this);
wdg_control_ = new Controls(wdg_back);
wdg_1_ = new GenericWidget(wdg_back);
//connect your signals/slots, etc
}
private:
BackWidget *wdg_back_;
Controls *wdg_control_;
GenericWidget *wdg_1_;
}
Ok I've finally found a solution for my issue.
My approach of using QStackedWidget was wrong, widget on the background are not meant to be clickable, and even though it might be done, it's not what I was looking for.
In the end, this is what I've done:
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
MapView *backgroundWidget = new MapView(centralWidget);
backgroundWidget->setMinimumSize(1024,600);
QGridLayout *controlsLayout = new QGridLayout(centralWidget);
MyControlWidget *control1 = new MyControlWidget(centralWidget);
control1->setMinimumSize(140,140);
control1->show();
controlsLayout->addWidget(control1,2,0);
So I create a QWidget, centralWidget which will be the parent of the background and the foreground. Set the background to full screen, and organize the controls in a QGridLayout, which doesn't affect the backgroundWidget.
If I click on a control, the event is processed by this control, but clicking on an empty space will trigger a mouse event on the backgroundWidget, which is what I needed.
I'll test this for some time and if it works fine I'll close the question.

How does a Qt custom widget notify ScrollArea parent about change of view

I'm writing an image viewer as a custom Qt widget (see: https://github.com/dov/Qviv) and I now got stuck on the question of how to make my widget notify a parent QScrollArea of changes in the view port, and thus to tell it to move the scrollbars. E.g. if the image viewer changes the zoom factor as the result of a keypress then the scrollbars need to change their page size.
One way of doing it would be to have the widget explicitly check if the parent is a QScrollArea and then make an explicit call to its methods to notify it on any changes.
Of course I also need to connect the changes of the ScrollArea to the internal view of the image, but that is a different question. And I need to cut the infinite recursion where the widget reports changes to the scrollbar that report changes to the widget etc.
Edit 20:15 Wednesday (GMT/UTC) trying to clarify to Vjo and myself what I need.
What I am trying to achieve is the equivalent of a Gtk widget that has been assigned a pair of GtkAdjustment's that are connected to a horizontal and vertical scrollbar. In my widget GtkImageViewer, that QvivImageViewer is based on, whenever I change the view due to some internal event (e.g. a keypress) I update the GtkAdjustment's. The scrollbars are connected to such changes and are update accordingly. GtkImageViewer also listens to the GtkAdjustment changes, and thus if the user scrolls the scrollbars, the GtkImageViewer is updated with this information and can change its view. My question is whether there is anything similar to GtkAdjustment in Qt that you can connect to for changes, and update in which case the update will be propagated to all the listeners?
Thus I don't expect the ScrollArea to be part of QvivImageViewer, but if the user has placed QvivImageViewer within a ScrollArea, I want bidirectional communication with it so that the scrollbars reflect the internal state of the widget.
The simplest is to send the QResizeEvent event from your widget object to the QScrollArea object.
I finally downloaded the Qt sources and investigated how QTextEdit does it. What I found is that QTextEdit inherits the QAbstractScrollArea on its own, and thus the scroll area and the scrollbars are part of the widget. This is different from Gtk, which uses a higher level of abstraction, through its GtkAdjustment's that are used to signal changes between the scrollbars and the widget. The Qt model is simpler and this is the way that I will implement it in my widget.
It's been a while, but I ran across this same issue.
You can inherit QAbstractScrollArea if you'd like, but QScrollArea will work as well.
Your custom inner widget (i.e. the one that you are scrolling), should do the following when its size changes:
void MyCustomControl::resize_me() {
// recompute internal data such that sizeHint() returns the new size
...
updateGeometry();
adjustSize();
}
QSize MyCustomControl::sizeHint() {
return ... ; // Return my internally computed size.
}
I was missing the adjustSize() call, and without it the QScrollArea will ignore size changes of the internal widget.