Test if QQuickView (QWindow) is full-screen in Qt 5.0.x - c++

For a QWidget we can test if it is displayed in full-screen with flags() & Qt::WindowFullScreen.
The same doesn't seem to work with QQuickView (which is a QQuickWindow which is a QWindow), as QWindow::flags() always returns Qt::WindowMinimized, whatever the reason might be. I display the window using this code:
QQuickView w;
w.setSource(...);
w.show(); /* or */ w.showFullScreen();
In Qt 5.1, QWindow::visibility() was introduced. It returns a new enum type which contains QWindow::FullScreen and behaves properly.
How can I test if a QWindow is shown in full-screen in Qt 5.0.x? I want to implement a "toggle full-screen" function. Keeping track of the current state seems to be the wrong way (yet it would be a possible work-around). I don't understand why QWindow::flags() returns Qt::WindowMinimized...
Code to reproduce issue (press RETURN to see the output of QWindow::flags()):
test.qml
import QtQuick 2.0
Rectangle {
signal test();
width: 100; height: 100
focus: true
Keys.onReturnPressed: test()
}
main.cpp
#include <QGuiApplication>
#include <QQuickView>
#include <QQuickItem>
#include <QDebug>
class Test : public QObject {
Q_OBJECT
public slots:
void test() {
QQuickItem *item = qobject_cast<QQuickItem*>(sender());
QQuickWindow *window = item->window();
qDebug() << window->flags(); // Will print 0x1 == Qt::WindowMinimized
}
};
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
QQuickView w;
w.setSource(QUrl("...(relative path to the qml file from above)..."));
w.show(); // Please also test w.showFullScreen();
QObject::connect(w.rootObject(), SIGNAL(test()),
new Test, SLOT(test()));
return a.exec();
}
#include "main.moc"
test.pro
QT += quick
TEMPLATE = app
SOURCES += main.cpp

Use method QWindow::windowState(). It returns key Qt::WindowFullScreen that you seek.
bool isFullScreen = w.windowState().testFlag(Qt::WindowFullScreen);

Related

Qt: cursor blinking cause repaint of parent widget?

Bellow you can see minimal example code to demonstrate problem.
If you run it and give focus to QLineEdit, you get output every second: paintEvent, paintEvent and so on.
I can not understand why MyW::paintEvent called on every
cursor blinking in child widget? As you see I do not configure QLineEdit,
by default on my linux box it have no transparent elements,
but still for some reason cursor cause all widgets to redraw their content?
#include <QApplication>
#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QLineEdit>
class MyW final : public QWidget {
public:
MyW() {
//setAutoFillBackground(false);
}
void paintEvent(QPaintEvent *e) {
e->accept();
qDebug("paintEvent");
QPainter painter{this};
painter.fillRect(rect(), Qt::green);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyW w;
w.resize(600, 600);
w.show();
auto le = new QLineEdit{&w};
le->show();
return app.exec();
}

Running Urho3D and Qt from main

I am using the Urho3D engine with Qt for an application. The problem is that both Urho3D and QApplication require to be ran from main(). For now I am using it in separate processes but IPC makes it complicated.
Is there any way to solve this issue? Thanks
My platform is Urho3D 1.5, Qt 4.71 and Windows 7 x64 and VS2015 (C++)
I'm new to both c++ and Urho3D, but I've successfully achieved it.
Simple code, haven't had further test:
awidget.h:
#ifndef AWIDGET_H
#define AWIDGET_H
#include <QWidget>
#include <QPushButton>
#include <Urho3D/Engine/Application.h>
class aWidget : public QWidget
{
Q_OBJECT
public:
explicit aWidget(QWidget *parent = 0)
{
QPushButton *button = new QPushButton(this);
connect(button, SIGNAL(clicked()), this, SLOT(pressed()));
}
public slots:
void pressed()
{
Urho3D::Context* context = new Urho3D::Context();
Urho3D::Application *application = new Urho3D::Application(context);
application->Run();
}
};
#endif // AWIDGET_H
main.cpp:
#include <QApplication>
#include <awidget.h>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
aWidget *widget = new aWidget();
widget->show();
return app.exec();
}
By the way, I'm using Qt 5.9.0
So the answer is quite simple. Instead of running QApplication by calling
app->exec();
it is needed to manually and regularily call this from your main loop:
app->processEvents();
This will take care that all events used by Qt are processed and QApplication will respond accordingly.
Example:
#include <QApplication>
#include <awidget.h>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
bool shallrun = true;
aWidget *widget = new aWidget();
widget->show();
while (shallrun)
{
app->processEvents();
...
}
...
}

Overlay while loading page into QWebView

