I’m using Qt Creator's Qt Quick and as suggested in the tutorial I made different .qml for every button.
I want when the button is clicked to make a window pop- up. What should I write after
onClicked:
in the mouseArea.
Also how to make a second window (the pop- up one), what should I add to the project so I can design it like the main one?
I read that I have to make a class that inherits with QWidget but I need a bit more information.
A short example would be great.
as suggested in the tutorial I made different .qml for every button
Surely you mean "for every button type"!?
To launch a second window:
// Main.qml
Window {
id: win
width: 640
height: 480
Button {
text: qsTr( "Open" )
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
onClicked: {
var factory = Qt.createComponent( "Popup.qml" );
factory.createObject( win );
}
}
}
// Popup.qml
Window {
height: 240
width: 320
title: qsTr( "Popup" )
visible: true
Text {
text: qsTr( "Hello" )
anchors.centerIn: parent
}
}
I read that I have to make a class that inherits with QWidget
Do not mix QML and the Qt Widgets module unless you are extending/converting a legacy system, QML has been designed to replace Qt Widgets (at some point).
Related
Guys!
I'm a new user of qt and I faced a problem with qml. This issue has already been discussed in this article, but for python. I write in C ++/Qt 6.1.1, QtCreator 4.15.1 for open source. Help me please.
Here is the crux of the problem: qml does not work, Application output writes the following message: "Failed to create vertex shader: Error 0x80070057: ???????? ????? ???????. Failed to build graphics pipeline state ".
The Qt documentation says that this is because of "Scene Graph Adaptations". Here is the link: https://doc-snapshots.qt.io/qt6-dev/qtquick-visualcanvas-adaptations.html.
I tried to use this method from the article in main:
QQuickWindow :: setSceneGraphBackend ("QT_QUICK_BACKEND");
For it, you also need to include the library QQuickWindow.
However, Qt gives the following error: Could not create scene graph context for backend 'QT_QUICK_BACKEND' - check that plugins are installed correctly in C: /Qt/6.1.1/mingw81_64/plugins
Here I no longer understand what to do ...
I provide the code for clarity. Since in qml it is enough to create a window and include the Rectangle {} in it.
I took the code from the example (tried 3 QtQuick examples).
Here is the main function code:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
int main(int argc, char *argv[])
{
QQuickWindow::setSceneGraphBackend("QT_QUICK_BACKEND");
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl("qrc:/sidepanel.qml"));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
QML code:
import QtQuick
import QtQuick.Controls
ApplicationWindow {
id: window
width: 360
height: 520
visible: true
title: qsTr("Side Panel")
//! [orientation]
readonly property bool inPortrait: window.width < window.height
//! [orientation]
ToolBar {
id: overlayHeader
z: 1
width: parent.width
parent: Overlay.overlay
Label {
id: label
anchors.centerIn: parent
text: "Qt Quick Controls"
}
}
Drawer {
id: drawer
y: overlayHeader.height
width: window.width / 2
height: window.height - overlayHeader.height
modal: inPortrait
interactive: inPortrait
position: inPortrait ? 0 : 1
visible: !inPortrait
ListView {
id: listView
anchors.fill: parent
headerPositioning: ListView.OverlayHeader
header: Pane {
id: header
z: 2
width: parent.width
contentHeight: logo.height
Image {
id: logo
width: parent.width
source: "images/qt-logo.png"
fillMode: implicitWidth > width ? Image.PreserveAspectFit : Image.Pad
}
MenuSeparator {
parent: header
width: parent.width
anchors.verticalCenter: parent.bottom
visible: !listView.atYBeginning
}
}
footer: ItemDelegate {
id: footer
text: qsTr("Footer")
width: parent.width
MenuSeparator {
parent: footer
width: parent.width
anchors.verticalCenter: parent.top
}
}
model: 10
delegate: ItemDelegate {
text: qsTr("Title %1").arg(index + 1)
width: listView.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
}
Flickable {
id: flickable
anchors.fill: parent
anchors.topMargin: overlayHeader.height
anchors.leftMargin: !inPortrait ? drawer.width : undefined
topMargin: 20
bottomMargin: 20
contentHeight: column.height
Column {
id: column
spacing: 20
anchors.margins: 20
anchors.left: parent.left
anchors.right: parent.right
Label {
font.pixelSize: 22
width: parent.width
elide: Label.ElideRight
horizontalAlignment: Qt.AlignHCenter
text: qsTr("Side Panel Example")
}
Label {
width: parent.width
wrapMode: Label.WordWrap
text: qsTr("This example demonstrates how Drawer can be used as a non-closable persistent side panel.\n\n" +
"When the application is in portrait mode, the drawer is an interactive side panel that can " +
"be swiped open from the left edge. When the application is in landscape mode, the drawer " +
"and the content are laid out side by side.\n\nThe application is currently in %1 mode.").arg(inPortrait ? qsTr("portrait") : qsTr("landscape"))
}
}
ScrollIndicator.vertical: ScrollIndicator { }
}
}
I have just switched from Qt 5.12 to Qt 6.1.2 and also experiencing the same problem as yours.
I'm on :
Windows x64 (with quite old CPU and so does the graphics)
Qt 6.1.2 , targeting desktop for both MSVC and MingW
In the nutshell , the working solution is to set the Qt Quick rendering to software.
But how to do it?
Nah, you just got to choose one based on your scenario:
Solution 1: Set the rendering to software permanently at OS env level
pros: you don't have to set the env value every time you create the project.
cons: this will less portable and if you move your project to another machine you might to set it again at the OS Env level.
So, this method works best for development purpose only.
How to do it?
Simply set QT_QUICK_BACKEND to software at the system env.
On Windows:
hit Win+R and type control sysdm.cpl,,3
on Environment Variables>System Variables register New... variable named QT_QUICK_BACKEND with value software
Restart Qt creator and rebuild. This should make it work without any code modification.
Solution 2: Set the QT_QUICK_BACKEND value on the fly to software
this just the same as solution 1 , but instead of writing to OS Env we just set it on the fly the flag from the code.
This method can be used either for production or development.
How to do it?
On your main.cpp simply put qputenv("QT_QUICK_BACKEND","software"); right after the main() declaration.
save and rebuild the project
Done
Solution 3: Explicitly set scene graph renderer to software
Well I see your code and that's bit miss. Instead of setting the value to QT_QUICK_BACKEND you should set to software instead.
How to do it?
on your main.cpp do importing QQuickWindow:
#include <QQuickWindow>
next, just after the main() declaration add:
QQuickWindow::setSceneGraphBackend("software");
save and rebuild project
DONE
it should works now , the window no longer show blank canvas, the QtQuick widgets are showing :
If the software renderer is not a solution, for me in the case of QtQuick3D, setting QSG_RHI_PREFER_SOFTWARE_RENDERER=1 or QT_D3D_ADAPTER_INDEX=1 as environment variables solved the issue.
See also Quick3D fails with software render backend.
I am reading the Qt doc to learn the Keyboard Focus in Qt Quick! I run the code which from the document. However, the result is different form the document! The codes are as follows.
main.qml
//Window code that imports MyWidget
Rectangle {
id: window
color: "white"; width: 240; height: 150
Column {
anchors.centerIn: parent; spacing: 15
MyWidget {
focus: true //set this MyWidget to receive the focus
color: "lightblue"
}
MyWidget {
color: "palegreen"
}
}
MyWidget.qml
Rectangle {
id: widget
color: "lightsteelblue"; width: 175; height: 25; radius: 10; antialiasing:
true
Text { id: label; anchors.centerIn: parent}
focus: true
Keys.onPressed: {
if (event.key == Qt.Key_A)
label.text = 'Key A was pressed'
else if (event.key == Qt.Key_B)
label.text = 'Key B was pressed'
else if (event.key == Qt.Key_C)
label.text = 'Key C was pressed'
}
}
The pic1 is the result form doc. And the pic2 is the result of my running which i just copy the code from doc and run it.
pic1
pic2
Is it a bug? Why the result are different?
The doc said:
We want the first MyWidget object to have the focus, so we set its focus property to true. However, by running the code, we can confirm that the second widget receives the focus.
Looking at both MyWidget and window code, the problem is evident - there are three types that set the focus property to true. The two MyWidgets set the focus to true and the window component also sets the focus. Ultimately, only one type can have keyboard focus, and the system has to decide which type receives the focus. When the second MyWidget is created, it receives the focus because it is the last type to set its focus property to true.
My question:
1.Why the result are different?In my result the first widget receives the focus.
2.Also, what is the meaning of"because it is the last type to set its focus property to true"in doc?
The doc you can get from here!
Qt doc
When I run the code I get the same result as you, but it does not matter. The point here is to understand that without FocusScope you have no control on which object receives the focus from the system (you have no guarantee in the order of creation of QML objects).
Did you try to set focus: true on the second MyWidget instead? If you try, the keyboard events will still be received by the first widget, except if you use a FocusScope.
Note that you can also remove focus: true from MyWidget.qml and you won't even need to manually add a FocusScope (it will automatically be managed by the application window).
try run with the following modification:
MyWidget { //the focus is here
color: "palegreen"
}
MyWidget {
focus: true //set this MyWidget to receive the focus
color: "lightblue"
}
MyWidget {
color: "palegreen"
}
I tested many times. The result is the same. Maybe the docs are outdated!
I am developing QT cross flat form application for Ubuntu and Windows. My Question is simple but as bit new to QT, i am not able to figure it out. I have bellow code in QML. I am using QT TextField in my qml. When QML is loaded for first time i want id_username TextField should show cursor by default at initial position (0) which is not happening. When i click same TextField using mouse, cursor is visible at initial position. I am doing focus: true which is not helpful. Next, i added cursorVisible: true with that cursor is visible when qml is loaded, but i am not able to type anything(Input anything) till i click on the TextField.
TextField
{
id: id_username
objectName: "id_username"
placeholderText: qsTr("username")
color: "#000000"
font.pixelSize: 20
cursorPosition: 0
selectByMouse: true
anchors.horizontalCenter: parent.horizontalCenter
focus: true
background: Rectangle
{
anchors.horizontalCenter: parent.horizontalCenter
implicitWidth: 200
border.color: id_username.focus ? "#000000": "#36404e"
border.width: id_username.focus ? 2: 1
radius: id_instruction.height / 4
}
}
Please let me know what i am doing wrong. Is there any onLoad function from where can call forceActiveFocus()
try this in TextField:
onVisibleChanged: if(visible) id_username.forceActiveFocus()
Reference link - http://www.qtcentre.org/threads/62655-How-to-gain-focus-onto-TextEdit-in-QML
I am testing on my desktop and can't seem to get qml to recognize the PressAndHold event.
Button
{
id: btn_draw
style: cgButtonStyle
width: isPortrait() ? Game.getBannerHeight() : Game.getBannerHeight() / 3
height: isPortrait() ? Game.getBannerHeight() : Game.getBannerHeight() / 3
MouseArea
{
onPressAndHold: iPod4.play()
}
// Much more code
Am I missing a signal somewhere or something? Do I need to add anything else in order for QML to recognize the PressAndHold event? Is it possible other code is preventing PressAndHold from working?
You're missing the MouseArea anchors... the mouse area is zero-sized, and so you can't click it...
Simply modify like that:
MouseArea
{
anchors.fill: parent
onPressAndHold: iPod4.play()
}
and it would work.
I want to create a button using Cascades on Black Berry 10 development which has an image as a background and also possibly a text with white color. I found this class button, but it seems to not support setting an image as a background on the button. What can I do? What are the alternate ways?
Maybe I should consider another library than Cascades for creating my UI??? any suggestions?
Container {
id:account
signal buttonClicked()
layout: DockLayout {
}
preferredWidth: 768.0
topMargin: 40.0
bottomMargin: 40.0
ImageButton {
id: addButton
defaultImageSource: "image/button_normal.png"
pressedImageSource: "image/button_press.png"
horizontalAlignment: HorizontalAlignment.Center
onClicked: {
buttonClicked();
}
}
Label {
text: "Add"
verticalAlignment: VerticalAlignment.Center
horizontalAlignment: HorizontalAlignment.Center
textStyle {
base: SystemDefaults.TextStyles.BodyText
fontSize: FontSize.Small
color: Color.create("#ffffff")
}
touchPropagationMode: TouchPropagationMode.None
}
}
You can have a button with both text and image by using the default Button class: cascades_button.html">https://developer.blackberry.com/cascades/reference/bb_cascades_button.html
Having a background image on the button with text over top is not really recommended. A button should be clear and easy to read. See the BlackBerry 10 UI Guidelines here: https://developer.blackberry.com/devzone/files/design/bb10/UI_Guidelines_BlackBerry_10.pdf
If you really want to do it, you can always build a custom component in Cascades that has an image with a label over top.
I've faced the same issue.
At the end, as PBernhardt said, I created a custom Container with an ImageView or a background image, and added a Label inside.
Then, I overrided onTouch to catch the different touch states (event.isDown(), event.isMove(), event.isUp()) and update the button graphics accordingly (text color and background image).
I'm using a Q_INVOKABLE method to bind with my C++ files.