property location in qml - qml

I have error
ReferenceError: redRow is not defined
on this code:
Repeater {
property int redRow: 0
...
Image {
...
anchors.bottom: parent.bottom
anchors.bottomMargin: height / 16 + height * redRow
...
}
if i put
property int redRow: 0
in the begin of file - all right, why i don't have a opportunity put this in Repeater element?

You can put this in the repeater but you have to reference this variable by the id of repeater:
Repeater {
id: repeater //add id to the repeater this can be any unique identifier
property int redRow: 0
...
Image {
...
anchors.bottom: parent.bottom
anchors.bottomMargin: height / 16 + height * repeater.redRow //reference repeaters property
...
}
}

Related

55/5000 The QuickItem implementation layer, the underlying control of the qml cascade control, cannot receive QMouseEvent* or QTouchEvent*

contentItem: QuarterViewPositioner {
id: control
spacing: 6
readonly property color backgroundColor: Qt.rgba(0,0,0,1.0)
item0: QImageView3D {
id: iv0
backgroundColor: control.backgroundColor
orientation: 0
property real lastZoom: 1
property real radio: 0.5
property real lastRadio: 0.5
QImageView3D inherit from QQuickFramebufferObject,
QImgaeView3D include a 'control' component named 'ControlTransRot3D' , this 'control' contains the Rectangle contentItem.
ControlTransRot3D {
id: tr0Channel
visible: showChannelRot3D && (uidata.channelListShowModel.count > 0 || uidata.traumaListShowModel.count > 0)
parent: item0
width: 100
height: 100
centerX: 200
centerY: 200
viewType:0
}
Control {
id:ctrl
property real w:0
property real h:0
property real centerX: ctrl.width / 2.0
property real centerY: ctrl.height / 2.0
property bool showUpDownBtn: true
property var viewType: EnumType.VertralSliceA
x: centerX - ctrl.width / 2.0
y: centerY - ctrl.height / 2.0
rotation: 0
property bool rotBtnVisible: true
property int hOffset: -60
// property int sizeBtn: 30
// property int sizeIcn: 16
property int sizeBtn: 33
property int sizeIcn: 30
property string bgColor: "transparent"
contentItem: Rectangle {
id: rectangle
color: "transparent"
anchors.fill: parent
//border.width: 2
//border.color: "#ff0000"
ToolButton {
when i touch the current rectangle on the touchscreen, i can't receive QMouseEvent * or QTouchEvent * on the parent QImageView3D
virtual void mousePressEvent(QMouseEvent* event);
virtual void mouseMoveEvent(QMouseEvent* event);
but when i use mouse to click the rectangle, the parent QImageView3D can receive the QMouseEvent * or QToucheEvent.
It seems that the signal under the touch screen is impenetrable.
The attribute propagateComposedEvents or mouse.accepted has been tried, it does not work.
And I have tried to test in the MouseArea,the MouseArea can capture the signal but cannot receive it in the MouseMoveEvent in the Cpp.

RecyclerView divider width with ItemDecoration

I have a RecyclerView and have added an ItemDecoration to it as follows :-
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
My ItemDecoration looks like :-
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)
{
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
{
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
This draws a divider taking full width of the screen. I want to add a little margin from the left and right of about 15dp (red line) so that it looks shorter than the screen width something like below :-
How can I achieve this? Any suggestions are appreciated.
Have a look at getItemOffsets method. Something like following should do it.
override fun getItemOffsets(
rect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
rect.right = parent.right - yourMargin
rect.left = parent.left + yourMargin
}
This method will set the rect space where you'll draw (onDraw(...)) your decoration.
Just put the value of
final int left = 200;
final int right= 200;

QML: Move a frameless window by dragging

I have a frameless QQuickWindow, and I want to move it with the mouse by dragging. Before trying in my big application, I have created a simple test application to try what I found here, using cursor position from C++ class to avoid problems from QML:
http://www.tickanswer.com/solved/5390888353/dragging-frameless-window-jiggles-in-qml
But I failed with the code below. When I press over the red RECT and move the mouse, my yellow rect (root RECT) moves, but only inside the original size it had (in this case, 500x500)... What am I doing wrong?
Thanks in advance
In my main.cpp:
int main(int argc, char *argv[])
{
QtQuickControlsApplication a(argc, argv);
QQuickView* pView = new QQuickView();
CursorPosProvider mousePosProvider;
pView->rootContext()->setContextProperty("mousePosition", &mousePosProvider);
pView->setSource(QUrl("qrc:/Test.qml"));
pView->setFlags(Qt::FramelessWindowHint);
pView->show();
return a.exec();
}
Test.qml:
import QtQuick 2.0
Rectangle {
id: myWindow
width: 500; height: 500
color: "yellow"
Rectangle {
anchors.centerIn: parent
width: 200; height: 200
color: "red"
MouseArea {
id: titleBarMouseRegion
property var clickPos
anchors.fill: parent
onPressed: clickPos = { x: mousePosition.cursorPos().x, y: mousePosition.cursorPos().y }
onPositionChanged: {
myWindow.x = mousePosition.cursorPos().x - clickPos.x
myWindow.y = mousePosition.cursorPos().y - clickPos.y
}
}
}
}
cursorprovider.h:
#ifndef CURSORPOSPROVIDER_H
#define CURSORPOSPROVIDER_H
#include <QObject>
#include <QPointF>
#include <QCursor>
class CursorPosProvider : public QObject
{
Q_OBJECT
public:
explicit CursorPosProvider(QObject *parent = nullptr) : QObject(parent)
{
}
virtual ~CursorPosProvider() = default;
Q_INVOKABLE QPointF cursorPos()
{
return QCursor::pos();
}
};
#endif // CURSORPOSPROVIDER_H
I wrote this example and I see no jiggle (running on Linux)
ApplicationWindow {
id: iWindow
visible: true
title: "My title"
color: "gray"
width: 500
height: 500
MouseArea{
id: iMouseArea
property int prevX: 0
property int prevY: 0
anchors.fill: parent
onPressed: {prevX=mouse.x; prevY=mouse.y}
onPositionChanged:{
var deltaX = mouse.x - prevX;
iWindow.x += deltaX;
prevX = mouse.x - deltaX;
var deltaY = mouse.y - prevY
iWindow.y += deltaY;
prevY = mouse.y - deltaY;
}
}
}
I have changed the structure, I have used a QQuickWidget with a QML inside, and now I have what I wanted. Here is my code in case anyone needs something similar
main.cpp
...
MovableWidget *view = new MovableWidget;
view->setSource(QUrl("qrc:/Test.qml"));
view->setWindowFlags(Qt::FramelessWindowHint);
view->show();
...
Test.qml
import QtQuick 2.0
Rectangle {
id: myWindow
width: 500; height: 500
color: "yellow"
Rectangle {
anchors.centerIn: parent
width: 200; height: 200
color: "red"
}
}
MovableWidget.cpp
#include "movableWidget.h"
#include <QMouseEvent>
// ****************************************************************************
MovableWidget::MovableWidget(QWidget *parent)
: QQuickWidget(parent),
m_previousPos(0,0)
{
installEventFilter(this);
}
// ****************************************************************************
bool MovableWidget::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
m_previousPos = QCursor:os();
}
else if (event->type() == QEvent::MouseMove)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if(mouseEvent->buttons() == Qt::LeftButton)
{
QPoint offset = m_previousPos - QCursor:os();
m_previousPos = QCursor:os();
move(pos() - offset);
}
}
return false;
}

Using sprite sheets in xcode

I'm trying to animate my game using a sprite sheet. How would I go about cutting out each sprite from the sprite sheet and using the sprite in xcode? I'm currently using obj -c. I read somewhere that i need to use a frame work, cocoa2d, in order to do this?
In sprite kit you can cut part of a texture out using SKTexture(rect: inTexture:) initializer. This is a helper class which manages an evenly spaced sprite sheet and can cut out a texture at a given row and column. It is used like So
let sheet=SpriteSheet(texture: SKTexture(imageNamed: "spritesheet"), rows: 1, columns: 11, spacing: 1, margin: 1)
let sprite=SKSpriteNode(texture: sheet.textureForColumn(0, row: 0))
Here is the full code
//
// SpriteSheet.swift
//
import SpriteKit
class SpriteSheet {
let texture: SKTexture
let rows: Int
let columns: Int
var margin: CGFloat=0
var spacing: CGFloat=0
var frameSize: CGSize {
return CGSize(width: (self.texture.size().width-(self.margin*2+self.spacing*CGFloat(self.columns-1)))/CGFloat(self.columns),
height: (self.texture.size().height-(self.margin*2+self.spacing*CGFloat(self.rows-1)))/CGFloat(self.rows))
}
init(texture: SKTexture, rows: Int, columns: Int, spacing: CGFloat, margin: CGFloat) {
self.texture=texture
self.rows=rows
self.columns=columns
self.spacing=spacing
self.margin=margin
}
convenience init(texture: SKTexture, rows: Int, columns: Int) {
self.init(texture: texture, rows: rows, columns: columns, spacing: 0, margin: 0)
}
func textureForColumn(column: Int, row: Int)->SKTexture? {
if !(0...self.rows ~= row && 0...self.columns ~= column) {
//location is out of bounds
return nil
}
var textureRect=CGRect(x: self.margin+CGFloat(column)*(self.frameSize.width+self.spacing)-self.spacing,
y: self.margin+CGFloat(row)*(self.frameSize.height+self.spacing)-self.spacing,
width: self.frameSize.width,
height: self.frameSize.height)
textureRect=CGRect(x: textureRect.origin.x/self.texture.size().width, y: textureRect.origin.y/self.texture.size().height,
width: textureRect.size.width/self.texture.size().width, height: textureRect.size.height/self.texture.size().height)
return SKTexture(rect: textureRect, inTexture: self.texture)
}
}
The margin property is the gap between the edge of the image and the sprites. The spacing is the gap between each sprite. The fameSize is the size each sprite will be. This image explains it:
Since the original question was tagged as Objective-C, here's a rough version of this SpriteSheet class in that language. Hope this is helpful:
#import "SpriteSheet.h"
#interface SpriteSheet ()
#property (nonatomic, strong) SKTexture *texture;
#property (nonatomic) NSInteger rows;
#property (nonatomic) NSInteger cols;
#property (nonatomic) CGFloat margin;
#property (nonatomic) CGFloat spacing;
#property (nonatomic, getter=frameSize) CGSize frameSize;
#end
#implementation SpriteSheet
- (instancetype)initWithTextureName:(NSString *)name rows:(NSInteger)rows cols:(NSInteger)cols margin:(CGFloat)margin spacing:(CGFloat)spacing {
SKTexture *texture = [SKTexture textureWithImageNamed:name];
return [self initWithTexture:texture rows:rows cols:cols margin:margin spacing:spacing];
}
- (instancetype)initWithTexture:(SKTexture *)texture rows:(NSInteger)rows cols:(NSInteger)cols {
return [self initWithTexture:texture rows:rows cols:cols margin:0 spacing:0];
}
- (instancetype)initWithTexture:(SKTexture *)texture rows:(NSInteger)rows cols:(NSInteger)cols margin:(CGFloat)margin spacing:(CGFloat)spacing {
if (self == [super init]) {
_texture = texture;
_rows = rows;
_cols = cols;
_margin = margin;
_spacing = spacing;
_frameSize = [self frameSize];
}
return self;
}
- (CGSize)frameSize {
CGSize newSize = CGSizeMake((self.texture.size.width - (self.margin * 2.0 + self.spacing * ((CGFloat)self.cols - 1.0))) / ((CGFloat)self.cols),
(self.texture.size.height - ((self.margin * 2.0) + (self.spacing * ((CGFloat)self.rows - 1.0))) / ((CGFloat)self.rows)));
return newSize;
}
- (SKTexture *)textureForColumn:(NSInteger)column andRow:(NSInteger)row {
if (column >= (self.cols) || row >= (self.rows)) {
NSLog(#"Asking for row or col greater than spritesheet");
return nil;
}
CGRect textureRect = CGRectMake(self.margin + (column * self.frameSize.width + self.spacing) - self.spacing,
self.margin + (row * self.frameSize.width + self.spacing) - self.spacing, // note using width here
self.frameSize.width,
self.frameSize.height);
textureRect = CGRectMake(textureRect.origin.x / self.texture.size.width, textureRect.origin.y / self.texture.size.height, textureRect.size.width / self.texture.size.width, textureRect.size.height/self.texture.size.height);
return [SKTexture textureWithRect:textureRect inTexture:self.texture];
}
I am adding this into a separate answer, because it contains two important things, that I found:
First :
var textureRect=CGRect(x: self.margin+CGFloat(column)*(self.frameSize.width+self.spacing)-self.spacing,
y: self.margin+CGFloat(row)*(self.frameSize.width+self.spacing)-self.spacing,
width: self.frameSize.width,
height: self.frameSize.height)
This code in Swift and its Objective-C counterpart both have a bug. The self.frameSize.width is used for both row and column calculations. The height needs to be used for column.
Second :
The coordinate system for SKTexture places its (0,0) origin at the bottom left corner of the image, this has to be considered when making your sprites or the code needs to be altered.
For example You can get all the frames of the sprite from top left corner to bottom right corner of the sprite like this:
var anim = [SKTexture]()
for row in (0..<self.rows).reversed() {
for column in 0..<self.columns {
if let frame = textureForColumn(column: column, row: row) {
anim.append(frame)
}
}
}
PS. I don't have the much experience with SpriteKit, so if there are any mistakes in my answer, please correct me.
I did a fix for getting sprites from top to bottom, left to right.
Also added a totalFrames so if you don't have a sprite with all frames, you can set the total frames so the array only contains the sprites, no blank sprites.
//
// SpriteSheet.swift
//
import SpriteKit
class SpriteSheet {
let texture: SKTexture
let rows: Int
let columns: Int
var margin: CGFloat=0
var spacing: CGFloat=0
var frameSize: CGSize {
return CGSize(width: (self.texture.size().width-(self.margin*2+self.spacing*CGFloat(self.columns-1)))/CGFloat(self.columns),
height: (self.texture.size().height-(self.margin*2+self.spacing*CGFloat(self.rows-1)))/CGFloat(self.rows))
}
init(texture: SKTexture, rows: Int, columns: Int, spacing: CGFloat, margin: CGFloat) {
self.texture=texture
self.rows=rows
self.columns=columns
self.spacing=spacing
self.margin=margin
}
convenience init(texture: SKTexture, rows: Int, columns: Int) {
self.init(texture: texture, rows: rows, columns: columns, spacing: 0, margin: 0)
}
func textureForColumn(column: Int, row: Int)->SKTexture? {
if !(0...self.rows ~= row && 0...self.columns ~= column) {
return nil
}
var textureRect = CGRect(x: self.margin + CGFloat(column) * (self.frameSize.width+self.spacing)-self.spacing, y: self.margin + CGFloat(self.rows - row - 1) * (self.frameSize.height+self.spacing)-self.spacing,
width: self.frameSize.width,
height: self.frameSize.height)
textureRect = CGRect(x: textureRect.origin.x/self.texture.size().width, y: textureRect.origin.y/self.texture.size().height,
width: textureRect.size.width/self.texture.size().width, height: textureRect.size.height/self.texture.size().height)
return SKTexture(rect: textureRect, in: self.texture)
}
}
To call, just add the animation like this:
fileprivate let framesOpening: [SKTexture] = {
let totalFrames = 28
let rows = 6
let columns = 5
let sheet = SpriteSheet(texture: SKTexture(imageNamed: "GETREADY"), rows: rows, columns: columns, spacing: 0, margin: 0)
var frames = [SKTexture]()
var count = 0
for row in (0..<rows) {
for column in (0..<columns){
if count < totalFrames {
if let texture = sheet.textureForColumn(column: column, row: row) {
frames.append(texture)
}
}
count+=1
}
}
return frames
}()
and call it
let sprite1 = SKSpriteNode(texture: framesOpening.first)
let openingAnimation: SKAction = SKAction.animate(with: framesOpening, timePerFrame: 0.2, resize: false, restore: true)
sprite1.position = CGPoint(x: frame.midX, y: frame.midY)
sprite1.zPosition = 2000
self.addChild(sprite1)
sprite1.run(SKAction.repeatForever(openingAnimation))

Copying Rectangles Automatically in Qml

Is it possible to make a certain amount of copies of a rectangle maybe by using a for loop or by any other way with the ability of changing each rectangle attributes like x,y,width etc.. by using QML
I have tried the following :
var x = 0
var t = 80
var z = 125
var Rectangle = []
if(rs.rows.length > 0){
x = 2
for(var i = 0; i < rs.rows.length; i++){
Rectangle[i] = rectangle18
Rectangle[i].x = t
Rectangle[i].y = z
Rectangle[i].visible = true
t = t - 40
z = z - 7
}
}
But unfortunately it's not working with me, is there a way of making this working
It's not quite that simple. You need to use Qt.createComponent and that object's createObject() call to achieve what you want. It's not just a matter of creating the rectangle and then copying it, you need to load each new copy separately from a qml file.
Something like:
var rects = []
var creator = Qt.createComponent("myRect.qml")
for (var i = 0; i < 10; i++) {
rects[i] = creator.createObject(PARENT)
rects[i].x = ...
}
Obviously extrapolating it to what you need. Note the reference to PARENT, which is the object that should end up containing the rectangle, which is often a container like a Grid or something.
If you don't want to use the Qt.CreateComponent method you can also consider using a Repeater component with a ListModel containing the info for each Rectangle. Here is an example placing 4 Rectangle in the scene:
ListModel {
id: modelRects
ListElement { _x: 0; _y:0 ; _width: 10; _height: 10; _color: "red" }
ListElement { _x: 100; _y:0 ; _width: 20; _height: 20; _color: "blue" }
ListElement { _x: 0; _y:100 ; _width: 30; _height: 30; _color: "yellow" }
ListElement { _x: 100; _y:100 ; _width: 40; _height: 40; _color: "green" }
}
Repeater {
model: modelRects
delegate: Rectangle {
width: _width
height: _height
x: _x
y: _y
color: _color
}
}
If you don't want to create the ListModel you can also base your calculations on the index of the element. Here is an example growing the Rectangle based on the index:
Repeater {
model: 5
delegate: Rectangle {
// Index starts at 0 so you want a width higher than 0 on first element
width: 10 * (index + 1)
height: 10 * (index + 1)
x: 50 * index
y: 50 * index
color: "red"
}
}