What is the difference between onCheckedChanged and onCheckStateChanged? Both yield the same result when I check/uncheck the box.
import QtQuick 2.12
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3
Page {
id : somepageid
CheckBox {
checked: true
text: qsTr("Check Me")
indicator.width: 15
indicator.height: 15
onCheckedChanged: {
console.log(checked)
}
onCheckStateChanged: {
console.log(checked)
}
}
}
A CheckBox can have 3 or 2 states depending on whether the tristate property is true or not, respectively.
Unchecked,
PartiallyChecked, and
Checked
So onCheckedChanged only fires if it goes to Checked or Unchecked state, for example it does not fire if it goes from Unchecked to PartiallyChecked state, unlike onCheckStateChanged which is fired in all cases.
Related
I am writing a small application that is working as follows:
1) I launch the application and I select a robot to which I will connect. See print screen below of the small app:
2) That will lead me to another page where I can actually choose the robot to connect to as shown in the print screen below:
3) Finally after selecting the robot the application brings me back to the initial screen that will show me an additional Button showing the chosen robot.
The problem: I have is that after I choose the robot and I am back to the initial screen and I push the button the color of the button should turn into a (for example) green color and changing the text into (for example) Connecting...
The code I am using is the following for which I am only putting the related part:
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls.Styles 1.4
Page {
property int dialogId: -1
signal selectDialog()
ColumnLayout {
anchors.fill: parent
spacing: 5
Button {
id: button1
text: "Select Robot"
onClicked: selectDialog()
Layout.fillWidth: true
font.pointSize: 20
}
Button {
id: dialogA
text: "FreddieMercury: Connect";
visible: dialogId === 1
Layout.fillWidth: true
font.pointSize: 20
function buttonClick()
{
console.log("Button "+ dialogA.text +" is clicked!")
}
Rectangle {
id: button
color: "red"
width: 96; height: 24; anchors.centerIn: parent
MouseArea {
id: region
anchors.fill: parent;
onClicked: console.log("clicked()")
onPressed: dialogA.color = "green"
onReleased: dialogA.color = "red"
}
Text {
id: st_text
anchors.centerIn: parent
text: "Connecting..."
font.bold: true
font.pointSize: 20
color: "green"
}
}
}
// Other Buttons
}
}
What I tried so far
I went through this source and also this post which I followed. As you can see from the point 3) I am close to the good functioning but there is clearly something I am not doing right.
Also this was useful and in fact I used the MouseArea option exactly from that post.
However I still don't see the whole color extended into the button.
Finally the text changed after the click event happened I included it in the Button as shown and thought that the property text: "Connecting..." was enough to overwrite the existing text but without success.
Please advise on what I am missing that is keeping me from a full working example.
I think the base issue is that you're trying to use examples for QtQuick Controls 1 with QtQuick Controls 2. They're completely different animals and you cannot style the v2 controls using QtQuick.Controls.Styles.
For customizing Controls 2 styles, like Button, see here. I also find it useful to look at the source code for the included controls (they're in your Qt library install folder inside /qml/QtQuick/Controls2/ directory). Though personally I find needing to re-create a whole new Button (or whatever) just to change a color or font is a bit much, especially if I want it to work across all the included QtQuick Controls2 Styles.
An alternative is to "hack" the properties of the built-in Control styles. This certainly has some drawbacks like if you want to be able to reset the control style back to default bindings, you'd have to save the original bindings and re-create them to reset the style. OTOH it beats creating customized controls for each style. YMMV.
Anyway here's an example of what i think you're looking for. This is based on our previous exercise with the buttons. :) Specifically, I just modified the Page1.qml code and the other 2 files are exactly the same as before. In this page I added buttonClick() handler and the Button::onClicked calls to trigger it from each button (and the button texts of course :).
Page1.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.impl 2.12 // for IconLabel
import QtQuick.Layouts 1.12
Page {
property int dialogId: -1;
signal selectDialog()
function buttonClick(button)
{
button.text = qsTr("Connecting to %1...").arg(button.text);
button.enabled = false; // prevent repeat clicks
// If Button has a background Rectangle object then we can set properties on it.
// note: `instanceof` was added in Qt 5.10
if (button.background && button.background instanceof Rectangle) {
button.background.color = "red"; // override style color
button.background.gradient = null; // some styles use a gradient
button.background.visible = true; // some styles may hide it in some situations
}
// Similar with the label element, IconLabel is used by all included QML styles.
if (button.contentItem && button.contentItem instanceof IconLabel) {
button.contentItem.color = "blue"; // override style color
button.contentItem.font.bold = true;
button.contentItem.font.pointSize = 20;
}
}
ColumnLayout {
anchors.fill: parent
spacing: 5
Button {
id: button1
text: "Select"
onClicked: selectDialog()
Layout.fillWidth: true
}
// These buttons should appear only after the user selects the choices on `Page2`
Button {
id: dialogA
text: "Freddie Mercury"
visible: dialogId === 1
Layout.fillWidth: true
onClicked: buttonClick(this)
}
Button {
id: dialogB
text: "David Gilmour"
visible: dialogId === 2
Layout.fillWidth: true
onClicked: buttonClick(this)
}
Button {
id: dialogC
text: "Mick Jagger"
visible: dialogId === 3
Layout.fillWidth: true
onClicked: buttonClick(this)
}
}
}
If you had a customized Button (like in the Qt docs example) then you could still do basically the same thing in buttonClick() but probably w/out worrying about the if (button.background ...) stuff (since you'd be sure your button has valid background/contentItem Items).
A better implementation of a "default" (Style-specific) Button but with custom colors/text properties would involve a subclass which uses Binding and/or Connections QML elements to control the properties and be able to reset them back to the current QtQuick Style defaults.
I have a Qt Quick Controls 2 Action with a shortcut:
Action {
id: myAction
shortcut: "Ctrl+D"
}
How can I get a platform native representation of the shortcut?
Here is what I already tried:
Using the shortcut right away like
ToolTip.text: myAction.shortcut
However, this returns the shortcut as defined (for example, "Ctrl+D") and not a platform native representation (for example, "⌘D"). It also returns incorrect results in case a StandardKey is used because it gives the integer value of the StandardKey and not the corresponding key combination.
Using a nativeText property like
ToolTip.text: myAction.shortcut.nativeText
But such a property doesn't exist.
There seems to be no straight forward way to get this.
A workaround is:
Create a disabled Shortcut item
This will give us the platform native representation via its nativeText property.
Derive from Action and add a custom property to hold the shortcut
This is necessary because the shortcut property of the Action will always return a string which will be interpreted incorrectly by the Shortcut item when using a StandardKey (the Shortcut item will interpret the integer value as the shortcut so you get a "3" instead of "Ctrl+O").
Bind the custom property to the Action shortcut and to the Shortcut sequence
So in code:
CustomAction.qml
import QtQuick 2.7
import QtQuick.Controls 2.4
Action {
/* Custom property */
property var keySequence
shortcut: keySequence
}
ToolTipButton.qml
import QtQuick 2.7
import QtQuick.Controls 2.4
Button {
/* Disabled Shortcut */
Shortcut {
id: dummyShortcut
enabled: false
sequence: action.keySequence
}
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.text: dummyShortcut.nativeText
}
Used like this:
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.4
ApplicationWindow {
visible: true
CustomAction {
id: myAction
keySequence: StandardKey.Open
}
ToolTipButton {
id: myButton
action: myAction
text: "Trigger my action"
}
}
I'm unable to assign ExclusiveGroup to my checkable buttons.
ExclusiveGroup {
id: group
onCurrentChanged: {
if(current != null) {
console.info("button checked...no!")
current = null
//current.checked = false <--- also this
}
}
}
Column {
width: parent.width
spacing: 0
Button {
id: btnScan
flat: true
text: qsTr("But1")
width: parent.width
checkable: true
exclusiveGroup: group
}
Button {
id: btnWhiteList
flat: true
text: qsTr("But2")
width: parent.width
checkable: true
exclusiveGroup: group
}
}
The documentation states clearly that Button does have exclusiveGroup property http://doc.qt.io/qt-5/qml-qtquick-controls-button.html#exclusiveGroup-prop. However, when I run the example, I get this error:
qrc:/main.qml:48 Cannot assign to non-existent property "exclusiveGroup"
Hovering mouse over "exclusiveGroup" makes a tooltip show up saying: "Invalid property name exclusiveGroup".
I have Qt 5.9.1 installed. Here's my import statements:
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.2
What am I doing wrong?
Thanks
The reason for your problem is this:
import QtQuick.Controls 1.4
import QtQuick.Controls 2.0
You have a Button in both, but they have a different API.
So at first you import the Button from QtQuick.Controls 1.4. Then you import the Button from QtQuick.Controls 2.0. As QML doesn't know, which one you want to use, it will take the one, you imported the last. If you want to be more specific, on which Button you want to use, you can use named imports
import QtQuick.Controls 1.4 as OldCtrl
import QtQuick.Controls 2.0 as NewCtrl
Then you can use Buttons from both versions as you like:
OldCtrl.Button { // from the QtQuick.Controls 1.4 }
NewCtrl.Button { // from the QtQuick.Controls 2.0 }
The documentation you quote is for QtQuick.Controls 1.x, and from there is the imported ExclusiveGroup. So you are trying to mix things from two libraries, that wont work together.
See ButtonGroup for a similar solution for QtQuick.Controls 2.x
For more on the differences and usecases of the both sets of controls read:
http://blog.qt.io/blog/2016/06/10/qt-quick-controls-2-0-a-new-beginning/
https://doc.qt.io/qt-5/qtquickcontrols2-differences.html
I have a situation where VolumeControl.qml should receive all the keys received by pages derived from Page1 (like Page2) and pages derived from Page2 (like Page3).
When I tried to forward the keys from all the pages to the VolumeControl (through id volumeControl), I am able to forward only from Page1, but getting reference error in Page2 and Page3 when trying to acess volume control id.
Why I am getting reference error in Page2 and Page3? How to resolve this to forward the keys from all individual pages to volume control, before the keys are consumed (event.accepted) by the pages?
Also Why I am not getting reference error in Page1?
VolumeControl.qml
import QtQuick 2.4
FocusScope
{
id: volumeControl
focus: true
Keys.onPressed:
{
console.error("VOLUME CTRL Key received" + event.key);
}
}
Page1.qml
import QtQuick 2.4
Item
{
id: p1
Keys.forwardTo: [volumeCtrl]
VolumeControl
{
id: volumeCtrl
visible: true
z: 60
}
}
Page2.qml
import QtQuick 2.4
Page1
{
id: p2
Keys.forwardTo: [volumeCtrl]
Keys.onDigit0Pressed: handleDigit("0")
Keys.onDigit1Pressed: handleDigit("1")
Keys.onDigit2Pressed: handleDigit("2")
Keys.onDigit3Pressed: handleDigit("3")
Keys.onDigit4Pressed: handleDigit("4")
Keys.onDigit5Pressed: handleDigit("5")
Keys.onDigit6Pressed: handleDigit("6")
Keys.onDigit7Pressed: handleDigit("7")
Keys.onDigit8Pressed: handleDigit("8")
Keys.onDigit9Pressed: handleDigit("9")
function handleDigit(digit)
{
}
}
Page3.qml
import QtQuick 2.4
Page2
{
id: p3
Rectangle
{
width: 360
height: 360
focus:true
Keys.forwardTo: [volumeCtrl]
Keys.onPressed:
{
console.error("page3 Key received" + event.key);
}
}
}
If I have correctly understood your question, you should add alias property for Page1 item. You getting reference error in Page2 and Page3 because volumeCtrl property or reference to it doesn't exist in these items directly.
Add to your root item in Page1.qml:
property alias volumeCtrlAlias1: volumeCtrl
Now Page1 items will have a reference property to your VolumeControl item.
Then in your Page2.qml change this:
Keys.forwardTo: [volumeCtrl]
to:
Keys.forwardTo: [volumeCtrlAlias1]
And finally in your Page3.qml change the same string
to
Keys.forwardTo: [p3.volumeCtrlAlias1]
Information about aliases from Qt Documentation here.
I dynamically add tabs to TabView and pass tab's item to c++ for futher processing. The problem is that method tabview.getTab(tabview.getTab(tabview.count-1).item) returns null for the which index is >0. Here is code:
//main.qml
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
signal tabAdded(variant c)
ColumnLayout{
anchors.fill: parent
TabView{
visible: true
id:tabview
Layout.fillHeight: true
Layout.fillWidth: true
}
Button{
text: "add tab"
onClicked:{
var c = Qt.createComponent("Tab.qml");
tabview.addTab("tab", c)
// tabAdded(tabview.getTab(tabview.count-1).item)
console.log(tabview.getTab(tabview.count-1).item)
}
}
}
}
//Tab.qml
import QtQuick 2.0
import QtQuick.Controls 1.1
Item{
signal tabButtonClicked()
anchors.fill: parent
Button{
text: "tabButton"
anchors.centerIn: parent
onClicked: tabButtonClicked()
}
}
I figured out that tabview.getTab(index).item returns apropriate value if tab(index) was activated manually (by clicking with mouse on it). It seems like tab's item is created only when user firstly activate tab. So, how to make item to be created immediately after tab creation?
Every tab in TableView is represented by a Tab component that inherits from Loader component. If you want force the Tab to load its contents, just set active property to true. This property controls when the component must be loaded. So now, your button code looks like this:
Button{
text: "add tab"
onClicked:{
var c = Qt.createComponent("Tab.qml");
tabview.addTab("tab", c);
var last = tabview.count-1;
tabview.getTab(last).active = true; // Now the content will be loaded
console.log(tabview.getTab(last).item);
}
I hope this help you.