Qt 5 (Qt Quick) MenuItem shows up blank most of the time - c++

I'm working on a OneDrive client for Linux built with Qt 5.3 + QtQuick UI controls. The issue I'm having is that MenuItem controls, after being activated, only draw fully every few attempts. Basically, clicking "File" in the Menu either produces a MenuItem called "Exit" or it shows up completely blank (white background, no text, no functionality). The issue shows itself very inconsistently. Sometimes it will do it 90% of the time or other times it will only show up 10-20% but in either case it's noticeable and annoying.
The whole project repository can be found at https://github.com/01000101/onedrive-linux-client/ but I've pasted one of the sections that has this issue. I'm using Qt Creator if that provides any hints. Dynamically generated menus (such as the one I also use for a right-click context menu) also is plagued by this.
Platform: Ubuntu 14.04 x86_64
Kernel: 3.13.0-34-generic
GCC: 4.8.2-19ubuntu1
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.1
import QtQuick.Controls.Styles 1.2
ApplicationWindow {
id: page_auth
visible: true
width: 720
height: 480
color: "#343434"
title: qsTr("OneDrive Linux Client")
menuBar: MenuBar {
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("Exit")
onTriggered: Qt.quit();
}
}
Menu {
title: qsTr("Help")
MenuItem {
text: qsTr("About")
onTriggered: messageDialog.open()
}
}
}

This is a bug in Qt. We have the same problem in our software. You can do nothing about it but wait.

Related

Tumbler in C++/Qt

I'm trying to implement a tumbler to set the time for an alarm in C++. Yet I've only seen tumblers in Qt quick and therefore coded in QML. Now I've tried to get QML code in my C++ code by doing:
void SmartAlarm::showTumbler(){
// Create the QML view
QQuickView* quickView = new QQuickView(QUrl(":/files/includes/AlarmTumbler.qml"));
// Make the QML view resize when the parent is resized
quickView->setResizeMode(QQuickView::SizeRootObjectToView);
QWidget* quickWidget = QWidget::createWindowContainer(quickView);
rightLayout->addWidget(quickWidget);
}
My QML file looks like this:
import QtQuick 2.12
import QtQuick.Window 2.2
import QtQuick.Controls 2.12
import QtQuick.Extras 1.4
TumblerColumn{
id: weekdayTumbler
model: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
}
TumblerColumn {
id: hourTumbler
model: 24
}
TumblerColumn {
id: minuteTumbler
model: 60
}
All I get is a blank, white widget in my layout. What am I doing wrong? Is there a way to implement a tumbler in Qt without using QMLs?
I think it doesn't find the tumbler-file. You can check this the easiest by starting the program and check in the Application Output (Bottom Menu in QTCreator) for following message:
":/files/includes/AlarmTumbler.qml: No such file or directory"
If you can't find it, it might be because you use a Shadow Build and the actual execution-files are in a different folder than the QML Files. To solve this, you can go to "Projects" and deactivate "Shadow Build", rebuild and you should see the tumbler.
The implementation itself should work fine. I tested it locally, added everything to the MainWindow though cause I don't know where your "rightLayout" comes from.
ui->setupUi(this);
// Create the QML view
QQuickView* quickView = new QQuickView(QUrl("tumbler.qml"));
// Make the QML view resize when the parent is resized
quickView->setResizeMode(QQuickView::SizeRootObjectToView);
QWidget* quickWidget = QWidget::createWindowContainer(quickView);
this->ui->rightLayout->addWidget(quickWidget);

Mapbox is not loading on raspberry

I'm trying to load a mapbox in my c++/qt application. On my PC the application is working fine, and the map is loaded. However, when the
application is deployed on the raspberry(v3) the application is running but the map is not loaded(a blank screen appears).
I've tried a different map plugins such as esri and they work fine
on the raspberry. But the mapbox plugin wont work
Here is the code I'm working on
import QtQuick 2.0
import QtQuick.Window 2.0
import QtLocation 5.6
import QtPositioning 5.6
Window {
width: 512
height: 512
visible: true
Plugin {
id: mapPlugin
name: "mapboxgl" // "mapboxgl", "esri", ...
// specify plugin parameters if necessary
// PluginParameter {
// name:
// value:
// }
}
Map {
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(41.38, 2.16) // Oslo
zoomLevel: 14
}
}
And the C++ code
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
I'm expecting a mapbox type map to be loaded but only a blank screen appears. There are no any error messages.
I think it's because a plugin is missing or something. But then why it is working on my laptop since I have the same version of QT in both machines: (QT 5.10)

how can I put a splashscreen on my project using EGFLS in qt

