I'd like to implement a table view, using QtQuick, allowing multiple selection at cell level, emulating the behaviour of old style QTableView with QAbstractItemView::SelectItems and QAbstractItemView::ExtendedSelection flags enabled.
Which of the QtQuick components may I use?
TableViewonly allow to select rows by default, but you can override the selection behavior by customizing its cell delegate (itemDelegate).
First you'll have to disable the default selection behavior with :
selectionMode: SelectionMode.NoSelection
Then in the itemDelegate you can do something like that :
itemDelegate: Item {
property bool isSelected: false
// When user clicks on a cell, turn the isSelected flag on
MouseArea {
anchors.fill: parent
onClicked: isSelected = !isSelected
}
Text {
anchors.verticalCenter: parent.verticalCenter
// If this cell is selected, color the text in blue
color: isSelected ? "blue" : "black"
text: styleData.value
}
}
Be careful as the signals emitted by your TableView will not work as your cells are accepting mouse events. But of course you can implement them easily if you need them.
Related
I have one button. I want to change the states of button e.g:
Default image is black.
onEntered i want image as blue, onExited i want image as black(equal to default state), and onReleased i want image as blue(equal to onEntered state).
Note:
onRelease should be active inside the button and outside the button onRelease shouldn't work.
How this can be achieved?
Mouse area looks like this:
MouseArea
{
anchors.fill: firstImage(parent)
onEntered:
{
firstImage.source = "blue.img"
}
onExited:
{
firstImage.source = "black.img"
}
onReleased:
{
firstImage.source = "blue.img"
}
}
Problem i am facing is:
onRelease is active outside the button.
I want onRelease to be active when press is released inside the button.
You can leverage the fact that you can give every object in qml an extra custom property.
I came up with the following, which seems to be what you ask, however, I see a flaw, because when you are 'entered' and press, the button will go to entered state, so there is not difference in the 'released' state, and after leaving the MouseArea it will again go to 'exited' state.
Note, I did not copy the firstImage.source stuff, but you can easily tailor this example to your situation
import QtQuick.Controls 2.4
Button {
hoverEnabled: true
property bool touched : false
onHoveredChanged: touched = hovered
onReleased: touched = true
text: touched ? "touched" : "not touched"
}
The hoverEnabled needs to be set
I have made list whose delegate is RowLayout consist of Button. The list takes data from cpp.
My problem is the button variable width. The button side changed based on data. I want to keep fix button side and wrap text
To give your Button a fixed width, just set the property with the same name to a fixed value.
The Button has a contentItem that is a Text. You can change the wrapMode there to Text.WordWrap
As the contentItem is of type Item you can't set the wrapMode like this:
Button {
width: 100
text: 'Very very long button description.'
contentItem.wrapMode: Text.WordWrap // Won't work
}
Instead you might use Component.onCompleted like this:
Button {
width: 100
text: 'Very very long button description.'
Component.onCompleted: contentItem.wrapMode = Text.WordWrap
}
I can show current selection QML ListView but similar thing doesn't work in TreeView.
Part of the problem is for TreeView it doesn't recognize index which is passed to delegate in case of ListView. I tried styleData.indexbut that doesn't work either.
rowDelegate: Item {
id: row_delegate
height: 40
Rectangle {
id: rectid
anchors.fill: parent
MouseArea {
id: mouse_area
anchors.fill: parent
onClicked: {
console.log("Row clicked " + rectid.styleData.index)
}
}
}
}
The output is:
qml: Row clicked undefined
As stated by the documentation, you have a set of properties within the namespace styleData that can be used for almost the same purposes from within a delegate.
As an example, you can set the text property of a label that is part of your delegate as it follows:
text: styleData.value
Where styleData.value is (documentation excerpt):
the value or text for this item
Similarly, you have:
styleData.pressed - true when the item is pressed
styleData.index - the QModelIndex of the current item in the model
styleData.hasChildren - true if the model index of the current item has or can have children
And so on... Please, refer to the documentation for the full list.
Be aware also of the note at the end of the documentation:
Note: For performance reasons, created delegates can be recycled across multiple table rows. This implies that when you make use of implicit properties such as styleData.row or model, these values can change after the delegate has been constructed. This means that you should not assume that content is fixed whenComponent.onCompleted is called, but instead rely on bindings to such properties.
By default, Flickable scrolls on mouse wheel event: horizontally if Shift modifier is pressed, and vertically if no modifier is active. I'd like to override this behaviour to make it zoom in/out.
I tried to use MouseArea as a child of Flickable. Defining desired behaviour inside onWheel handler I get what I want, but it breaks flicking feature. Motion of two touch points is recognised as a wheel event on my Mac, what prevents Flickable to steel this event (MouseArea.preventSteeling is false by default). So I get somewhat mixed zooming feature that respects velocity/acceleration behaviour of Flickable.
Add an onWheel handler underneath your MouseArea:
MouseArea
{
onWheel: {
if (wheel.modifiers & Qt.ControlModifier){
if (wheel.angleDelta.y > 0)
{
zoomin()
}
else
{
zoomout()
}
}
else{
wheel.accepted=false
}
}
}
I want to display the recently entered text to the label. Here's the code for the qml:
Container {
horizontalAlignment: HorizontalAlignment.Center
verticalAlignment: VerticalAlignment.Top
topPadding: 100
leftPadding: 50
rightPadding: leftPadding
/*TextArea {
id: taComment
preferredHeight: 270
editable: quoteBubble.editMode
enabled: enableSave
input.flags: TextInputFlag.SpellCheckOff
}*/
Label {
verticalAlignment: VerticalAlignment.Top
horizontalAlignment: HorizontalAlignment.Center
text: cppObj.desc
}
}
Container {
horizontalAlignment: HorizontalAlignment.Center
verticalAlignment: VerticalAlignment.Bottom
leftPadding: 50
rightPadding: leftPadding
bottomPadding: 40
TextField {
id: tfComment
hintText: qsTr("add comment")
inputMode: TextFieldInputMode.Text
input {
submitKey: SubmitKey.Submit
onSubmitted: {
cppObj.onCommentSubmitClicked(tfComment.text, "");
}
}
}
}
}
So when the user enters a phrase from the first textfield, I want that phrase to display in the label below it. More like a text messaging. How do I do that? And after displaying the entered text from textfield to label I want to save the label's text, so when I enter new comment it'll be saved to other label
Add id to Label like following
Label {
id: label
....
}
Then on TextField on submit handler, you can get text from textField and set it to label, like below
onSubmitted: {
label.text = tfComment.text;
}
This is all related to Qt signals/slots and properties mechanism. Your items, TextField and Label, have properties. A specific property they share in common is text (note that the name is the same, but what really matters is the type - two properties with different names could be binded too). You can bind a property to another one:
Label {
text: myTextField.text
}
TextField {
id: myTextField
}
Now, whenever the TextField's text changes, the Label's one is updated accordingly. Note that the TextField's text property is updated only when it looses its focus or when it's submitted.
This is the simple way to do what you need. There's a more generic way to do it. Qt's property system is based on signals/slots mechanism. A signal is something which a QObject can send, to notify other QObject children. Slots are a specific kind of methods, which can be connected to signals. Then, if a signal A is connected to a slot B, whenever the signal A will be emitted, the slot B will be called.
The TextField object has an input child, which has an submitted signal. As you can guess, this signal is emitted whenever the user submits the TextField. Eh, that's every time you want to change your Label's text property! Let's do this in a slot:
Label {
id: myLabel
}
TextField {
id: myTextField
input {
onSubmitted: {
myLabel.text = myTextField.text;
}
}
}
Here, the onSubmitted function is a slot, which will be called automatically by Qt whenever the submit signal is emitted. You can of course do whatever you want in this slot: update properties, on this object or other ones, invoke a C++ method, … you're free.
You'll find a complete reference about signals and slots here, and about properties here (couldn't find this one on BlackBerry's documentation, but it's exactly what's used by BlackBerry).
Give your label an id (for example id : myLabel), then in your onSubmitted slot assign the text of the TextField to that label like this:
onSubmit :{
myLabel.text = tfComment.text
}
First you must set objectNames in the relevant places in the QML.
...
Label {
objectName: "label"
...
}
...
TextField {
objectName: "textField"
...
}
Of course I'm not suggesting that these are good names.
Once this is done, from where you use the QML in C++ i.e.:
QmlDocument *qml = QmlDocument::create("asset///qml/YourQml.qml");
Container *container = qml->createRootObject<bb::cascades::Container>();
You can then find the root object's (just assumed container here) children and manipulate them by name.
TextField *textField = container->findChild<TextField*>("textField");
Label *label = container->findChild<Label*>("label");
...
label->setText(textField->text()); //take the text from textField and display in label