How to create an event handler for objects in array? - windows

I'm making a game in which an ellipse is created whenever random number generated is 6. But all of these objects are in an array. Whenever last object of ellipse is created then event handler only works for it and not for previous objects . I've used sender argument to recognize the source but it gives and exception . Here's my code
public static Ellipse[] greenEllipse = new Ellipse[10];
Game.green++;
Game.greenEllipse[green] = new Ellipse();
SolidColorBrush s = new SolidColorBrush();
s.Color = Colors.Green;
SolidColorBrush blackBrush = new SolidColorBrush();
blackBrush.Color = Colors.Black;
// Set Ellipse's width and color
greenEllipse[green].StrokeThickness = 2;
greenEllipse[green].Stroke = blackBrush;
// Fill rectangle with blue color
greenEllipse[green].Fill = s;
greenEllipse[green].Height = 40;
greenEllipse[green].Width = 45;
greenEllipse[green].RenderTransform = new TranslateTransform { X = -200, Y = -72 };
greenEllipse[green].PointerPressed += OnClickge;
g.Children.Add(greenEllipse[green]);
private void OnClickge(object sender, RoutedEventArgs e)
{
var ocg = sender;
tt.Text = nee.ToString();
if (green1 < 4 && nee != 5 && nee != 6)
{
Game.px += nee * 40;
Game.greenEllipse[Convert.ToInt32(ocg)].RenderTransform = new TranslateTransform { X = px, Y = py };
green1 += nee;
}
if (nee == 5)
{
Game.py += (nee) * (-20);
Game.greenEllipse[Convert.ToInt32(ocg)].RenderTransform = new TranslateTransform { X = px + nee, Y = py };
}
if (green1 > 4)
{
if (nee != 5)
{
green1--;
Game.py += nee * (-20);
Game.greenEllipse[Convert.ToInt32(ocg)].RenderTransform = new TranslateTransform { X = px + nee, Y = py };
}
}
}

Related

Three.JS - Object rotation

we have following function to create object wall:
function placeWorkareaWithSlope(points, waDetail, drawLine = true) {
const workareaHeight = Number(waDetail.WorkareaHeight) || 10;
const workareaParapet = Number(waDetail.WorkareaParapet) || 3;
// Different color wall for workarea
drawWallForWorkareaWithSlope(points, workareaHeight, waDetail);
drawWallBoxForWorkareaWithSlope(points, workareaHeight, waDetail);
// Convert points array to accrding to 3D space Quadrant
const convertedPoints = convertTo3dQuadrant(points);
const shape = [];
for (let i = 0; i < convertedPoints.length; i++) {
const e = convertedPoints[i];
shape.push(new THREE.Vector2(e.x, e.y));
}
const workareaShape = new THREE.Shape(shape);
const extrusionSettings = {
steps: 1,
depth: workareaHeight,
bevelEnabled: false,
};
const workareaGeometry = new THREE.ExtrudeGeometry(workareaShape, extrusionSettings);
workareaGeometry.computeVertexNormals();
workareaGeometry.computeFaceNormals();
const workarea = new THREE.Mesh(workareaGeometry, workareaMaterial);
workarea.rotation.x = -THREE.Math.degToRad(90);
//added by kd to define slope angle
objRotation(points, waDetail, workarea);
//end kd
workarea.receiveShadow = isRenderShaodw;
workarea.castShadow = isRenderWorkareaShadow;
scene.add(workarea);
// DrawLines
if (drawLine && workarea && workarea.geometry) {
const lineGeo = new THREE.EdgesGeometry(workarea.geometry);
const wireframe = new THREE.LineSegments(lineGeo, workareaLineMaterial);
wireframe.renderOrder = 1;
workarea.add(wireframe);
}
}
once we create wall over scene after that we rotate it base on slope provided with objRotation function with obj.rotation.y but when we rotate it at that movement object change its place, basically we require object should be there with world axis
following is object rotation function :
function objRotation(points, waDetail, obj) {
const Point1 = points[0];
const Point2 = points[1];
const Point3 = points[2];
const Point4 = points[3];
const slopeAngle = Number(waDetail.Angle) || 0;
if (waDetail.SlopeDirection == "P1 to P2") {
xDiff = Point1.x - Point2.x;
yDiff = Point1.y - Point2.y;
}
if (waDetail.SlopeDirection == "P2 to P3") {
xDiff = Point2.x - Point3.x;
yDiff = Point2.y - Point3.y;
}
if (waDetail.SlopeDirection == "P3 to P4") {
xDiff = Point3.x - Point4.x;
yDiff = Point3.y - Point4.y;
}
if (waDetail.SlopeDirection == "P4 to P1") {
xDiff = Point4.x - Point1.x;
yDiff = Point4.y - Point1.y;
}
if (Math.abs(xDiff) > Math.abs(yDiff)) {
if (obj.rotation.x > 0) {
if (xDiff > 0)
obj.rotation.y += THREE.Math.degToRad(slopeAngle);
else
obj.rotation.y -= THREE.Math.degToRad(slopeAngle);
}
else {
if (xDiff > 0)
obj.rotation.y -= THREE.Math.degToRad(slopeAngle);
else
obj.rotation.y += THREE.Math.degToRad(slopeAngle);
}
} else {
if (yDiff<0)
obj.rotation.x += THREE.Math.degToRad(slopeAngle);
else
obj.rotation.x -= THREE.Math.degToRad(slopeAngle);
}
}
So for the above issue, can someone guide me?
The wall created by the code with height and width provided by system and it rotates 90 degrees to setup over map surface but after that we have a requirement to slope its base on an angle so we added one more rotation there with provided slope angle by user. But when this slope angle rotation applied to object the object change its height base on camera left or right distance. We require the object should be same place there as before after rotation.

