I want to set my demo layout is Right to Left, and I set this in main function, like this:
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
app.setLayoutDirection(Qt::RightToLeft)
return app.exec();
}
Here is my qml file:
import QtQuick 2.6
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
id:root
Row {
spacing: 20
Repeater {
model: 5
Rectangle {
color: "red"
opacity: (5 - index) / 5
width: 70; height: 30
Text {
text: index + 1+" hello"
width:parent.width
}
}
}
}
}
However the layout result still is left to right:
How can I get the real RTL layout, all components are right to left, include the text, just like this:
Right-to-left User Interfaces says that you should use the LayoutMirroring attached properties. Taking the example from that page:
import QtQuick 2.0
Rectangle {
LayoutMirroring.enabled: true
LayoutMirroring.childrenInherit: true
width: 300; height: 50
color: "yellow"
border.width: 1
Row {
anchors { left: parent.left; margins: 5 }
y: 5; spacing: 5
Repeater {
model: 5
Rectangle {
color: "red"
opacity: (5 - index) / 5
width: 40; height: 40
Text {
text: index + 1
anchors.centerIn: parent
}
}
}
}
}
Related
I'm trying to do a menu that might have submenus for some of its options.
The behavior i want it to have is the same we see on most of websites.
When we hover an option that has a submenu, that submenu it will happear, if the mouse arrow goes anywhere else that is not the submenu the submenu will close.
I'm going to illustrate with images.
When we enter the submenu we have this:
Now we hover the Language option its submenu will happear
Now what is not done is the behavior i want. If we are hovering on the Languageoption the submenu is visible. If i go directly from language to the language's submenu it will remain there as intented.
The code of this example is provided below:
main.qml
#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.7
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.3
ApplicationWindow {
visible: true
width: 640
height: 500
title: qsTr("Tabbars")
Button{
id: button
text: "Menu"
onClicked: contextMenu.open()
anchors.top:parent.top
anchors.left:parent.left
height: 20
width: 100
}
Menu {
id: contextMenu
y: button.height
padding: 1
background: Rectangle {
implicitWidth: 200
border.color: "#fff"
color: "#000"
}
Button {
id: languageMenuItem
text: qsTr("Language")
width:parent.width
height: 35
background: Item {
Rectangle {
anchors.fill: parent
color: "#555"
opacity: mouseArea1.pressed ? 1 : mouseArea1.containsMouse ? 0.6 : 0.0
MouseArea {
id: mouseArea1
anchors.fill: parent
hoverEnabled: true
onEntered: function() {
submenuLanguage.open()
}
onExited: function() {
}
}
}
}
contentItem: Text {
text: languageMenuItem.text
color: "#fff"
font.pointSize: 12
font.bold: true
}
Rectangle {
z: 1
color: "#000"
opacity: 0.5
anchors.fill: parent
visible: !parent.enabled
}
Component.onCompleted: {
mouseArea1.clicked.connect(clicked)
}
}
CMenuItem{
text: qsTr("Exit")
width: parent.width
onClicked: close()
}
}
Menu {
id:submenuLanguage
x: contextMenu.width
background: Rectangle {
implicitWidth: 200
border.color: "#fff"
color: "#000"
}
Connections {
target: mouseArea1
onExited: {
console.log("mouseArea leaving")
}
}
CMenuItem{
id:btlingen
width: parent.width
text: qsTr("English")
onClicked: {
contextMenu.close()
console.log("English")
}
}
CMenuItem{
id:btlingpt
width: parent.width
text: qsTr("Português")
onClicked: {
contextMenu.close()
console.log("Português")
}
}
CMenuItem{
id:btlinges
width: parent.width
text: qsTr("Español")
onClicked: {
contextMenu.close()
console.log("Español")
}
}
CMenuItem{
id:btlingit
width: parent.width
text: qsTr("Italiano")
onClicked: {
contextMenu.close()
console.log("Italiano")
}
}
CMenuItem{
id:btlingde
width: parent.width
text: qsTr("Deutsch")
onClicked: {
contextMenu.close()
console.log("Deutsch")
}
}
}
}
CMenuItem.qml
import QtQuick 2.0
import QtQuick.Controls 2.1
import QtQuick.Controls.Styles 1.4
MenuItem {
id: mainMenuItem
background: Item {
Rectangle {
anchors.fill: parent
color: "#555"
opacity: mouseArea.pressed ? 1 : mouseArea.containsMouse ? 0.6 : 0.0
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
}
}
}
contentItem: Text {
text: mainMenuItem.text
color: "#fff"
font.pointSize: 12
font.bold: true
}
Rectangle {
z: 1
color: "#000"
opacity: 0.5
anchors.fill: parent
visible: !parent.enabled
}
Component.onCompleted: {
mouseArea.clicked.connect(clicked)
}
}
How can i do this?
Use the cascade property to create a nested menu:
ApplicationWindow {
id: window
width: 320
height: 260
visible: true
menuBar: MenuBar {
Menu {
title: qsTr("&Foo")
Menu {
cascade: true // Nested menu
title: qsTr("&Bar")
Action { text: qsTr("A1") }
Action { text: qsTr("A2") }
Action { text: qsTr("A3") }
}
}
}
}
I am trying to run the following, but nothing happens when I run it.
How can I debug such an issue?
import QtQuick 2.0
import QtQml.Models 2.1
Item{
id: main
width: 1500
height: 1500
GridView {
id: root
width: 1500
height: 1500
cellWidth: 200; cellHeight: 200
visible: true
model: DelegateModel {
model: ListModel {
ListElement {
color: "blue"
}
ListElement {
color: "white"
}
ListElement {
color: "red"
}
ListElement {
color: "green"
}
ListElement {
color: "orange"
}
ListElement {
color: "yellow"
}
ListElement {
color: "grey"
}
}
delegate: MouseArea {
objectName: "mousearea"
implicitHeight: parent.height
implicitWidth: parent.width
Rectangle {
anchors.fill: parent
color: model.color
}
drag{
target: parent
}
}
}
}
}
What I intend from this code is the following:
create few rectangles inside a GridView and add a MouseArea to them and try dragging them around afterwards. I am not sure if my model structure is correct here.
EDIT:
Adding 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();
}
QQmlApplicationEngine expects to have a Window as the root element as indicated by the docs:
...
Unlike QQuickView, QQmlApplicationEngine does not automatically create
a root window. If you are using visual items from Qt Quick, you will
need to place them inside of a Window.
...
So the solution is simple, change Item by Window:
main.qml
import QtQuick 2.0
import QtQuick.Window 2.11
import QtQml.Models 2.1
Window{
visible: true
id: main
width: 1500
height: 1500
GridView {
id: root
width: 1500
height: 1500
cellWidth: 200; cellHeight: 200
visible: true
model: DelegateModel {
model: ListModel {
ListElement {
color: "blue"
}
ListElement {
color: "white"
}
ListElement {
color: "red"
}
ListElement {
color: "green"
}
ListElement {
color: "orange"
}
ListElement {
color: "yellow"
}
ListElement {
color: "grey"
}
}
delegate: MouseArea {
objectName: "mousearea"
implicitHeight: parent.height
implicitWidth: parent.width
Rectangle {
anchors.fill: parent
color: model.color
}
drag{
target: parent
}
}
}
}
}
I am trying to create a "menu" in QML with custom data in each option
For requirements of my application, I need to show it loading the QML file dynamically (Qt.createComponent). What I need is to show some fixed options in the bottom part, and when clicked the top one, another options appear below this top option, which keeps in the top
A simple example. I have this menu:
Option 4
Option 2
Option 1
And when clicked in Option 4, the menu changes to
Option 4
Option 3
Option 2
Option 1
So Option 4 is moved upwards and Option 3 appears.
I would like to have a 'shadow' around all my menu (I added a DropShadow component for that purpose).
I have this simple test code, where I have a main Rectangle (to be surrounded by the shadow), and 2 Rectangles inside.
Rect1 for the fixed part (Option 1, Option 2), and Rect2 for the 'movable' part (Option 3, Option 4).
Rect2 is behind Rect1 (z: -1), and located to have only Option 4 visible, above Option 2. When clicked Option 4, Rect2 is moved upwards and all options are visible.
To achieve that, I have to update Rect2 visible height, and main window position (y value), since main window height depends on this Rect2 visible height.
I have it working, but it flicks a lot since 2 variables changes ('fixed panel' is moved upwards and back).
I have also tried with a ParallelAnimation for 2 values, but no success.
Any idea to have this menu with a smooth movement?
Main.qml:
import QtQuick 2.0
Rectangle
{
id: window
property variant win: undefined;
Component.onCompleted:
{
var component = Qt.createComponent("TestMenu.qml");
win = component.createObject(window, {"x": 500, "y": 500});
win.show();
}
}
TestMenu.qml:
import QtQuick 2.0
import QtQuick.Window 2.1
import QtGraphicalEffects 1.0
Window {
id: window
flags: Qt.Tool | Qt.FramelessWindowHint
height: panel.height
color: "transparent"
property int radiusShadow: 20
property int iOptionHeight: 30
Rectangle {
id: panel
anchors { centerIn: parent}
height: menu1.height + menu2.heightVisible + 2*radiusShadow
width: window.width - 2*radiusShadow
color: "transparent"
Rectangle {
id: menu1
anchors { bottom: parent.bottom; bottomMargin: radiusShadow }
width: parent.width
height: column1.children.length * iOptionHeight
Column {
id: column1
anchors.fill: parent
Rectangle {
color: "red";
Text { text: qsTr("option 2") }
height: iOptionHeight; width: parent.width
}
Rectangle {
color: "green";
Text { text: qsTr("option 1") }
height: iOptionHeight; width: parent.width
}
}
}
Rectangle {
id: menu2
property int heightVisible: iOptionHeight
anchors { top: parent.top; topMargin: radiusShadow; left: menu1.left }
width: parent.width
height: column2.children.length * iOptionHeight
z: -1
Column {
id: column2
anchors.fill: parent
Rectangle {
id: blue
property bool bOpen: false
color: "blue";
height: iOptionHeight; width: parent.width
Text { text: qsTr("option 4") }
MouseArea {
anchors.fill: parent
onClicked: {
blue.bOpen = !blue.bOpen;
panel.showHideMenu2(blue.bOpen);
}
}
}
Rectangle {
color: "pink";
Text { text: qsTr("option 3") }
height: iOptionHeight; width: parent.width
}
}
}
function showHideMenu2(bShow)
{
if (bShow)
{
window.y -= iOptionHeight
menu2.heightVisible += iOptionHeight;
}
else
{
window.y += iOptionHeight
menu2.heightVisible -= iOptionHeight;
}
}
}
DropShadow {
id: dropShadow
visible: true
anchors.fill: panel
radius: radiusShadow
samples: 24
color: "#40000000"
source: panel
}
}
As a quick answer for your question, you can get what you want using Behavior animation for a property change.
Here, Behavior animation will be used on y (position) change of your window, and for height change of respective rectangles.
Here is the patch for your code I recommend you to apply to see smooth movement:
## -10,6 +10,9 ##
property int radiusShadow: 20
property int iOptionHeight: 30
+ property int animationDuration: 500 // ms
+
+ Behavior on y { NumberAnimation { duration: window.animationDuration } }
Rectangle {
id: panel
## -18,6 +21,7 ##
height: menu1.height + menu2.heightVisible + 2*radiusShadow
width: window.width - 2*radiusShadow
color: "transparent"
+ Behavior on height { NumberAnimation { duration: window.animationDuration } }
Rectangle {
id: menu1
## -25,6 +29,7 ##
anchors { bottom: parent.bottom; bottomMargin: radiusShadow }
width: parent.width
height: column1.children.length * iOptionHeight
+ Behavior on height { NumberAnimation { duration: window.animationDuration } }
Column {
id: column1
## -52,6 +57,8 ##
width: parent.width
height: column2.children.length * iOptionHeight
+ Behavior on height { NumberAnimation { duration: window.animationDuration } }
+
z: -1
Column {
## -64,6 +71,7 ##
color: "blue";
height: iOptionHeight; width: parent.width
Text { text: qsTr("option 4") }
+ Behavior on height { NumberAnimation { duration: window.animationDuration } }
MouseArea {
anchors.fill: parent
## -77,6 +85,7 ##
color: "pink";
Text { text: qsTr("option 3") }
height: iOptionHeight; width: parent.width
+ Behavior on height { NumberAnimation { duration: window.animationDuration } }
}
}
}
## -105,4 +114,4 ##
color: "#40000000"
source: panel
}
-}+}
I have tried with a model and a ListView (code is simpler now), but I don't know where and how insert an 'Animation' or a 'Behaviour' to achieve my target, if it is possible to do it (I have tried several options with no success...)
The expected effect is that the 1st rectangle moves up when the 2nd appears, so the bottom one keeps in its position (at bottom). But the default behaviour when I add an element to the model is that the list increased the height downwards
Maybe anyone could help...
My code:
import QtQuick 2.0
import QtQuick.Controls 1.4
Rectangle {
id: rootItem
width: 400
height: list.height
ListModel {
id: modelRects
ListElement { rectColor: "green" }
ListElement { rectColor: "orange" }
}
ListView {
id: list
height: modelRects.count * 30
model: modelRects
delegate: Rectangle {
id: delegate
height: 30
width: rootItem.width
color: rectColor
MouseArea {
anchors.fill: parent
onClicked: onRectClicked(index);
}
}
}
function onRectClicked(index)
{
if (index == 0)
{
if (modelRects.count == 2)
modelRects.insert(1, {"idRect": 2, "rectColor": "red"});
else
modelRects.remove(1, 1);
}
}
}
The problem is simple: window doesn't rendering and refresh, until the program is finished. It just doesn't show anything.
And I want to see the window even if the long cycle is not finished yet.
I will be very grateful for any help!
#include <QtGui>
#include <QtQml>
int main(int _nArgCount, char * _pArgValues[]) {
QApplication app(_nArgCount, _pArgValues);
//QMLblock
QString strQmlPath = "../main.qml";
QQmlApplicationEngine engine;
QQmlComponent pComponent(&engine, strQmlPath);
if( pComponent.status()==QQmlComponent::Error )
{ qDebug()<<"Error:"<<pComponent.errorString();
return app.exec();
}
QObject * pQmlObject = pComponent.create();
QObject * pWindow = pQmlObject->findChild<QObject*>("initStateGui");
QObject * pWindowNext = pQmlObject->findChild<QObject*>("searchRemovableGui");
pWindow->setProperty("visible","false");
pWindowNext->setProperty("visible","true");
QObject * pList = pQmlObject->findChild<QObject*>("devicesList");
QStringList s;
QString str;
s.append("3");
pList->setProperty("model",s);
for (int i=0; i<5; i++){
s.append(str.number(i));
pList->setProperty("model",s);
}
return app.exec();
}
And my QML (I don't think it's needed, but anyway):
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Window 2.2
QtObject {
property real defaultSpacing: 10
property SystemPalette palette: SystemPalette { }
property var controlWindow: Window {
width: 500
height: 500
color: palette.window
title: "Updater"
visible: true
//init state
Column {
id: initStateGui
objectName: "initStateGui"
anchors.fill: parent
anchors.margins: defaultSpacing
spacing: defaultSpacing
property real cellWidth: initStateGui.width / 3 - spacing
visible: true
Text { text: "Init state" }
Grid {
id: grid
columns: 3
spacing: defaultSpacing
width: parent.width
Button {
id: showButton
width: initStateGui.cellWidth
text: "Cancel"
onClicked: Qt.quit()
}
Button {
id: initStateContinue
objectName: "initStateContinue"
width: initStateGui.cellWidth
text: "Continue"
signal sigInitStateContinue()
onClicked: initStateContinue.sigInitStateContinue()
}
}
Text {
id: textLabel
text: "Welcome to the updater!"
}
Rectangle {
id: horizontalRule
color: "black"
width: parent.width
height: 1
}
}
//updater update state
Column {
id: updaterUpdateGui
objectName: "updaterUpdateGui"
anchors.fill: parent
anchors.margins: defaultSpacing
spacing: defaultSpacing
visible: false
property real cellWidth: initStateGui.width / 3 - spacing
Text { text: "UpdaterUpdate State" }
Grid {
id: grid1
columns: 3
spacing: defaultSpacing
width: parent.width
Button {
id: showButton1
width: initStateGui.cellWidth
text: "Cancel"
onClicked: Qt.quit()
}
Button {
id: updaterUpdateContinue
objectName: "updaterUpdateContinue"
width: initStateGui.cellWidth
text: "Continue"
signal sigUpdaterUpdateContinue()
onClicked: updaterUpdateContinue.sigUpdaterUpdateContinue()
}
}
Text {
text: "Update is started!"
}
Rectangle {
id: horizontalRule1
color: "black"
width: parent.width
height: 1
}
}
//removable Search gui
Column {
id:searchRemovableGui
objectName: "searchRemovableGui"
anchors.fill: parent
anchors.margins: defaultSpacing
spacing: defaultSpacing
visible: false
property real cellWidth: initStateGui.width / 3 - spacing
Text { text: "Removable search State" }
Grid {
id: grid2
columns: 3
spacing: defaultSpacing
width: parent.width
Button {
id: showButton2
width: initStateGui.cellWidth
text: "Cancel"
onClicked: Qt.quit()
}
}
Text {
text: "Searching for removable, please wait...!"
}
ListView {
id:devicesList
objectName:"devicesList"
width: 100; height: 500
model: myModel
delegate: Rectangle {
height: 15
width: 100
Text { text: modelData }
}
}
}
}
}
Addition: i don't need threads, i need to see the freezed window with the caption.
I see it if i add the button, and begin cycle after the button is pressed.
Without the button the window doesn't rendering, and i can't find how to do it.
It's impossible to realize in one thread.
Only moving long process to another thread allows to render GUI.
Considering the documentation of GridLayout, here is what I have tried:
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
Window
{
visible: true
MainForm
{
GridLayout {
id: gridLayout
columns: 3
height: 100
width: 100
property int oneRow: 0
property int oneCol: 0
Rectangle { id: one; Layout.row :gridLayout.oneRow; Layout.column: gridLayout.oneCol;
height: 50; width: 50; color: "brown"}
Rectangle { height: 50; width: 50; color: "red" }
Rectangle { height: 50; width: 50; color: "blue"}
Rectangle { height: 50; width: 50; color: "green"}
Rectangle { height: 50; width: 50; color: "yellow"}
}
Component.onCompleted:
{
gridLayout.oneRow = 2
gridLayout.oneCol = 2
}
}
}
If I comment out this code from Component.onCompleted,
gridLayout.oneRow = 2
gridLayout.oneCol = 2
I get:
Whereas I want that brown square to "move to" the second row's last column.
So, I wrote:
gridLayout.oneRow = 1
gridLayout.oneCol = 2
in Component.onCompleted.
but then, I got the following:
which is NOT what I wanted.
Please help.
If you wish to change the cell number of some item in the GridLayout, then you need to assign the initial row number and column number to all the elements _yourself_, and then change the position of the desired item dynamically as shown below:
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
Window
{
visible: true
MainForm
{
GridLayout {
id: gridLayout
height: 100
width: 100
property int oneRow: 0
property int oneCol: 0
Rectangle { id: one;
Layout.row :gridLayout.oneRow; Layout.column: gridLayout.oneCol;
height: 50; width: 50; color: "brown"}
property int twoRow: 0
property int twoCol: 1
Rectangle { id: two;
Layout.row :gridLayout.twoRow; Layout.column: gridLayout.twoCol;
height: 50; width: 50; color: "red" }
property int threeRow: 0
property int threeCol: 2
Rectangle { id: three;
Layout.row :gridLayout.threeRow; Layout.column: gridLayout.threeCol;
height: 50; width: 50; color: "blue"}
property int fourRow: 1
property int fourCol: 0
Rectangle { id: four;
Layout.row :gridLayout.fourRow; Layout.column: gridLayout.fourCol;
height: 50; width: 50; color: "green"}
property int fiveRow: 1
property int fiveCol: 1
Rectangle { id: five;
Layout.row :gridLayout.fiveRow; Layout.column: gridLayout.fiveCol;
height: 50; width: 50; color: "yellow"}
}
Component.onCompleted:
{
gridLayout.oneRow = 1
gridLayout.oneCol = 2
}
}
}
Now, as you can see the following code in Component.onCompleted moves the brown rectangle to the 2nd row's 3rd column.
Component.onCompleted:
{
gridLayout.oneRow = 1
gridLayout.oneCol = 2
}