Let's say we have a barebones QWebView:
#include <QApplication>
#include <QWebView>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QWebView view;
view.show();
view.setUrl(QUrl("http://google.com"));
return app.exec();
}
How can I display a graphic overlay, preferably fullscreen with transparency and minimal animation (like timer/beachball/etc.) from when the page starts loading till it's finished? Should also be triggered when url changes from within the QWebView.
You can use the LoadingOverlay class provided in this answer to draw an overlay over any QWidget. In your case, show the overlay on top of the QWebView when the signal loadStarted is triggered and hide it, when the signal loadFinished is triggered.
The following code should get you started. I put the code from the linked answer into overlay.h, the subclass of QWebView which handles the showing/hiding of the overlay is in webview.h:
webview.h
#include "overlay.h"
#include <QWebView>
class WebView : public QWebView
{
Q_OBJECT
public:
WebView(QWidget * parent) : QWebView(parent)
{
overlay = new LoadingOverlay(parent);
connect(this,SIGNAL(loadFinished(bool)),this,SLOT(hideOverlay()));
connect(this,SIGNAL(loadStarted()),this,SLOT(showOverlay()));
}
~WebView()
{
}
public slots:
void showOverlay()
{
overlay->show();
}
void hideOverlay()
{
overlay->hide();
}
private:
LoadingOverlay* overlay;
};
main.cpp
#include <QApplication>
#include "overlay.h"
#include "webview.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ContainerWidget base;
Webview w(&base);
base.show();
w.load(QUrl("http://google.com"));
return a.exec();
}

Qt remove title bar

I've a MediaPanel which inherits from QWidget and I want to hide the title bar but event if I set the flags with setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint); (or some other flags like ) the result is still the same :
and if I use setWindowFlags(Qt::Window | Qt::FramelessWindowHint); I lose all the buttons, labels and sliders :
I've played with the Qt example and some combination seems to be impossible...
EDIT :
I've posted a reduced part of my code, could someone tell me where should I set the flags ?
main.cpp :
#include <QApplication>
#include "JokerWindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
JokerWindow w(&settings);
w.show();
return a.exec();
}
JokerWindow.h
#ifndef JOKERWINDOW_H
#define JOKERWINDOW_H
#include <QMainWindow>
#include "PhCommonUI/PhMediaPanelDialog.h"
namespace Ui {
class JokerWindow;
}
class JokerWindow : public QMainWindow
{
Q_OBJECT
public:
explicit JokerWindow(QSettings *settings);
~JokerWindow();
private:
PhMediaPanelDialog _mediaPanel;
};
#endif // MAINWINDOW_H
JokerWindow.cpp
#include "JokerWindow.h"
#include "ui_JokerWindow.h"
JokerWindow::JokerWindow(QSettings *settings) :
QMainWindow(NULL),
ui(new Ui::JokerWindow)
{
_mediaPanel.show();
}
JokerWindow::~JokerWindow()
{
delete ui;
}
PhMediaPanel.h
#ifndef PHMEDIAPANEL_H
#define PHMEDIAPANEL_H
#include <QWidget>
namespace Ui {
class PhMediaPanel;
}
class PhMediaPanel : public QWidget
{
Q_OBJECT
public:
explicit PhMediaPanel(QWidget *parent = 0);
~PhMediaPanel();
private:
Ui::PhMediaPanel *ui;
};
#endif // PHMEDIAPANEL_H
PhMediaPanel.cpp
#include "PhMediaPanel.h"
#include "ui_PhMediaPanel.h"
PhMediaPanel::PhMediaPanel(QWidget *parent) :
QWidget(parent)
{
ui->setupUi(this);
}
PhMediaPanel::~PhMediaPanel()
{
delete ui;
}
setWindowFlags(Qt::Window | Qt::FramelessWindowHint) works for me. Make sure you are applying the setting on your highest level window. e.g in the main.cpp See the image below, forgive the wired 3D thing, testing some OpenGL code.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
WoodPuppet window;
window.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
window.show();
}
This is what I did with qPysie6. I just directly use flags property in QML.
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
id: root
visible: true
width: 400; height: 300
title: "Windows"
flags: Qt.FramelessWindowHint
}
QWindow Class

In Qt, find out that all windows are closed, when QApplication::processEvents() is used?

