I want to change this code so when I click on the ball, it turns red. Can anyone help me? I'm new to java:
http://download.oracle.com/javafx/1.3/tutorials/ui/syntax/index.html
Try this:
import javafx.scene.Scene;
import javafx.scene.shape.Rectangle;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.scene.input.MouseEvent;
var circle: Circle;
Stage {
title: "Declaring Is Easy!"
scene: Scene {
width: 300
height: 250
content: [
circle = Circle {
centerX: 150 centerY: 120 radius: 80
fill: Color.MAROON
stroke: Color.INDIANRED
strokeWidth: 10.0
}, //Circle
Rectangle {
x: 25, y: 80 width: 250, height: 80
arcWidth: 20 arcHeight: 20
fill: Color.web("#6699ff")
stroke: Color.web("#003399")
strokeWidth: 5.0
onMouseClicked:function(e: MouseEvent)
{
if(circle.fill == Color.MAROON)
circle.fill = Color.GREEN
else
circle.fill = Color.MAROON
}
} //Rectangle
] //Content
} //Scene
} //Stage
Two changes here:
1) Extract Circle in a variable (circle), so that it can be used later.
2) Add a mouse clicked event to the rectangle, to flip colors.
you just have to change the word circle into rectangle right here
if(**circle**.fill == Color.MAROON)
**circle**.fill = Color.GREEN
else
**circle**.fill = Color.MAROON
}
if(**rectangle**.fill == Color.MAROON)
**rectangle**.fill = Color.GREEN
else
**rectangle**.fill = Color.MAROON
}
and put in this sentence var rectangle : Rectangle; just like var circle: Circle;
Related
I'm creating a "dotted paper" component for my QML app. Essentially this components consists of a dotted background that the user can zoom upon. To create this I used the following code:
DottedPaper.qml
import QtQuick 2.15
Rectangle{
id: page
property int spacing: 50
// this property changes the spacing between the dots
property real contentScale: 1.0
Repeater{
id: rowRepeater
model: 200
Repeater{
id: row
property int rowIndex: index
model: 200
Rectangle{
id: circle
color: "red"
width: 4; height: 4
x: index * spacing * page.contentScale + width/2;
y: rowIndex * spacing * page.contentScale+ height/2
radius: width/2
}
}
}
}
Then in my main file I have the following:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Flickable{
clip: true // doesn't improve anything
anchors.fill: parent
contentWidth: paper.width
contentHeight: paper.height
DottedPaper{
id: paper
width: 10000; height: 10000;
clip: true
}
}
// the slider changes the content scale of the dotted paper
Slider{
from: 1
to: 3
onValueChanged: paper.contentScale = value
}
}
The problem with this code is that it's slow. Upon checking the application does not render the content at 60fps, but I get around 45 - 50 fps on my desktop. I suspect the issues is that QML is reevaluating the contentScale property binding for each circle in the background even if the circle is not visible on the screen. What is the best way to prevent this?
It works a lot better if you change your Repeaters to be ListViews. That's because a ListView is smart enough to only create enough delegates as needed for the visible space. (At first I thought a GridView would work, but that doesn't give you enough control over rows/columns.)
Rectangle{
id: page
property int cellWidth: 50 * contentScale
property int dotWidth: 4
// this property changes the spacing between the dots
property real contentScale: 1.0
ListView {
id: grid
model: 200
anchors.fill: parent
anchors.leftMargin: page.dotWidth / 2
anchors.topMargin: page.dotWidth / 2
spacing: page.cellWidth - page.dotWidth
delegate: ListView {
model: 200
width: window.width
height: page.dotWidth
orientation: ListView.Horizontal
spacing: page.cellWidth - page.dotWidth
property int rowIndex: index
delegate: Rectangle{
id: circle
color: "red"
width: page.dotWidth; height: page.dotWidth
radius: width/2
}
}
}
}
I have been asked, using Konvajs, to work out an animation that will rotate a circle as if spinning on its central x-axis. So imagine a coin spinning on a table. The intention is to reveal some text on the circle. At the start the circle is fully visible as if from behind so no text visible, then it flips to reveal the text.
I have this code that does a rotation like a spinning wheel.
Can anyone give me a tween / animation approach that would achieve the spinning coin effect?
// the tween has to be created after the node has been added to the layer
var tween = new Konva.Tween({
node: group,
duration: 4,
rotation: 360,
easing: Konva.Easings.BackEaseOut
}
});
tween.play();
After some research it looks like a 3D spin requires heavier lifting which may not be available or work well on mobile.
A good second-best appears to be using scaleX and animating from 0 > 1.
group.scaleX(0);
var tween = new Konva.Tween({
node: group,
duration: .25,
scaleX: 1,
easing: Konva.Easings.EaseOut
});
Here is an example of the second-best version using scaleX() effect. Because of the need to calculate scaleX() and control visibility of the text so as to make it appear that the disc is solid, I moved away from a tween and over to an animation().
// Set up the canvas / stage
var s1 = new Konva.Stage({container: 'container1', width: 300, height: 200});
// Add a layer for line
var layer = new Konva.Layer({draggable: false});
s1.add(layer);
// just a plain JS object to keep common variables in hand.
var cfg = { w: 300, h: 200, r: 80, txtSize: 520};
var group = new Konva.Group();
var circle = new Konva.Circle({x: cfg.w/2, y: cfg.h/2, radius: cfg.r, fill: 'DodgerBlue', stroke: 'DeepPink', strokeWidth: 5})
group.add(circle)
var textValue = new Konva.Text({
id: "t1",
x: cfg.w/2,
y: cfg.h/2,
text: '',
fill: 'DeepPink ',
fontSize: cfg.txtSize
});
group.add(textValue);
textValue.offset({x: textValue.getWidth()/2, y: textValue.getHeight()/2});
layer.add(group)
// to spin a group about a point, set the offset to that point, then set the x & y to that point to !
var pos = group.getClientRect();
RotatePoint(group, {x: pos.x + pos.width/2, y: pos.y + pos.height/2});
// Everything is ready so draw the canvas objects set up so far.
s1.draw()
$('#st').on('click', function(){
group.scaleX(1);
var txt = $('#theText').val();
setValue(txt);
})
// set the offset for rotation to the given location and re-position the shape
function RotatePoint(shape, pos){ // where pos = {x: xpos, y: yPos}
var initialPos = shape.getAbsolutePosition();
var moveBy = {x: pos.x - initialPos.x, y: pos.y - initialPos.y};
// offset is relative to initial x,y of shape, so deduct x,y.
shape.offsetX(moveBy.x);
shape.offsetY(moveBy.y);
shape.x(initialPos.x + moveBy.x);
shape.y(initialPos.y + moveBy.y);
}
var setValue = function(newText){
// work out scaling to make text fit into the circle
var txt = this.layer.find('#t1')[0];
txt.text(newText).scale({x:1, y: 1})
var txtSize = txt.getClientRect();
var maxW = (cfg.r); // max allowed width of text
var txtScaleW = (txtSize.width > maxW ? ( maxW / txtSize.width) : 1);
var maxH = cfg.r; // max allowed height of text
var txtScaleH = (txtSize.height > maxH ? ( maxH / txtSize.height) : 1);
// finally decide which is the worst case and use that scaling
var txtScale = ( txtScaleW > txtScaleH ? txtScaleH : txtScaleW);
txt.scale({x: txtScale, y: txtScale});
txt.offset({x: txt.getWidth()/2, y: txt.getHeight()/2});
layer.draw()
}
// set initial text & spin !
setValue('BBB');
var anim, pos = 0, frameCnt = 0
if (anim) {anim.stop(); }
anim = new Konva.Animation(function(frame) {
frameCnt = frameCnt + 1;
if (frameCnt % 2 === 0){
pos = pos + .2
var scaleX = Math.sin(pos)
textValue.visible(scaleX < 0 ? false : true);
group.scaleX(scaleX);
if (pos % 360 === 0){ console.log('spin') }
}
}, layer);
anim.start();
div
{
float: left;
margin: 0 5px;
}
p
{
margin: 0 5px 5px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.5.1/konva.min.js"></script>
<div id='container1' style="width: 300px, height: 200px;"></div>
<div>
<p> <input type='text' id='theText' value='BBB' /> <button id='st'>Change text</button> </p>
</div>
I have a canvas with background image, now I need to draw virtual regions on that canvas for selecting some parts of the image.
Currently I am using fabricjs to draw simple shapes like rectangle, circle on canvas. But don't know how to draw complex shapes.
Can anyone help please?
function createPath(event) {
var pointers = canvas.getPointer(event.originalEvent);
if (firstClick) {
var pointsArray = ["M", pointers.x, pointers.y];
initializePath(pointsArray);
firstClick = false;
}
else {
var pointsArray = ["L", pointers.x, pointers.y];
addPath(pointsArray);
}
}
function initializePath(pointsArray) {
var path = new fabric.Path('M 0 0');
path.path[0] = pointsArray;
path.set({
fill: 'red', stroke: 'green', opacity: 0.3,
Type: ObjectType.Region,
shape: builderConstants.HeatMapShapeType.Polygon
});
canvas.add(path);
}
function addPath(pointsArray) {
var latestAddedPath = canvas.getObjects()[Object.keys(canvas.getObjects()).length - 1];
latestAddedPath.path.push(pointsArray);
latestAddedPath.path.push(["z"]);
canvas.renderAll();
}
if you want to make heart shape you can use these code
function heartshape()
{
var path = new fabric.Path('M 272.70141,238.71731 \
C 206.46141,238.71731 152.70146,292.4773 152.70146,358.71731 \
C 152.70146,493.47282 288.63461,528.80461 381.26391,662.02535 \
C 468.83815,529.62199 609.82641,489.17075 609.82641,358.71731 \
C 609.82641,292.47731 556.06651,238.7173 489.82641,238.71731 \
C 441.77851,238.71731 400.42481,267.08774 381.26391,307.90481 \
C 362.10311,267.08773 320.74941,238.7173 272.70141,238.71731 \
z ');
var scale = 100 / path.width;
path.set({ left: 20, top: 0, scaleX: scale, scaleY: scale, fill: 'red', });
canvas.add(path);
canvas.renderAll();
}
What I am attempting to do is anchor an Item over a particular place over an Image. The Image needs to use Image.PreserveAspectFit for the fillMode. The problem I am having is that the height/width/paintedWidth/paintedHeight of the Image are for the entire image "canvas" (I'm not sure what it's actually called), not the drawn part of the image itself. So I can't anchor to the actual image.
See code below for an example I tried with anchors (red rectangle) and with a child rectangle and x,y coordinates (green rectangle).
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
visible: true
height: 400
width: 400
Image {
id: image
anchors.fill: parent
fillMode: Image.PreserveAspectFit
source: "image.jpg"
Rectangle {
id: bottomRight
width: 40
height: 40
color: "green"
x: parent.width * 0.75
y: parent.height * 0.75
}
}
Rectangle {
id: topLeft
width: 40
height: 40
color: "red"
anchors.top: image.top
anchors.left: image.left
anchors.topMargin: image.height * 0.25
anchors.leftMargin: image.width * 0.25
}
}
When you change the size of the window the placement of the rectangles is not in the same place over the image. I'd post some screenshots but I don't have enough reputation yet!
I poked around through the widget tree using the debugger but I can't seem to find any properties that provide the information about the scaling that I could use to calculate placement of the rectangles.
Update
I used the following functions to calculate the margins since I will be using potentially lots of these overlays.
function horMargin(val)
{
return ((image.width - image.paintedWidth)/2 + image.paintedWidth * val)
}
function verMargin(val)
{
return ((image.height - image.paintedHeight)/2 + image.paintedHeight * val)
}
Did you try to use paintedWidth and paintedHeight? :)
This will give you a rectangle that fills the painted image:
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
visible: true
height: 400
width: 400
Image {
id: image
anchors.fill: parent
fillMode: Image.PreserveAspectFit
source: "image.jpg"
}
Rectangle {
x: (image.width - image.paintedWidth) / 2
y: (image.height - image.paintedHeight) / 2
width: image.paintedWidth
height: image.paintedHeight
color: "transparent"
border.color: "darkorange"
border.width: 2
}
}
From there, you can work out how to apply the margins that you need.
In the following example I have two shapes, a rectangle and a semitransparent circle:
http://jsfiddle.net/cequiel/zZ22s/
var stage = new Kinetic.Stage({
container: 'canvas',
width: 800,
height: 600
});
var layer = new Kinetic.Layer();
// adds a rectangle
var rect = new Kinetic.Rect({
x: 100,
y: 50,
width: 200,
height: 150,
fill: 'yellow',
stroke: 'black'
});
rect.on('mousedown', function() {
$('#text').text('mouse down');
}).on('mouseup', function() {
$('#text').text('mouse up');
}).on('mouseenter', function() {
$('body').css('cursor', 'pointer');
$('#text').text('mouse enter');
}).on('mouseleave', function() {
$('body').css('cursor', 'default');
$('#text').text('mouse leave');
});
layer.add(rect);
// adds a semitransparent circle
var circ = new Kinetic.Circle({
x: 300,
y: 125,
radius: 60,
fill: 'green',
stroke: 'black',
opacity: 0.2,
locked: true
});
layer.add(circ);
stage.add(layer);
The rectangle captures the mouse down, up, enter and leave events. But when the mouse is over the circle, the rectangle doesn't receive any event. And this is fine. But, how could I avoid this? I mean, how could I make the circle "invisible" to the mouse events? I'm looking for something similar to the 'mouseEnabled' property defined in AS3:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/InteractiveObject.html#mouseEnabled
Thanks.
You can instruct any shape to temporarily stop listening for events like this:
myShape.setListening(false);