I am developing a user interface with qt/QML and I need to show a splashscreen image at the begininning of the application.
I'm running the application on a device with a iMX6 microprocessor.
I used the library QtSplashscreen but it gives me this error: EGLFS: openGL windows cannot be mixed with others.
I know that it cannot open 2 windows simultaneously, can somebody help?
About your problem, see this question:
OpenGL and Qt Quick 2 applications can only have one fullscreen window existing at a time. Trying to create another OpenGL window, or trying to mix an OpenGL window with a raster one will display the above message and abort the application.
QSplashScreen use another window to show the splash view. So, this is not a direct solution. You can embed your QWidget inside a QQuickItem to use it as QtQuick2 control components.
Another, and faster solution is to use a QML component and load it with a Loader. You can take a look in the Qt Examples Repository, this file is a good example.
Here we go with an easy example;
Loader {
id: splashLoader
anchors.fill: parent
source: "SplashScreen.qml"
asynchronous: false
visible: true
onStatusChanged: {
if (status === Loader.Ready) {
appLoader.setSource("App.qml");
}
}
}
Connections {
target: splashLoader.item
onReadyToGo: {
appLoader.visible = true
appLoader.item.init()
splashLoader.visible = false
splashLoader.setSource("")
appLoader.item.forceActiveFocus();
}
}
Loader {
id: appLoader
anchors.fill: parent
visible: false
asynchronous: true
onStatusChanged: {
if (status === Loader.Ready)
splashLoader.item.appReady()
if (status === Loader.Error)
splashLoader.item.errorInLoadingApp();
}
}

Force signal/slot hookup of not-yet-visible QML item on startup

In Qt's QML language for writing GUI code, QML elements are (if I understand correctly) not actually created until they become visible. (EDIT: It sounds like the elements are created when the QML engine loads them, but it appears that signal/slot connections are not made unless the elements are visible.)
I have some QML elements (LineSeries objects from QtCharts) that record some data over time, and I would like them to start recording data as soon as my app starts up, even though the ChartView elements containing each series aren't immediately visible (users must navigate to a page containing these elements).
Is this possible?
One approach might be to keep each data series itself in some kind of QVariantList containing QPointFs in a global QML object, then dynamically assign it to the desired LineSeries object when the parent ChartView is instantiated. This might be possible using ChartView::createSeries, though I believe the only way to populate the new series would be to call ChartView::series() and pass that to some kind of Q_INVOKABLE method in my C++ backend that would populate the series.
EDIT: Not sure if this is relevant, but the GUI element I'm using for navigation (i.e. the reason the ChartView isn't visible on startup) is a TabView. The ChartView objects are not top-level TabView pages; they're a couple levels down.
EDIT 2: The answer below seems like it should work, but I get the rather unhelpful error TypeError: Type error when I try to implement it. I've put together a minimal (non-)working example here (use qmlscene to run it; I am using Qt 5.5).
EDIT 3: The above non-working version was fixed by simply adding a property alias, thanks to Mitch's answer and comments.
Items in Qt Quick are created as soon as the QML they reside in is loaded by the QML engine (even if they default to non-visible). The exception to this rule are items that dynamically load their content, like Loader.
In your edit, you said that you're using TabView. I think that the setup you have is something like this:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
ApplicationWindow {
title: qsTr("Hello World")
width: 800
height: 700
visible: true
TabView {
id: sv
anchors.fill: parent
Tab {
title: "Page 1"
}
Tab {
title: "Page 2"
ChartView {}
}
}
}
Try changing it to something like this:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
ApplicationWindow {
title: qsTr("Hello World")
width: 800
height: 700
visible: true
ChartView {
id: chartView
color: "red"
anchors.fill: parent
visible: false
Component.onCompleted: print("Monitoring data...")
}
TabView {
id: sv
anchors.fill: parent
Tab {
id: tab1
title: "Page 1"
}
Tab {
id: tab2
title: "Page 2"
onActiveChanged: {
if (active) {
chartView.parent = tab2;
chartView.visible = true;
}
}
}
}
}
Tabs are basically just Loaders, so they have all of Loader's API, including the active property. This property lets you know when that tab has been loaded. Before that stage, it's inaccessible.
When the tab becomes active, we reparent the ChartView to it so that it's displayed in the correct place, and then show it.
As you can see from the debug output, the ChartView is created at startup. You can move it somewhere else to control when it's loaded, or... use a Loader. :)
EDIT: Based on this answer and the discussion in the comments, OP has created a small working example that demonstrates how persistent items can be pre-loaded and re-parented.

QML FontLoader not working

I'm trying to use QML's built-in FontLoader element to load a custom font for our application without success.
I've tried using both OTF and TTF fonts with identical results.
The fonts are in the same directory as the project files. There is only one QML, the main one where this FontLoader lives.
This is what it should look like:
Here is my code:
import QtQuick 2.0
Rectangle {
width: 360
height: 360
FontLoader {
id: cFontLoader
source: "./fontlol.ttf"
}
Text {
id: testText
anchors.centerIn: parent
text: "Hello Fonts!"
font.family: cFontLoader.name
font.pointSize: 32
}
}
I've had headaches with Qt/QML's font handling. Fonts with "various sub styles" seem to be the fundamental problem. When I absolutely needed to get at one particular problem font style in Qt, creating a custom version with fontforge of the font where the wanted style was renamed "normal" seemed to work.
I've also expirienced that problem, but in mine case it was because I've added the "name" property. When I deleted name font start showing.
The text component of QML recognizes fonts by their font name. However, if you load different font types, usually the font name within the metadata of the font is the same.
The text component has a property font.styleName, which you can use to access different types of a font:
FontLoader{id: loader source: "AwesomeFont-Bold.ttf"}
Text
{
font.family: loader.name
font.styleName: "Bold"
}