I am having a image which contains numbers in following order :--
0 1 2 3 4 5 6 7 8 9 ... i have to show meter reading .. so now how to create sub image of individual numbers from this image so that i can display each number separately .. means to say i want to extract images of number from this image so that i can display them separately on Meter reading .. please suggest.
Full image size is 108x16 .
I tried using column then using the repeater i replicated the image, but how to change x,y of image inside the repeater so that image inside the repeater is clipped .. so that i extract the numbers from image.. ?
I created column's of the images... using repeater.. but not able to clip the real image.. so that X,Y coordinate changes... and each column contains Digit from the image.
Window {
visible: true
width: 400
height: 300
color: "grey"
Item {
id: container
anchors.centerIn: parent
width: 12
height: 16
clip: true
property int position: 0
Column {
id: image
y: -container.position * 16
Repeater {
model: 10
delegate: Rectangle {
width: 12
height: 16
Image {
anchors.fill: parent
source: "files/REE Demo images/odo_font_orange.png"
}
}
}
}
}
Timer {
interval: 1000
repeat: true
running: true
onTriggered: {
if(container.position == 9)
container.position = 0;
else
container.position ++
}
}
You may want to use Sprite and SpriteSequence. Obviously, you have to set running to true so that you can manually set your desired frame(number) by using jumpTo method.
As your image is not 120 pixels wide, it means that your sprites are not the same size. But I recommend you to choose 12 pixels width frames within your original image. SpriteSequence will resize your sprite to its own size if it has a different size. It means that you have to manually set frameX of each Sprite object to get a good visual appearance.
SpriteSequence {
id: digit
width: 12
height: 16
interpolate: false
goalSprite: ""
running: true
property var sourceImage: 'files/REE Demo images/odo_font_orange.png'
Sprite{
name: "1"
source: digit.sourceImage
frameCount: 1
frameWidth: 12
frameHeight: 16
frameX: 0
frameY: 0
}
Sprite{
name: "2"
source: digit.sourceImage
frameCount: 1
frameWidth: 12
frameHeight: 16
frameX: 12
frameY: 0
}
//other digits with their topleft and width/height
//in original image should be repeated with their own name
function setNumber(n){
digit.jumpTo(n);
}
}
You should place your image inside a container with clip:true and play with x/y of the content item, for example:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 400
height: 300
Item {
id: container
anchors.centerIn: parent
width: 30
height: 30
clip: true
property int position: 0
Column {
id: image
y: -container.position * 30
Repeater {
model: 10
delegate: Rectangle {
width: 30
height: 30
Text {
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: index
font.pixelSize: 20
color: "orange"
}
}
}
}
}
Timer {
interval: 1000
repeat: true
running: true
onTriggered: {
if(container.position == 9)
container.position = 0;
else
container.position ++
}
}
}
here I replace Image with Column item to just illustrate the idea. You maybe want to add some move animation etc.
Updated:
taking you image into account:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 400
height: 300
Item {
id: container
anchors.centerIn: parent
width: 12
height: 16
clip: true
property int position: 1
Image {
id: image
x: -container.position * 12
source: "http://i.stack.imgur.com/jnbEZ.png"
}
}
Timer {
interval: 1000
repeat: true
running: true
onTriggered: {
if(container.position == 9)
container.position = 0;
else
container.position ++
}
}
}
but since your images are not aligned right the result is a bit rough. You need 10 cells with the same size each one.
Related
I have a Component for an sddm theme. At the moment I use the theme dark sugar as the base theme. The component looks like the following:
Item {
id: hexagon
property color color:"yellow"
property int radius: 30
//layer.enabled: true
//layer.samples: 8
Shape {
//... Here some Positioning and other Stuff
ShapePath {
//... Here some Options and Pathlines
}
}
}
This works fine, but as soon as I uncomment both layer settings the component disappears. Does this happen, because I load the component like this:
Pane {
...
Item {
...
MyComponent {
z: 1
}
}
}
Nor the Pane or the Item use layer but most Components in the Item use the z: 1 property.
As iam_peter says, the default width and height properties of any Item are 0, and layer.enabled sets the size of the offscreen texture to the item size. By default, the scene graph doesn't do any clipping: a child item can populate scene graph nodes outside its parent's bounds. But when you confine the children's rendering to a specific offscreen texture, anything that doesn't fit is clipped. Here's a more interactive example to play with this:
import QtQuick
import QtQuick.Controls
Rectangle {
width: 640
height: 480
Column {
CheckBox {
id: cbLE
text: "layer enabled"
}
Row {
spacing: 6
TextField {
id: widthField
text: layerItem.width
onEditingFinished: layerItem.width = text
}
Label {
text: "x"
anchors.verticalCenter: parent.verticalCenter
}
TextField {
id: heightField
text: layerItem.height
onEditingFinished: layerItem.height = text
}
}
}
Rectangle {
id: layerItem
x: 100; y: 100
border.color: "black"; border.width: 2
layer.enabled: cbLE.checked
Rectangle {
width: 100
height: 100
color: "tomato"
opacity: 0.5
}
Text {
text: "this text will get clipped even when layer size is defined"
}
}
}
You can use renderdoc to see how the rendering is done; for example you can see the texture that is created by enabling the layer.
This is a small reproducible example:
import QtQuick
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Item {
//width: 200
//height: 200
//layer.enabled: true
Rectangle {
width: 100
height: 100
color: "red"
}
}
}
I suspect that if you don't set a size on the Item on which you want to enable the layer (layer.enabled: true), it will have a size of 0. Hence the offscreen buffer has a size of 0.
As a side note, this works without layer, because the clip property of an Item by default is set to false. So it won't clip to the bounds of its parent.
I have a Qt QML application. Following is the complete code of the application:
Code:
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
id: app_main_window
visible: true
width: 800
height: 600
title: qsTr("Hello QML")
Rectangle {
id: my_item_1
x: 100
y: 100
width: 100
height: 100
color: "grey"
visible: true
z: 1
}
Rectangle {
id: my_item_2
x: 400
y: 400
width: 100
height: 100
color: "grey"
visible: true
z: 1
MouseArea {
anchors.fill: parent
onClicked: {
// How can I change the center of my_item_1 to some arbitrary new center. lets say app_main_window's center. this involves another question. how can I get app_main_window's center?
}
}
}
}
Question:
My question is simple. How can change the center of any QQuickitem to a new center? So in above case how can change the center of my_item_1 to a new center (Qt.point(some_x_center, some_y_center)) when my_item_2 gets a click event.
Additionally, is possible to get another item's center? Like app_main_window or my_item_2's center to apply to the target my_item_1?
PS:
I have made the code simple to make the question objective. I have quite a complicated logic in my actual code where I need to realign something like my_item_1 to a new center without usage of anchors as the QQuickitem I am trying to do that with is scaled and panned into a new point.
If anchors can't be used, you have to calculate manually the center and assign it.
Quick example:
Item
{
anchors.fill: parent
Rectangle
{
id: nonParentOrSibling
width: 200
height: 200
x: 350
y: 240
color: "red"
}
}
Rectangle
{
id: rectToMove
width: 100
height: 100
y: 200
color: "blue"
MouseArea
{
anchors.fill: parent
onClicked:
{
var itemCenter = Qt.point(nonParentOrSibling.x + nonParentOrSibling.width / 2, nonParentOrSibling.y + nonParentOrSibling.height / 2)
rectToMove.x = itemCenter.x - rectToMove.width / 2
rectToMove.y = itemCenter.y - rectToMove.height / 2
}
}
}
Note that this is a one time moving only, and the rectangle won't move if the target is moved.
To make it follow the target you have to rebind it with Qt.binding.
If rectToMove is not in the same coordinate system as nonParentOrSibling, you can use Item.mapToItem() and mapFromItem() to adapt the coordinates.
I'd like to replace a SwipeView with an Tumbler in QML as I prefer the notion, that there is no first and no last Item.
The problem is, I can't find any other way to get this Tumbler tumble horizontally instead of vertically, but to rotate it by -90° and then rotate the Items back by +90°
This is my code so far, and works as expected:
import QtQuick 2.5
import QtQuick.Controls 2.0
import QtQuick.Window 2.2
Window {
id: root
visible: true
width: 640
height: 480
Row {
id: buttons
spacing: 2
Button {
text: '0'
onClicked: tumbl.currentIndex = 0
}
Button {
text: '1'
onClicked: tumbl.currentIndex = 1
}
Button {
text: '2'
onClicked: tumbl.currentIndex = 2
}
Button {
text: '3'
onClicked: tumbl.currentIndex = 3
}
}
Tumbler {
id: tumbl
rotation: -90 // <---- Rotate there
anchors {
top: buttons.bottom
left: buttons.left
right: buttons.right
bottom: parent.bottom
}
model: 4
delegate: Rectangle {
rotation: 90 // <---- Rotate back
color: 'red'
border.width: 15
Text {
anchors.centerIn: parent
text: index
}
}
visibleItemCount: 1
Component.onCompleted: contentItem.interactive = false
}
}
You can see the two lines, in which I do the rotation marked with a comment.
Does anybody know a way to either produce this circular behavior with a SwipeView or to change the tumble-orientation of the tumbler without this rotation trick?
I am creating a ListView with horizontal orientation. The highlight is set to one fixed position of the view so that the list elements scroll through the visible area when I increment/decrement the current Item. Here is my code for the view:
ListView {
anchors.fill: parent
model: ListModel{
ListElement{name:"x"}
ListElement{name:"y"}
ListElement{name:"z"}
}
delegate:
Rectangle {
property int viewW: ListView.view.width
property bool isCurrent: ListView.isCurrentItem
width: ListView.isCurrent? viewW * 0.4 : viewW * 0.3
Text {
anchors.fill: parent
text: name
}
}
orientation: Qt.Horizontal
highlight: Rectangle {color: "transparent"}
preferredHighlightBegin: 0
preferredHighlightEnd: width*0.4
highlightRangeMode: ListView.StrictlyEnforceRange
}
I want the delegate of the current item to have a greater width than all the other elements. However, when the width of all delegates is not identical, the list scrolling animation (e.g. you can see elements moving to next position, instead of just appearing on the new position) does not apply any more.
How can I have a ListView with the current element showing a different width than the rest of the other elements, while still being able to have the scrolling animations?
The currently selected item can be modified by combining the property to modify with the currentIndex/index properties. The former is the property contained in the ListView to indicate the selected item (as you already know). The latter is a property exposed in the delegate to represent the index of the corresponding item in the list. When we have that
ListView.view.currentIndex === index
we are in the currently selected item. Hence, in your delegate, you can write something like this:
width: ListView.view.currentIndex === index ? 60 : 30
Now the selected item will be twice as large as the other items. However the effect is a little bit ugly. I would go for the following one:
scale: ListView.view.currentIndex === index ? 1.5 : 0.5
Here you are saying that "when this item is the selected one it should grow by 50%, otherwise it should shrink by 50%".
The final code for the width could look like this:
import QtQuick 2.3
import QtQuick.Window 2.0
import QtQuick.Controls 1.2
Window {
id: container
width: 300
height: 150
visible: true
ListView {
id: list
anchors.fill: parent
spacing: 5
model: ListModel{
ListElement{name:"a"}
ListElement{name:"b"}
ListElement{name:"c"}
ListElement{name:"d"}
ListElement{name:"e"}
ListElement{name:"f"}
ListElement{name:"g"}
ListElement{name:"h"}
ListElement{name:"i"}
ListElement{name:"j"}
ListElement{name:"k"}
ListElement{name:"l"}
ListElement{name:"x"}
ListElement{name:"y"}
ListElement{name:"z"}
}
delegate:
Rectangle {
width: ListView.view.currentIndex === index ? 60 : 30 // the magnifying/shrinking
color: "steelblue"
height: ListView.view.height
Text {
anchors.centerIn: parent
text: name
font.pixelSize: 20
}
Behavior on width { // added to smooth the resizing
NumberAnimation { duration: 100 }
}
}
orientation: Qt.Horizontal
highlight: Rectangle {color: "transparent"}
preferredHighlightBegin: 0
preferredHighlightEnd: delegate.width
highlightRangeMode: ListView.StrictlyEnforceRange
}
}
And the effect is not that beautiful as said. I would go for the scale property, as follows:
import QtQuick 2.3
import QtQuick.Window 2.0
import QtQuick.Controls 1.2
Window {
id: container
width: 300
height: 150
visible: true
ListView {
id: list
anchors.fill: parent
spacing: 5
model: ListModel{
ListElement{name:"a"}
ListElement{name:"b"}
ListElement{name:"c"}
ListElement{name:"d"}
ListElement{name:"e"}
ListElement{name:"f"}
ListElement{name:"g"}
ListElement{name:"h"}
ListElement{name:"i"}
ListElement{name:"j"}
ListElement{name:"k"}
ListElement{name:"l"}
ListElement{name:"x"}
ListElement{name:"y"}
ListElement{name:"z"}
}
delegate:
Rectangle {
scale: ListView.view.currentIndex === index ? 1.5 : 0.5
color: "transparent"
width: 30
height: ListView.view.height
Text {
anchors.centerIn: parent
text: name
font.pixelSize: 20
}
Behavior on scale { // added to smooth the scaling
NumberAnimation { duration: 100 }
}
}
orientation: Qt.Horizontal
highlight: Rectangle {color: "steelblue"}
preferredHighlightBegin: 0
preferredHighlightEnd: delegate.width
highlightRangeMode: ListView.StrictlyEnforceRange
}
}
Note that the highlight it strictly maintained at the beginning of the list (i.e. at the left side) as required.
We have to make progress bar consisting with slider, which has colour transition as the slider proceeds as shown in the figure below.
I tried my hand with below logic but could not get the desired effect. Any help or suggestion how to implement the same.
Below is my code snippet
import QtQuick 1.1
Rectangle {
id: container
width: 500; height: 400
Row {
id:repeaterid
x: 75
y: 280
anchors.bottom: parent.bottom
anchors.bottomMargin: 114
spacing: 4
Repeater {
model: 50
Rectangle {
id: smallrect
color: "red"
width:4
height:4
}
}
}
Timer {
id: progressTimer
interval: 50
running: true
repeat: true
onTriggered: {
if (slider.x < 460)
{
slider.x += repeaterid.spacing + 4
smallrect.color = "green"
}
}
}
Rectangle {
id: slider
x: repeaterid.x
y: repeaterid.y
width: 6; height: 6
color: "blue"
}
}
I have tried to use ColorAnimation, but got any luck.
The timer works correctly. The problem is entirely different: Your try to access smallrect in the onTriggerd handler, an undefined reference outside of the Repeater. Try to solve the problem more declarative:
use an integer property in the container to store the current position of progress bar
in smallrect use the value of that property to set the color (index < position? "green": ... )
use a Timer or better a NumberAnimation to update that property
get rid of slider rectangle, just give the right rectangle in the Repeater a blue color
To access the items within the repeater you can use the itemAt(index) function. This will allow you to change the color of the repeaters children. I also added a indexCurrent property to keep track of the current index.
Try this code:
import QtQuick 1.1
Rectangle {
id: container
width: 500; height: 400
property int indexCurrent: 0
Row {
id:repeaterid
x: 75
y: 280
anchors.bottom: parent.bottom
anchors.bottomMargin: 114
spacing: 4
Repeater {
id: repeater
model: 50
Rectangle {
id: smallrect
color: "red"
width:4
height:4
}
}
}
Timer {
id: progressTimer
interval: 50
running: true
repeat: true
onTriggered: {
if (slider.x < 460)
{
slider.x += repeaterid.spacing + 4
repeater.itemAt(indexCurrent).color = "green"
indexCurrent = indexCurrent + 1
}
}
}
Rectangle {
id: slider
x: repeaterid.x
y: repeaterid.y
width: 6; height: 6
color: "blue"
}
}