how do i make FlxAsyncLoop work for making a progress bar in HaxeFlixel?

so, i tried to make an async loop for my game (to make a progress bar) and the game crashes when the state loads...
i tried to change the loops position so they don't collide and all of the code is from the FlxAsyncLoop demo but with other variables and some other changes.
here's the code:
import flixel.FlxCamera;
import flixel.FlxG;
import flixel.FlxObject;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.addons.util.FlxAsyncLoop;
import flixel.group.FlxGroup;
import flixel.math.FlxPoint;
import flixel.math.FlxVelocity;
import flixel.text.FlxText;
import flixel.ui.FlxBar;
import flixel.util.FlxColor;
class PlayState extends FlxState
{
public static var player:FlxSprite;
var ground:FlxSprite;
var axe:FlxSprite;
var wood:FlxSprite;
var base:FlxSprite;
var txt:FlxText;
var playerPos:FlxPoint;
var enemy:FlxSprite;
var move = false;
var progressR:FlxGroup;
var progressE:FlxGroup;
var resourceGroup:FlxGroup;
var enemyGroup:FlxGroup;
var maxItems:Int = 100;
var bar1:FlxBar;
var bartxt1:FlxText;
var bar2:FlxBar;
var bartxt2:FlxText;
var loopR:FlxAsyncLoop;
var loopE:FlxAsyncLoop;
public function addR()
{
var wood = new FlxSprite(FlxG.random.int(100, 2500), FlxG.random.int(100, 1800));
wood.makeGraphic(40, 100, FlxColor.BROWN);
add(wood);
bar1.value = (resourceGroup.members.length / maxItems) * 100;
bartxt1.text = "Loading resources... " + resourceGroup.members.length + " / " + maxItems;
bartxt1.screenCenter();
}
public function addE()
{
var enemy = new FlxSprite(FlxG.random.int(300, 2500), FlxG.random.int(300, 1800));
enemy.makeGraphic(32, 32, FlxColor.RED);
add(enemy);
bar2.value = (enemyGroup.members.length / maxItems) * 100;
bartxt2.text = "Loading enemys... " + enemyGroup.members.length + " / " + maxItems;
bartxt2.screenCenter();
}
override public function create()
{
super.create();
resourceGroup = new FlxGroup(maxItems);
enemyGroup = new FlxGroup(maxItems);
loopR = new FlxAsyncLoop(maxItems, addR);
loopE = new FlxAsyncLoop(maxItems, addE);
FlxG.camera.zoom = 0.5;
playerPos = FlxPoint.get();
ground = new FlxSprite(0, 0);
ground.makeGraphic(2500, 1800, FlxColor.GREEN);
add(ground);
player = new FlxSprite(100, 100);
player.loadGraphic(AssetPaths.n1__png);
axe = new FlxSprite(player.x + 60, player.y);
axe.loadGraphic(AssetPaths.axeR__png);
camera = new FlxCamera(0, 0, 2500, 1800);
camera.bgColor = FlxColor.TRANSPARENT;
camera.setScrollBoundsRect(0, 0, ground.width, ground.height);
FlxG.cameras.reset(camera);
camera.target = player;
if (FlxG.collide(wood, player))
FlxObject.separate(wood, player);
if (FlxG.collide(wood, enemy))
FlxObject.separate(wood, enemy);
if (FlxG.collide(enemy, player))
FlxObject.separate(enemy, player);
progressR = new FlxGroup();
bar1 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
bar1.value = 0;
bar1.screenCenter();
progressR.add(bar1);
bartxt1 = new FlxText(0, 0, FlxG.width, "Loading resources... 0 / " + maxItems);
bartxt1.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
bartxt1.screenCenter();
progressR.add(bartxt1);
progressE = new FlxGroup();
bar2 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
bar2.value = 0;
bar2.screenCenter();
progressE.add(bar2);
bartxt2 = new FlxText(0, 0, FlxG.width, "Loading enemys... 0 / " + maxItems);
bartxt2.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
bartxt2.screenCenter();
progressE.add(bartxt2);
resourceGroup.visible = false;
resourceGroup.active = false;
enemyGroup.visible = false;
enemyGroup.active = false;
add(progressR);
add(progressE);
add(resourceGroup);
add(enemyGroup);
add(loopR);
}
override public function update(elapsed:Float)
{
super.update(elapsed);
if (FlxG.keys.pressed.LEFT && move)
{
player.x -= 5;
axe.loadGraphic(AssetPaths.axeL__png);
}
if (FlxG.keys.pressed.RIGHT && move)
{
player.x += 5;
axe.loadGraphic(AssetPaths.axeR__png);
}
if (FlxG.keys.pressed.UP && move)
{
player.y -= 5;
}
if (FlxG.keys.pressed.DOWN && move)
{
player.y += 5;
}
axe.x = player.x + 60;
axe.y = player.y;
playerPos = FlxPoint.get();
playerPos = player.getMidpoint();
FlxVelocity.moveTowardsPoint(enemy, playerPos, 70);
if (!loopR.started)
{
loopR.start();
}
else
{
if (loopR.finished)
{
resourceGroup.visible = true;
progressR.visible = false;
resourceGroup.active = true;
progressR.active = false;
loopR.kill();
loopR.destroy();
add(loopE);
loopE.start();
}
}
if (loopE.finished)
{
move = true;
add(player);
add(axe);
enemyGroup.visible = true;
progressE.visible = false;
enemyGroup.active = true;
progressE.active = false;
loopE.kill();
loopE.destroy();
}
}
}
i'm showing everything because of the functions and other things that can make this problem
(my english is bad sorry if i miss something...)
Without knowing the exact error, I suspect that the problem is when you call
if (FlxG.collide(wood, player))
FlxObject.separate(wood, player);
if (FlxG.collide(wood, enemy))
FlxObject.separate(wood, enemy);
if (FlxG.collide(enemy, player))
FlxObject.separate(enemy, player);
Inside your create function - wood and enemy are declared in other functions and do not exist there.
There are a couple of things I would do differently here:
(Note: I didn't TEST this code, so there may still be problems, but this might help get you pointed in the right direction...)
class PlayState extends FlxState
{
public static var player:FlxSprite;
var ground:FlxSprite;
var axe:FlxSprite;
var base:FlxSprite;
var txt:FlxText;
var playerPos:FlxPoint;
var move:Bool = false;
var progressR:FlxGroup;
var progressE:FlxGroup;
var resourceGroup:FlxTypedGroup<FlxSprite>;
var enemyGroup:FlxTypedGroup<FlxSprite>;
var maxItems:Int = 100;
var bar1:FlxBar;
var bartxt1:FlxText;
var bar2:FlxBar;
var bartxt2:FlxText;
var loopR:FlxAsyncLoop;
var loopE:FlxAsyncLoop;
public function addR()
{
var wood = new FlxSprite(FlxG.random.int(100, 2500), FlxG.random.int(100, 1800));
wood.makeGraphic(40, 100, FlxColor.BROWN);
resourceGroup.add(wood);
bar1.value = (resourceGroup.members.length / maxItems) * 100;
bartxt1.text = "Loading resources... " + resourceGroup.members.length + " / " + maxItems;
bartxt1.screenCenter();
FlxG.collide(player, resourceGroup) // should not need to call `seperate` - it's automatic when using `collide` vs `overlap`
}
public function addE()
{
var enemy = new FlxSprite(FlxG.random.int(300, 2500), FlxG.random.int(300, 1800));
enemy.makeGraphic(32, 32, FlxColor.RED);
enemyGroup.add(enemy);
FlxG.collide(enemyGroup, resourceGroup)
FlxG.collide(player, resourceGroup)
bar2.value = (enemyGroup.members.length / maxItems) * 100;
bartxt2.text = "Loading enemys... " + enemyGroup.members.length + " / " + maxItems;
bartxt2.screenCenter();
}
override public function create()
{
super.create();
resourceGroup = new FlxTypedGroup<FlxSprite>(maxItems);
enemyGroup = new FlxTypedGroup<FlxSprite>(maxItems);
loopR = new FlxAsyncLoop(maxItems, addR);
loopE = new FlxAsyncLoop(maxItems, addE);
FlxG.camera.zoom = 0.5;
playerPos = FlxPoint.get();
ground = new FlxSprite(0, 0);
ground.makeGraphic(2500, 1800, FlxColor.GREEN);
add(ground);
player = new FlxSprite(100, 100);
player.loadGraphic(AssetPaths.n1__png);
axe = new FlxSprite(player.x + 60, player.y);
axe.loadGraphic(AssetPaths.axeR__png);
camera = new FlxCamera(0, 0, 2500, 1800);
camera.bgColor = FlxColor.TRANSPARENT;
camera.setScrollBoundsRect(0, 0, ground.width, ground.height);
FlxG.cameras.reset(camera);
camera.target = player;
progressR = new FlxGroup();
bar1 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
bar1.value = 0;
bar1.screenCenter();
progressR.add(bar1);
bartxt1 = new FlxText(0, 0, FlxG.width, "Loading resources... 0 / " + maxItems);
bartxt1.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
bartxt1.screenCenter();
progressR.add(bartxt1);
progressE = new FlxGroup();
bar2 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
bar2.value = 0;
bar2.screenCenter();
progressE.add(bar2);
bartxt2 = new FlxText(0, 0, FlxG.width, "Loading enemys... 0 / " + maxItems);
bartxt2.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
bartxt2.screenCenter();
progressE.add(bartxt2);
resourceGroup.visible = false;
resourceGroup.active = false;
enemyGroup.visible = false;
enemyGroup.active = false;
add(progressR);
add(progressE);
add(resourceGroup);
add(enemyGroup);
add(loopR);
}
public function gamePlay(elapsed:Float):Void
{
if (FlxG.keys.pressed.LEFT && move)
{
player.x -= 5; // why +/- position and not .velocity?
// THIS is probably not right - you want to use a sprite sheet with animations and call axe.play("left") or something...
axe.loadGraphic(AssetPaths.axeL__png);
}
if (FlxG.keys.pressed.RIGHT && move)
{
player.x += 5;
axe.loadGraphic(AssetPaths.axeR__png);
}
if (FlxG.keys.pressed.UP && move)
{
player.y -= 5;
}
if (FlxG.keys.pressed.DOWN && move)
{
player.y += 5;
}
axe.x = player.x + 60;
axe.y = player.y;
playerPos = FlxPoint.get();
playerPos = player.getMidpoint();
for (e in enemyGroup)
{
FlxVelocity.moveTowardsPoint(e, playerPos, 70);
}
}
public function loading(elapsed:Float):Void
{
if (!loopR.started)
{
loopR.start();
}
else if (loopR.finished)
{
resourceGroup.visible = true;
progressR.visible = false;
resourceGroup.active = true;
progressR.active = false;
loopR.kill();
loopR.destroy();
add(loopE);
loopE.start();
}
else if (loopE.finished)
{
move = true;
add(player);
add(axe);
enemyGroup.visible = true;
progressE.visible = false;
enemyGroup.active = true;
progressE.active = false;
loopE.kill();
loopE.destroy();
}
}
override public function update(elapsed:Float)
{
super.update(elapsed);
if (!move)
{
loading(elapsed);
}
else
{
gamePlay(elapsed);
}
}
}

dynamically change an image via c# script in Xamarin forms

I have a cross platform app which I need to show a set of images when the user clic in a button, so, I put these image files named as "img000.png" to "img029.png" in a folder in the PCL solution and make al these images as "EmbeddedResource", after,I fill a List with all these images and its work fine at now, i.e. the image is shown like I want, but when I click in the button to show the next image in the list the image don't go to the next.
I have this:
//...
public class ImageSetPage : BasePage
// BasePage encapsule a ContentPage...
{
private string directory = "MyApp.Assets.";
private int idx = 0;
protected StackLayout _mainLayout;
protected StackLayout _buttonStack;
protected Image _btnPrevI;
protected Label _displayName;
protected Image _btnNestI;
protected Image _image;
protected List<Image> _Images;
public ImageSetPage()
{
this._Images = getImages();
var prevI_Tap = new TapGestureRecognizer();
prevI_Tap.Tapped += (s, e) =>
{
onClick("pvi");
};
var nextI_Tap = new TapGestureRecognizer();
nextI_Tap.Tapped += (s, e) =>
{
onClick("nti");
};
/// begin layout
base.Title = "set of Images";
this._mainLayout = new StackLayout()
{
Orientation = StackOrientation.Vertical,
BackgroundColor = Color.Black,
Padding = new Thickness(0, 10, 0, 0)
};
this._btnPrevI = new Image()
{
Aspect = Aspect.AspectFill,
Source = ImageSource.FromResource(directory+"prevbtn.png")
};
_btnPrevI.GestureRecognizers.Add(prevI_Tap);
this._displayName = new Label()
{
Style = Device.Styles.SubtitleStyle,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
TextColor = Color.White,
};
this._btnNextI = new Image()
{
Aspect = Aspect.AspectFill,
Source = ImageSource.FromResource(directory + "nextbtn.png")
};
_btnNextI.GestureRecognizers.Add(nextI_Tap);
this._buttonStack.Children.Add(_btnPrevI);
this._buttonStack.Children.Add(_displayName);
this._buttonStack.Children.Add(_btnNextI);
this._mainLayout.Children.Add(_buttonStack);
FillImage(idx);
this._mainLayout.Children.Add(this._image);
this.Content = this._mainLayout;
}
private void FillImage(int i)
{
this._displayName.Text = "Image n# " + FillWithZeroes(i);
// [EDIT 1] cemented these lines ...
// this._image = null;
// mi = _images[i];
// this._image = mi;
// [EDIT 2] the new try
string f = directory + "imgs.img0" + FillWithZeroes(i) + ".png";
this._image = new Image() {
VerticalOptions = LayoutOptions.Center,
Soruce = ImageSource.FromResource(f)
};
// In this way the image show and don't change when click
// this Fking* code is a big S_OF_THE_B*
// The Xamarin and the C# is brothers of this FKing* code
}
private void onClick(string v)
{
string vw = v;
if (vw.Equals("pvi")) idx--;
if (vw.Equals("nti")) idx++;
if (idx <= 0) idx = 29;
if (idx >= 29) idx = 0;
FillImage(idx);
vw = "";
}
private string FillWithZeroes(int v)
{
string s = v.ToString();
string r = "";
if (s.Length == 1) { r = "0" + s; } else { r = s; }
return r;
}
// to fill a list of Images with files in a PCL folder
private List<Image> getImages()
{
string directory = "MyApp.Assets.";
List<Image> imgCards = new List<Image>();
int c = 0;
for (c = 0; c < 30;c++) {
string f = directory + "imgs.img0" + FillWithZeroes(c) + ".png";
Image img = new Image();
img.Source = ImageSource.FromResource(f);
imgCards.Add(img);
}
return imgCards;
}
// ...
}
but the image don't change, i.e. change, like I see in debug, but don't show in the Layout when I click in the buttons.
Maybe I'm doing it wrong.
Can someone here help me?
thanks in advance

Binding Scene size properties to Stage JavaFX

I need to adjust the size of a Scene to the current size of the Stage/Window.
Currently when I resize the Stage/Window the Scene resizes as well, but not to the same size. The Scene contains a StackPane.
I looked for a way to bind but didn't find anything, setters for the size parameters of the Scene also aren't available it seems. Does anyone know a way to get this done?
EDIT: Here's the Code of my Class atm.
public class SimpleSun extends Application {
// Controls
Label lblPos = new Label();
Stage primaryStage;
List<Visibility> vislist;
Scene scene;
Rectangle rect;
Circle circle;
Line line1;
Line line2;
// Variables
private double sunDiameter = 700;
private Integer center = 400;
int fovrad = 80;
int fovpxl = calculatePixelsFromRad(fovrad);
/**
* #param args
* the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
#SuppressWarnings("static-access")
#Override
public void start(final Stage stage) {
// Initialize Containers
this.primaryStage = stage;
primaryStage.setTitle("0.1-alpha -- Sun Simulation");
BorderPane root = new BorderPane();
scene = new Scene(root, 800, 800);
StackPane sp = new StackPane();
// Paint Graphics
rect = new Rectangle(center - fovpxl / 2, center - fovpxl / 2, fovpxl,
fovpxl);
circle = new Circle(400, 400, 350);
line1 = new Line(0, 0, 0, scene.getHeight());
line2 = new Line(0, 0, scene.getHeight(), 0);
// Insert Controls
sp.getChildren().addAll(circle, line1, line2, lblPos, rect);
sp.setAlignment(lblPos, Pos.TOP_LEFT);
lblPos.setStyle("margin-top:10px");
root.setCenter(sp);
primaryStage.setScene(scene);
// Binding Circle size to stage & Scene size to Stage
circle.radiusProperty().bind(
primaryStage.widthProperty().divide(2).subtract(50));
circle.centerXProperty().bind(primaryStage.widthProperty().divide(2));
circle.centerYProperty().bind(primaryStage.widthProperty().divide(2));
// Assign Handlers
line1.setOnMouseClicked(mouseHandler);
line1.setOnMouseMoved(mouseHandler);
line2.setOnMouseClicked(mouseHandler);
line2.setOnMouseMoved(mouseHandler);
circle.setOnMouseClicked(mouseHandler);
circle.setOnMouseMoved(mouseHandler);
rect.setOnMouseClicked(mouseHandler);
rect.setOnMouseMoved(mouseHandler);
scene.widthProperty().addListener(cListener);
scene.heightProperty().addListener(cListener);
// Properties
circle.setFill(Color.YELLOW);
circle.setStroke(Color.BLACK);
rect.setFill(null);
rect.setStroke(Color.BLACK);
primaryStage.show();
}
EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getEventType() == MouseEvent.MOUSE_CLICKED) {
int x = (int) mouseEvent.getSceneX();
int y = (int) mouseEvent.getSceneY();
DoubleMatrix1D pCoords = calculateXYRad(x, y);
final ISource p = new GaussianRadialSource(pCoords.get(0),
pCoords.get(1), 1, 1, 0);
MainSimulation.runSim(p, fovrad);
// DEBUG
// String message = "Source Position: " + mouseEvent.getSceneX()
// + " / " + mouseEvent.getSceneY();
// System.out.println(message);
} else if (mouseEvent.getEventType() == MouseEvent.MOUSE_MOVED) {
int x = (int) mouseEvent.getSceneX();
int y = (int) mouseEvent.getSceneY();
if (mouseEvent.getSource().getClass().equals(Circle.class)) {
((Circle) mouseEvent.getSource())
.setCursor(Cursor.CROSSHAIR);
} else if (mouseEvent.getSource().getClass().equals(Line.class)) {
((Line) mouseEvent.getSource()).setCursor(Cursor.CROSSHAIR);
} else if (mouseEvent.getSource().getClass()
.equals(Rectangle.class)) {
((Rectangle) mouseEvent.getSource())
.setCursor(Cursor.CROSSHAIR);
}
DoubleMatrix1D pCoords = calculateXYRad(x, y);
// Adjust label to new cursor position
lblPos.setText((pCoords.get(0) + " :: " + pCoords.get(1)));
// DEBUG
System.out.println("x: " + pCoords.get(0) + ", y: "
+ pCoords.get(1));
}
}
};
ChangeListener<? super Number> cListener = new ChangeListener<Number>() {
public void changed(ObservableValue<? extends Number> scenewidth,
Number oldValue, Number newValue) {
// System.out.println(primaryStage.getHeight());
// Adjust Size of Window instead of binding
if (primaryStage.getHeight() < primaryStage.getWidth()) {
primaryStage.setWidth(primaryStage.getHeight());
center = (int) (primaryStage.getHeight() / 2);
sunDiameter = primaryStage.getHeight() - 100;
}
if (primaryStage.getWidth() < primaryStage.getHeight()) {
primaryStage.setHeight(primaryStage.getWidth());
center = (int) (primaryStage.getWidth() / 2);
sunDiameter = primaryStage.getWidth() - 100;
}
// Adjust Center and Sun Diameter to new Window Size
repaintSimpleSun();
System.out.println(primaryStage.getWidth() + " " + primaryStage.getHeight());
System.out.println(scene.getWidth() + " " + scene.getHeight());
System.out.println(center + " " + sunDiameter);
}
};
private DoubleMatrix1D calculateXYRad(int x, int y) {
double X = ((x - center) * (Units.SUN_HALF_DIAMETER_RAD * 2.0) / sunDiameter);
double Y = ((y - center) * (Units.SUN_HALF_DIAMETER_RAD * 2.0) / sunDiameter);
return DoubleFactory1D.dense.make(new double[] { X, Y });
}
private int calculatePixelsFromRad(int rad) {
int pixels = (int) ((sunDiameter) / (Units.SUN_HALF_DIAMETER_RAD * 2) * rad);
// System.out.println(pixels);
return pixels;
}
private void repaintSimpleSun() {
fovpxl = calculatePixelsFromRad(fovrad);
rect.setHeight(fovpxl);
rect.setWidth(fovpxl);
rect.setX(center - (fovpxl / 2));
rect.setY(center - (fovpxl / 2));
line1.setEndY(primaryStage.getWidth());
line2.setEndX(primaryStage.getHeight());
}
}

JFreechart multiline Label on Symbolaxis or other way to align charts

i have a lot of charts, each in a different JInternalFrame:
But the horizontal axis should be aligned to the same point(maybe the red line). The problem is, that the space for the label is set automatically by jFreechart.
So i tried to find a solution for multiline ticklabels. I found this:
int optionsCount = state.getStatusOptions().toArray().length;
String[] grade = new String[optionsCount + 1];
grade[0] = "";
for (int x = 1; x < optionsCount + 1; x++) {
//grade[x] ="blaa"+x;//state.getStatusOptions().get(x - 1);
//grade[x]="1.line\n2.line\n3.line";
grade[x] = newLineString(state.getStatusOptions().get(x - 1), 5);
}
// grade[1]="1.line\n2.line";
SymbolAxis rangeAxis;
rangeAxis = new SymbolAxis("", grade){
#Override
protected Rectangle2D getLabelEnclosure(Graphics2D g2, RectangleEdge edge) {
Rectangle2D l = super.getLabelEnclosure(g2, edge);
l.setRect(l.getX(),l.getY(),l.getWidth()*0.5,l.getHeight());
return l;
}
#Override
protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge) {
AxisState state = new AxisState(cursor);
if (isAxisLineVisible()) {
drawAxisLine(g2, cursor, dataArea, edge);
}
double ol = getTickMarkOutsideLength();
double il = getTickMarkInsideLength();
List ticks = refreshTicks(g2, state, dataArea, edge);
state.setTicks(ticks);
g2.setFont(getTickLabelFont());
Iterator iterator = ticks.iterator();
// remember the max number of lines used in any label
int maxLinesUsed = 0;
while (iterator.hasNext()) {
ValueTick tick = (ValueTick) iterator.next();
if (isTickLabelsVisible()) {
g2.setPaint(getTickLabelPaint());
float[] anchorPoint = calculateAnchorPoint(tick, cursor, dataArea, edge);
g2.draw(plotArea);
g2.setPaint(Color.green);
g2.draw(dataArea);
g2.setPaint(getTickLabelPaint());
// split by "\n" and draw text in a new line for each result
String tickText = tick.getText();
int line = 1;
for (String tickTextLine : tickText.split("\n")) {
float x = anchorPoint[0];
// one row down...
float y = anchorPoint[1] + line * g2.getFont().getSize();
TextUtilities.drawRotatedString(tickTextLine, g2, x, y, tick.getTextAnchor(), tick.getAngle(), tick
.getRotationAnchor());
line++;
}
// if we used more lines than any time before remember it
if (line > maxLinesUsed) {
maxLinesUsed = line;
}
}
if (isTickMarksVisible() && tick.getTickType().equals(TickType.MAJOR)) {
float xx = (float) valueToJava2D(tick.getValue(), dataArea, edge);
Line2D mark = null;
g2.setStroke(getTickMarkStroke());
g2.setPaint(getTickMarkPaint());
if (edge == RectangleEdge.LEFT) {
mark = new Line2D.Double(cursor - ol, xx, cursor + il, xx);
} else if (edge == RectangleEdge.RIGHT) {
mark = new Line2D.Double(cursor + ol, xx, cursor - il, xx);
} else if (edge == RectangleEdge.TOP) {
mark = new Line2D.Double(xx, cursor - ol, xx, cursor + il);
} else if (edge == RectangleEdge.BOTTOM) {
mark = new Line2D.Double(xx, cursor + ol, xx, cursor - il);
}
g2.draw(mark);
}
}
// need to work out the space used by the tick labels...
// so we can update the cursor...
// patched using maxLinesUsed => we need more space because of multiple lines
double used = 0.0;
if (isTickLabelsVisible()) {
if (edge == RectangleEdge.LEFT) {
used += findMaximumTickLabelWidth(ticks, g2, plotArea, isVerticalTickLabels()) * maxLinesUsed;
state.cursorLeft(used);
} else if (edge == RectangleEdge.RIGHT) {
used = findMaximumTickLabelWidth(ticks, g2, plotArea, isVerticalTickLabels()) * maxLinesUsed;
state.cursorRight(used);
} else if (edge == RectangleEdge.TOP) {
used = findMaximumTickLabelHeight(ticks, g2, plotArea, isVerticalTickLabels()) * maxLinesUsed;
state.cursorUp(used);
} else if (edge == RectangleEdge.BOTTOM) {
used = findMaximumTickLabelHeight(ticks, g2, plotArea, isVerticalTickLabels()) * maxLinesUsed;
state.cursorDown(used);
}
}
return state;
}
};
As you can see in the picture above, the new line function works, but the spacing for the labels does not work. I tried to override the getLabelEnclosure method, but its given string is just "".
Does anyone know a solution for my problem. Either the multiline or an other way to align the charts?
thanks!
Override the reserveSpace function and in the place where the height is calculated modify it with the number of rows you need:
Rectangle2D labelEnclosure = getLabelEnclosure(g2, edge);
if (RectangleEdge.isTopOrBottom(edge)) {
double labelHeight = labelEnclosure.getHeight();
space.add(labelHeight + **YOUR_NUMBER_OF_ROWS** * tickLabelHeight, edge);
} else if (RectangleEdge.isLeftOrRight(edge)) {
double labelWidth = labelEnclosure.getWidth();
space.add(labelWidth + tickLabelWidth, edge);
}
return space;

Resources