There is a QApplication::lastWindowClosed() signal. The Qt docs say:
This signal is emitted from QApplication::exec()
when the last visible primary window [...] is closed.
However, I used QApplication::processEvents() instead of QApplication::exec() in a loop. See this minimal example. (save as qapp.h, it must end on .h, and run qmake -project && qmake && make)
#include <QApplication>
#include <QDebug>
#include <QObject>
#include <QMainWindow>
int exitprogram = 0;
class MyMainWindow : public QMainWindow
{
Q_OBJECT
public slots:
void request_exit() {
qDebug() << "exit requested";
exitprogram = 1;
}
};
int main(int argc, char** argv)
{
QApplication app(argc, argv);
MyMainWindow w;
QObject::connect(&app, SIGNAL(lastWindowClosed()),
&w, SLOT(request_exit()));
w.show();
while(!exitprogram)
{
app.processEvents(QEventLoop::AllEvents, 20);
}
}
Is there still a good way to find out, or to even get a signal, if the last such window is being closed?
Whatever reason you have for using processEvents in place of exec is wrong. The two are not equivalent. exec() will, for example, process the deferred deletion events, while processEvents will not. As you've just found out, the lastWindowClosed signal is not emitted either. This should be telling you right there that you're doing it wrong.
The idiomatic Qt way of doing something each time the event loop goes for another iteration, is to use a zero-timeout timer. Those are virtual timers that do not use operating system resources, they are an internal Qt construct.
The example below illustrates the following:
Use of a zero-timeout timer within a QObject.
Use of the State Machine Framework to manage the state of the application. We have three states:
sWindows is the state when the application windows are still shown. The application is set not to quit on the last window being closed.
sSetup is the state reached when the last of the windows was closed. In this state we ask our Object to send its notification signal with the number of times it executed the zero-timeout timer. This will set the proper count in the message label (C++11 code) or in the count label (legacy code). The state machine automatically transitions to the following state.
sMessage is the state when the message labels are shown, and the application is set to quit upon the last window being closed.
The use of a state machine leads to declarative code: you tell the state machine how to behave, without implementing all of the behavior. You only have to implement the behaviors that are specific to your application and not already provided by Qt. The objects that the state machine manages can be very much decoupled, and the code that declares the behavior of the machine is cohesive - it can be all in one function, instead of being spread around. This is considered to be good software design.
Do note that the zero-timeout timer is very diligent: it will force your handler code to execute constantly whenever the event loop is empty. This will force 100% CPU consumption on the core where the GUI thread happens to be executing. If you have nothing to do, you should stop() the timer.
Qt 5 C++11 Code
// https://github.com/KubaO/stackoverflown/tree/master/questions/close-process-19343325
#include <QtWidgets>
int main(int argc, char** argv)
{
QApplication app{argc, argv};
QLabel widget{"Close me :)"};
QLabel message{"Last window was closed"};
int counter = 0;
auto worker = [&]{
counter++;
};
QTimer workerTimer;
QObject::connect(&workerTimer, &QTimer::timeout, worker);
workerTimer.start(0);
QStateMachine machine;
QState sWindows{&machine};
QState sSetup {&machine};
QState sMessage{&machine};
sWindows.assignProperty(qApp, "quitOnLastWindowClosed", false);
sWindows.addTransition(qApp, &QGuiApplication::lastWindowClosed, &sSetup);
QObject::connect(&sSetup, &QState::entered, [&]{
workerTimer.stop();
message.setText(QString("Last window was closed. Count was %1.").arg(counter));
});
sSetup.addTransition(&sMessage);
sMessage.assignProperty(&message, "visible", true);
sMessage.assignProperty(qApp, "quitOnLastWindowClosed", true);
machine.setInitialState(&sWindows);
machine.start();
widget.show();
return app.exec();
}
Qt 4/5 C++11 Code
#include <QApplication>
#include <QLabel>
#include <QStateMachine>
#include <QBasicTimer>
class Object : public QObject {
Q_OBJECT
QBasicTimer m_timer;
int m_counter = 0;
protected:
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() == m_timer.timerId())
m_counter ++;
}
public:
Object(QObject * parent = 0) : QObject{parent} {
m_timer.start(0, this);
}
Q_SLOT void stop() const {
m_timer.stop();
emit countedTo(m_counter);
}
Q_SIGNAL void countedTo(int) const;
};
int main(int argc, char** argv)
{
QApplication app{argc, argv};
Object object;
QLabel widget{"Close me :)"};
QLabel message{"Last window was closed"};
QLabel count;
QStateMachine machine;
QState sWindows{&machine};
QState sSetup{&machine};
QState sMessage{&machine};
sWindows.assignProperty(qApp, "quitOnLastWindowClosed", false);
sWindows.addTransition(qApp, "lastWindowClosed()", &sSetup);
object.connect(&sSetup, SIGNAL(entered()), SLOT(stop()));
count.connect(&object, SIGNAL(countedTo(int)), SLOT(setNum(int)));
sSetup.addTransition(&sMessage);
sMessage.assignProperty(&message, "visible", true);
sMessage.assignProperty(&count, "visible", true);
sMessage.assignProperty(qApp, "quitOnLastWindowClosed", true);
machine.setInitialState(&sWindows);
machine.start();
widget.show();
return app.exec();
}
#include "main.moc"
I modified your code and now it works. I override closeEvent
==> test.cpp <==
#include "windows.hpp"
int exitprogram = 0;
int main(int argc, char** argv)
{
QApplication app(argc, argv);
MyMainWindow w;
w.show();
while(!exitprogram)
{
app.processEvents(QEventLoop::AllEvents, 20);
}
}
==> test.pro <==
TEMPLATE = app
TARGET = test
QT += widgets
INCLUDEPATH += .
HEADERS += windows.hpp
# Input
SOURCES += test.cpp
==> windows.hpp <==
#include <QApplication>
#include <QDebug>
#include <QObject>
#include <QMainWindow>
#include <QCloseEvent>
extern int exitprogram;
class MyMainWindow : public QMainWindow
{
Q_OBJECT
public slots:
void closeEvent(QCloseEvent *event) override {
exitprogram = 1;
event->accept();
}
};