I finished a Qt Quick UI project, where I am using many QML and audio files. It is an application for children. In the main screen I have 10 sections. One is for letters (Pismena.qml), second for numbers(Cislice.qml) etc (Tvary.qml,Farby.qml). If you choose some section, then you can browse through the images, which are accompanied by sound. One section contains about 30 png and 30 mp3 files. Everything works fine.
But if I want to deploy this application and transform this project into a Qt Quick Application project, I have a problem. For three sections it is OK, but if I want to use four sections, I get errors like:
Error: "Internal data flow error."
Error: "GStreamer encountered a general stream error."
Error: "Failed to connect stream: Too large"
These error messages are displayed immediately when I start the application, not when I am browsing the images.
Also some audio elements are not played.
Here is my main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
Here is my main.qml (it's not complete)
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtGraphicalEffects 1.0
import QtQuick.Window 2.0
import QtMultimedia 5.0
ApplicationWindow {
visible: true
width: 1024
height:300
Rectangle {
width: parent.width
height: parent.height
id: appWindow
property alias pismenaIconAlias: pismenaIcon
Pismena{
id: pismena
visible: false
}
Cislice{
id: cislice
visible: false
}
Farby{
id: farby
visible: false
}
Tvary{
id: tvary
visible: false
}
Image{
id: pismenaIcon
source: "file:" + applicationDirPath + "/obrazky/pismenaIcon.png"
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
parent.visible = false
pismena.visible = true
}
}
}
Image{
id: cisliceIcon
source: "file:" + applicationDirPath + "/obrazky/cisliceIcon.png"
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
parent.visible = false
cislice.visible = true
}
}
Image{
id: farbyIcon
source: "file:" + applicationDirPath + "/obrazky/farbyIcon.png"
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
parent.visible = false
farby.visible = true
}
}
Image{
id: tvaryIcon
source: "file:" + applicationDirPath + "/obrazky/tvaryIcon.png"
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
parent.visible = false
tvary.visible = true
}
}
}
}
In the main.qml file, if you choose Pismena(pismenaIcon Image element), you are redirected to that file - Pismena.qml, where you can browse through Images with sounds:
import QtQuick 2.3
import "myJava.js" as MyScript
import QtMultimedia 5.0
import QtQuick.Window 2.0
Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
Audio {
id: hrajPismeno
}
Image {
id: pis
MouseArea{
anchors.fill: parent
onClicked: {
pis.source = "file:" + applicationDirPath + MyScript.cobr()
hrajPismeno.source = "file:" + applicationDirPath + MyScript.zobr()
hrajPismeno.play()
}
}
}
}
And here is my myJava.js
.pragma library
var pr = 0;
var c = 1;
var z = 1;
var numberOfItems = 33;
var itemFolder = "\/pismena\/";
function cobr(){
c = (c === numberOfItems) ? 0 : c;
c = c + 1;
var s = itemFolder + c + ".png";
return s;
}
function setLetters(){
numberOfItems = 33;
itemFolder = "\/pismena\/";
}
function zobr(){
z = (z === numberOfItems) ? 0 : z;
z = z + 1;
var r = itemFolder + z + ".mp3";
return r;
}
I am using Qt 5.3 On Linux Mint 13.
Why I can not use many Audio files?
In Pismena.qml you have not set the initial width and height for the Item and also for the Image. So in the window there is no place where user can actually click. Also there is no default path for the Image element.
EDIT
In each Audio element, set the autoLoad property to false.
Related
I am new to Qt QML and trying to implement a splash screen in qml.
But, I am ended with below error when running the ui in eglfs instance.
"EGLFS: OpenGL windows cannot be mixed with others."
I have referred the below code from GIT and it was working good in x86 instance
Could you please help me in resolving this.
main.qml
Item {
Loader {
id: mainWindowLoader
anchors.fill: parent
visible: false
source: "qrc:/window.qml"
asynchronous: true
onLoaded: {
item.visible = true;
splashScreenLoader.item.visible = false;
splashScreenLoader.source = "";
}
}
Loader {
id: splashScreenLoader
source: "qrc:/splashscreen.qml"
anchors.fill: parent
asynchronous: false
onLoaded: {
mainWindowLoader.active = true;
}
}
}
spalshscreen.qml
Window {
id: splashScreen
modality: Qt.ApplicationModal
flags: Qt.SplashScreen
width: 1024
height: 600
Rectangle {
id: splashRect
anchors.fill: parent
color: "white"
border.width: 1
border.color: "black"
Text {
id: initializationErrorMessage
text: "This is the splash screen"
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 50
font.bold: true
font.pixelSize: 20
color: "black"
}
}
Component.onCompleted: visible = true
}
window.qml
ApplicationWindow {
id: mainWindow
flags: Qt.Window | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.WindowCloseButtonHint
width: 1024
height: 600
visible: false
title: "Scresh Screen Test"
Component.onCompleted: {
var timeout = new Date().valueOf() + 3000;
while(timeout > new Date().valueOf()) {}
}
Text {
text: "Window ready!"
anchors.centerIn: parent
font.bold: true
font.pixelSize: 20
color: "black"
}
}
main.cpp
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
I'm working on a project that gets news with API. I can clearly get the news from api and load them to the listview.
I simplify the code for telling my problem clearly.
Here is a 2 questions...
1 - I need to slide this list from top to the bottom basic sliding animation with given time. (eg. y from 0 to en of list with 5secs). The important point is the item count of the list can be changeable.
2 - When the animation reachs to the end of the list, I need to see the first item after the last item. But it has to be like this; after the last item of list, the first item has to shown( like infinite list) while the sliding process going on.
Here are my codes;
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QStringList news = { "news01",
"news02",
"news03",
"news04",
"news05",
"news06",
"news07",
"news08",
"news09",
"news10",
"news11",
"news12",
"news13",
"news14",
"news15",
"news16",
"news17",
"news18",
"news19",
};
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("listNews",news);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.3
Window {
id:pencere
visible: true
width: 640
height: 480
title: qsTr("Hello World")
color: "black"
ListView{
id: newsListView
implicitWidth: parent.width
implicitHeight: parent.height
model:listNews
spacing: 5
delegate: Rectangle {
id: delegateBackground
color:"#505051"
radius: 10
width: parent.width
height: contentContainer.height + 20
Item {
id: contentContainer
width: parent.width - 20
height: column.height
anchors.centerIn: delegateBackground
RowLayout {
width: parent.width
Rectangle {
id: newsicon
width: 16
height: 16
color: "steelblue"
Layout.alignment: Qt.AlignTop
}
ColumnLayout {
id: column
Layout.fillWidth: true
spacing: 100
Text {
Layout.fillWidth: true
Layout.alignment: Qt.AlignBottom
id: messageText
text: modelData
wrapMode: TextEdit.WordWrap
verticalAlignment: index %2 == 0 ? Text.AlignBottom : Text.AlignTop
color: "white"
}
}
}
}
}
}
}
For the first question you could add something like the following to your ListView. This will trigger an animation if you press the arrow key up/down. It isn't perfect, but it explains how to use NumberAnimations. The key to move the ListView content is the property contentY. If you want to scroll all the way to the bottom of the news feed you could calculate the position by using contentHeight of the ListView and the Window height.
ListView {
id: newsListView
property bool scrollUp: false
property bool scrollDown: false
focus: true
Keys.onUpPressed: newsListView.scrollUp = true
Keys.onDownPressed: newsListView.scrollDown = true
NumberAnimation on contentY {
running: newsListView.scrollDown
from: 0
to: newsListView.contentHeight
duration: 1000
onFinished: newsListView.scrollDown = false
}
NumberAnimation on contentY {
running: newsListView.scrollUp
from: newsListView.contentHeight
to: 0
duration: 1000
onFinished: newsListView.scrollUp = false
}
...
}
For the first question as proposed by #iam_peter, you can try using NumberAnimation to animate scrolling. For second query, in my opinion you can try researching on PathView as it is much easier to get circular list behavior in PathView without cumbersome index calculations.
Also, please have a look at this topic ListView Scrolling.
After successfully designing the layout of a small application from my previous post I am adding the logic of the events. I almost completed it but some events are not happening as I am planning. Below the logic and the full source code here in case would like to verify:
1) As soon as I chose the robot to connect to as show below, It does show I am connecting, but I am not able to interact with the QML page at all and all actions are blocked. I think this could be due to the fact that I have 2 ColumnLayout and I think that one is overwriting the other but I am not sure why that is happening as I thought the logic was complete:
The expected result would be that when I am connecting to the robot, the entire page works instead of being (or looking) disable.
Below the most important part of the code that composes the Minimal Reproducible Example with the problem:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
main.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtWebEngine 1.8
import QtQuick.Controls.Styles 1.4
ApplicationWindow {
id: root
visible: true
width: 440
height: 630
title: qsTr("Conn")
property Page1 page1: Page1 {}
property Page2 page2: Page2 {}
Component.onCompleted: {
page1.selectDialog.connect(function() {
mystackview.push(page2);
});
page2.onButtonClicked.connect(function(buttonId) {
page1.dialogId = buttonId;
mystackview.pop();
});
}
StackView {
id: mystackview
anchors.fill: parent
initialItem: page1
}
}
Page1.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls.impl 2.12 // for IconLabel
import QtWebEngine 1.8
Page {
property int dialogId: -1
signal selectDialog()
function buttonClick(button)
{
button.text = qsTr("Connecting to %1...").arg(button.text);
button.enabled = false;
if (button.background && button.background instanceof Rectangle) {
button.background.color = "green";
button.background.gradient = null;
button.background.visible = true;
}
if (button.contentItem && button.contentItem instanceof IconLabel) {
button.contentItem.color = "white";
button.contentItem.font.bold = true;
button.contentItem.font.pointSize = 20;
}
}
function buttonClearList(buttonClear)
{
buttonClear.text = qsTr("Clear List").arg(buttonClear.text);
buttonClear.enabled = true;
if (buttonClear.background && buttonClear.background instanceof Rectangle) {
buttonClear.background.color = "red";
buttonClear.background.gradient = null;
buttonClear.background.visible = true;
}
if (buttonClear.contentItem && buttonClear.contentItem instanceof IconLabel) {
buttonClear.contentItem.color = "white";
buttonClear.contentItem.font.bold = true;
buttonClear.contentItem.font.pointSize = 20;
}
}
ColumnLayout {
// anchors.fill: parent
// anchors.topMargin: 0 // margin from top of the page
Layout.fillWidth: true
width: parent.width
spacing: 5
Button {
id: button1
text: "Select Robot"
width: parent.width
onClicked: selectDialog()
Layout.fillWidth: true
font.pointSize: 20
}
Button {
id: dialogA
text: "Freddie Mercury: Connected"
visible: dialogId === 1
Layout.fillWidth: true
font.pointSize: 20
spacing: 10
onClicked: {
buttonClick(this)
}
ColumnLayout {
anchors.fill: parent
anchors.topMargin: 50 // margin from top of the page
Layout.fillWidth: true
spacing: 10
GroupBox {
id: box1
width: parent.width
title: "Connection"
font.pointSize: 20
Layout.fillWidth: parent
spacing: 10
GridLayout {
width: parent.width
columns: 1
RowLayout {
id: row1
spacing: 200
Layout.fillWidth: true
Layout.fillHeight: false
Label {
id: textField
text: "Connection:"
font.pointSize: 15
Layout.fillWidth: true
}
Text {
id: connected
text: "Not-Connected"
color: "red"
font.pointSize: 15
horizontalAlignment: Text.AlignRight
Layout.fillWidth: true
}
}
}
}
Button {
id: clist
text: "Clear List";
Layout.fillWidth: true
font.pointSize: 20
width: parent.width
onClicked: {
buttonClearList(this)
}
}
}
}
}
}
Page2.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Page {
signal onButtonClicked(var buttonId)
Component.onCompleted: {
button1.clicked.connect(function() {
onButtonClicked(1);
});
}
ColumnLayout {
id: mybuttons
anchors.fill: parent
spacing: 5
Button {
id: button1
Layout.fillWidth: true
Layout.fillHeight: true
text: "Freddie Mercury"
font.pointSize: 20
}
}
}
So far I have been trying very different combinations of locating the ColumnLayout in different places. But my doubt i: I already have a ColumnLayout and after that I have another ColumnLayout, and I think that they are overwriting each other.
However, from the official documentation and also consulting other sources re is no problem in using it in a nested loop.
The same post talks about how a Column is a Positioner, while a ColumnLayout is a Layout.
I was sure I was using in the right way but something is missing.
Please point out in the right direction to solve this problem.
Basic design rule: If the parent item is disabled the children too.
Explanation:
In your case, the ColumnLayout is the child of the Button and this is the container of the other items that are your children, so if Button is disabled by the previous ColumnLayout rule, it will also be, and consequently also the entire contents of the ColumnLayout.
Solution:
In your case it is not necessary for ColumnLayout to be the children of Button but it can be on the same level.
On the other hand you have other errors:
If you are going to use Layout.XXX then you should not use the widths.YYY since they fulfill the same task but if you use both you can have problems since it can have an indefinite behavior since they will compete with each other.
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls.impl 2.12 // for IconLabel
Page {
property int dialogId: -1
signal selectDialog()
function buttonClick(button)
{
button.text = qsTr("Connecting to %1...").arg(button.text);
button.enabled = false;
if (button.background && button.background instanceof Rectangle) {
button.background.color = "green";
button.background.gradient = null;
button.background.visible = true;
}
if (button.contentItem && button.contentItem instanceof IconLabel) {
button.contentItem.color = "white";
button.contentItem.font.bold = true;
button.contentItem.font.pointSize = 20;
}
}
function buttonClearList(buttonClear)
{
buttonClear.text = qsTr("Clear List").arg(buttonClear.text);
buttonClear.enabled = true;
if (buttonClear.background && buttonClear.background instanceof Rectangle) {
buttonClear.background.color = "red";
buttonClear.background.gradient = null;
buttonClear.background.visible = true;
}
if (buttonClear.contentItem && buttonClear.contentItem instanceof IconLabel) {
buttonClear.contentItem.color = "white";
buttonClear.contentItem.font.bold = true;
buttonClear.contentItem.font.pointSize = 20;
}
}
ColumnLayout {
Layout.fillWidth: true
width: parent.width
spacing: 5
Button {
id: button1
text: "Select Robot"
width: parent.width
onClicked: selectDialog()
Layout.fillWidth: true
font.pointSize: 20
}
Button {
id: dialogA
text: "Freddie Mercury: Connected"
visible: dialogId === 1
Layout.fillWidth: true
font.pointSize: 20
spacing: 10
onClicked: {
buttonClick(this)
}
}
ColumnLayout {
id: layout
visible: dialogId === 1
Layout.fillWidth: true
spacing: 10
GroupBox {
id: box1
width: parent.width
title: "Connection"
font.pointSize: 20
Layout.fillWidth: parent
spacing: 10
GridLayout {
width: parent.width
columns: 1
RowLayout {
id: row1
spacing: 200
Layout.fillWidth: true
Layout.fillHeight: false
Label {
id: textField
text: "Connection:"
font.pointSize: 15
Layout.fillWidth: true
}
Text {
id: connected
text: "Not-Connected"
color: "red"
font.pointSize: 15
horizontalAlignment: Text.AlignRight
Layout.fillWidth: true
}
}
}
}
Button {
id: clist
visible: dialogId === 1
text: "Clear List";
Layout.fillWidth: true
font.pointSize: 20
width: parent.width
onClicked: {
buttonClearList(this)
}
}
}
}
}
I have a form where i've done a custom field that only accepts the top, right and bottom arrows.
But to accept the tab navigation i'm using the following chain of functions:
nextItemInFocusChain().forceActiveFocus()
The problem is that this is working on windows but not on mac...
I've a formulary to illustrate the problem where next to that "code text field" i have a comboBox where i want, that when the user clicks on tab in the "code text field" to navigate to.
It seems that it only navigates to other textFields, and a spinBox, like i have on the example seems to have a textField as a contentItem.
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml
import QtQuick 2.9
import QtQuick.Controls 2.0
ApplicationWindow {
id: window
title: "Stack"
visible: true
height: 200
width: 400
Item {
id: page
anchors.fill: parent
width:parent.width
height: parent.height
Column{
width:parent.width
spacing:10
TextField {
id:textField
KeyNavigation.tab: spinBox1
implicitHeight: 30
font.bold: true
}
SpinBox {
id: spinBox1
width: 100
height: 30
editable: true
Component.onCompleted: contentItem.KeyNavigation.tab = userCodeField
}
PanelCodeField {
id: userCodeField
width: 100
height: 30
KeyNavigation.tab: comboBox
}
ComboBox {
id:comboBox
anchors.topMargin: 10
model: [ "Banana", "Apple", "Coconut" ]
KeyNavigation.tab: spinBox2
}
SpinBox {
id: spinBox2
width: 100
height: 30
editable: true
Component.onCompleted: contentItem.KeyNavigation.tab = textField
}
}
}
}
PanelCodeField.qml
import QtQuick 2.0
PanelTextField {
height: 479.9
visible: true
maximumLength: 5
font.pointSize: 12
property bool jumpOnTab: false
Keys.onPressed: {
var c
switch (event.key) {
case Qt.Key_Up:
c = String.fromCharCode(0x25B2)
break
case Qt.Key_Down:
c = String.fromCharCode(0x25BC)
break
case Qt.Key_Right:
c = String.fromCharCode(0x25B6)
break
case Qt.Key_Tab:
if(jumpOnTab)
nextItemInFocusChain().nextItemInFocusChain().forceActiveFocus()
else
nextItemInFocusChain().forceActiveFocus()
event.accepted = true
break
default:
event.accepted = true
break
}
if (!event.accepted) {
var s = text.concat(c)
text = s.substr(Math.max(0,s.length-maximumLength), maximumLength)
event.accepted = true
}
}
}
PanelTextField.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
TextField {
property var linkedData
implicitHeight: 30
font.bold: true
implicitWidth:parent.width
}
Am i doing something wrong for the mac os x, or is there a workaround?
Open System Preferences > Keyboard > Shortcuts and select All Controls. By default macOS only allows tab navigation between "Text boxes and lists only".
I have a trouble in changing Video item sources. In a code below I pick randomly a mov file from the folder on a mouse click. After 2 - 7 (max) times it always hangs (on changing). All movs are rather small (700 kb - 7 mb), H.264, Mac OS. Any ideas how to fix it?
import QtQuick 2.4
import QtMultimedia 5.4
import Qt.labs.folderlistmodel 2.1
Item {
id:container
property bool change_video: false
width: 320
height: 240
FolderListModel {
id: folderModel
folder: "file:///Users/michaellevin/Dropbox/Movie/Xcanvas/XXX/animation/"
nameFilters: ["*.mov"] }
Video
{ id: vvv
width: container.width
height: container.height
//autoLoad: true
autoPlay: true
anchors.fill: parent
anchors.margins: 0
onStopped: play()
}
MouseArea {
id: xxx
anchors.fill: parent
onClicked: {
var index = Math.floor(Math.random()*(folderModel.count))
print(index)
//vvv.stop()
vvv.source = folderModel.get(index, "fileURL")
//vvv.play()
}
}
Timer {
id: start; interval: 10; running: true; repeat: false;
onTriggered: vvv.source = folderModel.get(2, "fileURL")
}
}