Why I don't get error and application doesn't open - android-studio

Why Android Studio doesn't detect error but when I try to open the app on mobile device it doesn't open.
It only opens if I comment these 2 lines in the Activity but of course I don't get full functionality. Am I missing something?
Commented lines
spinner.findViewById(R.id.spinnerCountries);
spinner.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item,CountryData.countryNames));
*Activity.java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.FirebaseAuth;
public class RegisterActivity extends AppCompatActivity {
private Spinner spinner;
private EditText editText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
spinner.findViewById(R.id.spinnerCountries);
spinner.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item,CountryData.countryNames));
editText = findViewById(R.id.editTextPhone);
findViewById(R.id.buttonContinue).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String code = CountryData.countryAreaCodes[spinner.getSelectedItemPosition()];
String number = editText.getText().toString().trim();
if (number.isEmpty() || number.length() < 10){
editText.setError("Valid number is required");
editText.requestFocus();
return;
}
String phonenumber = "+" + code + number;
Intent intent = new Intent (RegisterActivity.this,OtpActivity.class);
intent.putExtra("phonenumber",phonenumber);
startActivity(intent);
}
});
}
#Override
protected void onStart() {
super.onStart();
if (FirebaseAuth.getInstance().getCurrentUser() !=null) {
Intent intent = new Intent (this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
}
}
This is the file which I am trying to connect to the Activity
CountryData.java
public class CountryData {
public static final String[] countryNames =
{"Afghanistan", "Albania",
"Algeria", "Andorra", "Angola", "Antarctica", "Argentina",
"Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
"Bahrain", "Bangladesh", "Belarus", "Belgium", "Belize", "Benin",
"Bhutan", "Bolivia", "Bosnia And Herzegovina", "Botswana",
"Brazil", "Brunei Darussalam", "Bulgaria", "Burkina Faso",
"Myanmar", "Burundi", "Cambodia", "Cameroon", "Canada",
"Cape Verde", "Central African Republic", "Chad", "Chile", "China",
"Christmas Island", "Cocos (keeling) Islands", "Colombia",
"Comoros", "Congo", "Cook Islands", "Costa Rica", "Croatia",
"Cuba", "Cyprus", "Czech Republic", "Denmark", "Djibouti",
"Timor-leste", "Ecuador", "Egypt", "El Salvador",
"Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia",
"Falkland Islands (malvinas)", "Faroe Islands", "Fiji", "Finland",
"France", "French Polynesia", "Gabon", "Gambia", "Georgia",
"Germany", "Ghana", "Gibraltar", "Greece", "Greenland",
"Guatemala", "Guinea", "Guinea-bissau", "Guyana", "Haiti",
"Honduras", "Hong Kong", "Hungary", "India", "Indonesia", "Iran",
"Iraq", "Ireland", "Isle Of Man", "Israel", "Italy", "Ivory Coast",
"Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati",
"Kuwait", "Kyrgyzstan", "Laos", "Latvia", "Lebanon", "Lesotho",
"Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
"Macao", "Macedonia", "Madagascar", "Malawi", "Malaysia",
"Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania",
"Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
"Monaco", "Mongolia", "Montenegro", "Morocco", "Mozambique",
"Namibia", "Nauru", "Nepal", "Netherlands", "New Caledonia",
"New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue", "Korea",
"Norway", "Oman", "Pakistan", "Palau", "Panama",
"Papua New Guinea", "Paraguay", "Peru", "Philippines", "Pitcairn",
"Poland", "Portugal", "Puerto Rico", "Qatar", "Romania",
"Russian Federation", "Rwanda", "Saint Barthélemy", "Samoa",
"San Marino", "Sao Tome And Principe", "Saudi Arabia", "Senegal",
"Serbia", "Seychelles", "Sierra Leone", "Singapore", "Slovakia",
"Slovenia", "Solomon Islands", "Somalia", "South Africa",
"Korea, Republic Of", "Spain", "Sri Lanka", "Saint Helena",
"Saint Pierre And Miquelon", "Sudan", "Suriname", "Swaziland",
"Sweden", "Switzerland", "Syrian Arab Republic", "Taiwan",
"Tajikistan", "Tanzania", "Thailand", "Togo", "Tokelau", "Tonga",
"Tunisia", "Turkey", "Turkmenistan", "Tuvalu",
"United Arab Emirates", "Uganda", "United Kingdom", "Ukraine",
"Uruguay", "United States", "Uzbekistan", "Vanuatu",
"Holy See (vatican City State)", "Venezuela", "Viet Nam",
"Wallis And Futuna", "Yemen", "Zambia", "Zimbabwe"};
public static final String[] countryAreaCodes = {"93", "355", "213",
"376", "244", "672", "54", "374", "297", "61", "43", "994", "973",
"880", "375", "32", "501", "229", "975", "591", "387", "267", "55",
"673", "359", "226", "95", "257", "855", "237", "1", "238", "236",
"235", "56", "86", "61", "61", "57", "269", "242", "682", "506",
"385", "53", "357", "420", "45", "253", "670", "593", "20", "503",
"240", "291", "372", "251", "500", "298", "679", "358", "33",
"689", "241", "220", "995", "49", "233", "350", "30", "299", "502",
"224", "245", "592", "509", "504", "852", "36", "91", "62", "98",
"964", "353", "44", "972", "39", "225", "1876", "81", "962", "7",
"254", "686", "965", "996", "856", "371", "961", "266", "231",
"218", "423", "370", "352", "853", "389", "261", "265", "60",
"960", "223", "356", "692", "222", "230", "262", "52", "691",
"373", "377", "976", "382", "212", "258", "264", "674", "977",
"31", "687", "64", "505", "227", "234", "683", "850", "47", "968",
"92", "680", "507", "675", "595", "51", "63", "870", "48", "351",
"1", "974", "40", "7", "250", "590", "685", "378", "239", "966",
"221", "381", "248", "232", "65", "421", "386", "677", "252", "27",
"82", "34", "94", "290", "508", "249", "597", "268", "46", "41",
"963", "886", "992", "255", "66", "228", "690", "676", "216", "90",
"993", "688", "971", "256", "44", "380", "598", "1", "998", "678",
"39", "58", "84", "681", "967", "260", "263"};
}

Related

How to change the state of the checkbox in the drop-down list?

I study flutter and make a simple application with a drop-down list and checkboxes, as shown in the picture. But it is not possible to achieve a change in the status of checkboxes.
Many different options reviewed, I did following the example. Most likely the problem is in the EntryItem class constructor, because when creating an entry instance, its children child element is called as null, writes the error "The getter 'children' was called on null."
Here is the code I'm currently working with:
import 'package:flutter/material.dart';
// run app
void main() => runApp(new ExpansionTileSample());
class ExpansionTileSample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('ExpansionTile'),
),
body: new ListView.builder(
itemBuilder: (BuildContext context, int index) => new EntryItem(data[index]),
itemCount: data.length,
),
),
);
}
}
class EntryItem extends StatefulWidget {
// Entry entry;
EntryItem(Entry entry);
#override
_EntryItemState createState() {
return new _EntryItemState();
}
}
class _EntryItemState extends State<EntryItem> {
Entry entry;
Widget _buildTiles(Entry root) {
if (root.children.isEmpty)
return new Column(
children: <Widget>[
new CheckboxListTile(
title: new Text(
root.title,
style: new TextStyle(fontSize: 14.0),
),
value: entry.isCheck,
onChanged: (bool value) {
setState(() {
entry.isCheck = value;
});
},
),
new Divider(height: 16.0, indent: 0.0),
],
);
// return new Divider();
return new ExpansionTile(
key: new PageStorageKey<Entry>(root),
title: new Text(root.title),
children: root.children.map(_buildTiles).toList(),
);
}
#override
Widget build(BuildContext context) {
return _buildTiles(entry);
}
}
// One entry in the multilevel list displayed by this app.
class Entry {
Entry(this.isCheck, this.title, [this.children = const <Entry>[]]);
final String title;
List<Entry> children;
bool isCheck;
}
// The entire multilevel list displayed by this app.
List<Entry> data = <Entry>[
new Entry(false,
' Компетентность',
<Entry>[
new Entry(false,
'Опыт работы и практические знания',
<Entry>[
new Entry(false,"Обладает исключительно большим опытом работы, большими практическими знаниями, такой опыт и такова практика имеются далеко не у каждого."),
new Entry(false,"Обладает большим опытом работы и большими практическими знаниями."),
new Entry(false,"Обладает достаточным опытом работы и практическими знаниями, чтобы успешно справляться с порученным делом."),
new Entry(false,"Опыт работы и практические знания несколько маловаты."),
new Entry(false,"Опыт работы и практические знания недостаточны для того, чтобы успешно справляться со своей работой."),
]),
new Entry(false,'Знания по специальности', <Entry>[
new Entry(false,"Имеет обширные и глубокие знания по своей специальности, широкую общую эрудицию в служебных вопросах. Умело использует свои знания в повседневной работе, может давать ценные консультации."),
new Entry(false,"Имеет обширные и глубокие знания по своей специальности, может дать ценную консультацию. Однако, вопросах деятельности других служб ориентируется недостаточно."),
new Entry(false,"Имеет хорошие знания по своей специальности, достаточную эрудицию в других служебных вопросах."),
new Entry(false,"Имеет достаточные знания по своей специальности, однако в других служебных вопросах разбирается меньше."),
new Entry(false,"Имеет достаточные знания по своей специальности, но совершенно отсутствует осведомленность по другим служебным вопросам."),
new Entry(false,"Явно не достает знаний по своей специальности и совершенно отсутствует осведомленность в других вопросах."),
]),
new Entry(false,'Самостоятельность', <Entry>[
new Entry(false,"Может решать все вопросы, касавшиеся своей работы, совершенно самостоятельно, не ожидая чьей-либо подсказки или указания."),
new Entry(false,"В основном может решать большинство вопросов, касающихся своей работы, самостоятельно, не ожидая подсказки или указания."),
new Entry(false,"Может решать многие вопросы, касающиеся своей работы, более или менее самостоятельно."),
new Entry(false,"Многие вопросы, связанные со своей работой, не может решать самостоятельно, нуждается в известной помощи, подсказках и указаниях."),
new Entry(false,"Вопросы, связанные со своей работой, не может решать самостоятельно, нуждается в помощи, подсказках и указаниях."),
new Entry(false,"Не может решать самостоятельно даже самые простые вопросы, связанные со своей собственной работой, постоянно нуждается в помощи, подсказках и указаниях."),
]),
new Entry(false,'Самообразование', <Entry>[
new Entry(false,"Постоянно, много и упорно занимается самообразованием по своей специальности и это очень положительно сказывается на работе."),
new Entry(false,"Много и упорно занимается самообразованием по своей специальности и это заметно сказывается на улучшении работы."),
new Entry(false,"Успешно сочетает работу с самообразованием по своей специальности."),
new Entry(false,"Понимает пользу самообразования и по мере возможности стремится пополнить свои знания по избранной специальности."),
new Entry(false,"Признает на словах необходимость самообразования, однако, никаких успехов в этом не заметно."),
new Entry(false,"Отрицает необходимость самообразования, что не приносит пользы, делу."),
]),
],
),
new Entry(false,
'Работоспособность',
<Entry>[
new Entry(false,'Результативность', <Entry>[
new Entry(false,"В своей работе постоянно добивается высоких результатов, своим примером воодушевляет коллег."),
new Entry(false,"В своей работе постоянно добивается хороших результатов, вносит важный вклад в работу коллектива."),
new Entry(false,"Работает ровно, без срывов, трудовая отдача соответствует предъявленным требованиям."),
new Entry(false,"Работает неровно, наряду с успехами в служебной деятельности бывают и отдельные срывы."),
new Entry(false,"Работает недостаточно интенсивно, не всегда добивается требуемых результатов, иногда допускает серьезные срывы."),
new Entry(false,"Работает плохо. Результаты работы хронически не отвечают предъявленным требованиям."),
]),
new Entry(false,'Отношение к работе', <Entry>[
new Entry(false,"Очень любит свою работу, практически уделяет ей все свое свободное время и энергию."),
new Entry(false,"Любит свою работу."),
new Entry(false,"К своей работе относится добросовестно."),
new Entry(false,"К своей работе относится равнодушно."),
new Entry(false,"Не любит свою работу, но выполняет ее добросовестно."),
new Entry(false,"Крайне не любит свою работу и повсюду говорит об этом."),
]),
new Entry(false,'Интенсивность работы', <Entry>[
new Entry(false,"В работе показывает очень высокую интенсивность, способность работать за пятерых."),
new Entry(false,"В работе показывает высокую интенсивность."),
new Entry(false,"В работе показывает достаточную интенсивность."),
new Entry(false,"В работе показывает недостаточную интенсивность."),
new Entry(false,"В работе показывает низкую интенсивность."),
new Entry(false,"В работе показывает крайне низкую интенсивность, нуждается в постоянном понукании."),
]),
],
),
new Entry(false,
'Деловитость',
<Entry>[
new Entry(false,'Соблюдение сроков', <Entry>[
new Entry(false,'Всегда все делает вовремя, всегда укладывается в срок, в связи с этим можно совершенно не беспокоиться.'),
new Entry(false,'Обычно все делает вовремя и укладывается в срок - можно положиться.'),
new Entry(false,'В основном порученные задания выполняет в срок и других товарищей не подводит.'),
new Entry(false,'Не всегда выполняет порученную работу вовремя, иногда не укладывается в срок, но в особо ответственных случаях старается не подводить других товарищей.'),
new Entry(false,'Часто при выполнении порученных заданий не укладывается в срок и подводит этим других товарищей.'),
new Entry(false,'Постоянно не укладывается в срок и подводит этим других товарищей, на такого человека совершенно невозможно положиться.'),
]),
new Entry(false,'Качество работы', <Entry>[
new Entry(false,'Работает практически всегда без ошибок.'),
new Entry(false,'Работает, в основном, без ошибок, если и допускает ошибки в работе, то они не отражаются на конечных результатах.'),
new Entry(false,'Редко допускает в работе ошибки, как правило, лишь незначительные.'),
new Entry(false,'Допускает в работе ошибки, и иногда это сказывается на конечных результатах.'),
new Entry(false,'Часто допускает в работе ошибки, в тон числе и довольно грубые.'),
new Entry(false,'Постоянно допускает в работе грубейшие ошибки.'),
]),
new Entry(false,'Отношение к нововведениям',
<Entry>[
new Entry(false,'Любит различные нововведения и реорганизации. Но не любит работать в нормальном спокойном режиме.'),
new Entry(false,'Порой излишне увлекается различными новшествами и реорганизациями в ущерб текущей работе.'),
new Entry(false,'Стремится вовремя поддержать любое начинание.'),
new Entry(false,'Может поддержать полезное назначение, хотя не особенно любит различные нововведения и реорганизации.'),
new Entry(false,'Порой проявляет изливший консерватизм, не любит различных нововведений и реорганизаций.'),
new Entry(false,'Проявляет крайний консерватизм, выступает против всякого нововведения.'),
],
),
],
),
];
The main problem in you code is, You are passing an object to EntryItem(data[index]) but there is no constructor.
Replace your below code of "EntryItem" Class
class EntryItem extends StatefulWidget {
// Entry entry;
EntryItem(Entry entry);
#override
_EntryItemState createState() {
return new _EntryItemState();
}
}
With this:
class EntryItem extends StatefulWidget {
Entry entry;
EntryItem(Entry entry){
this.entry=entry;
}
#override
_EntryItemState createState() {
return new _EntryItemState(entry);
}
}
And add below constructor to _EntryItemState class:
...
_EntryItemState(Entry entry){
this.entry = entry;
}
...
And your error will be gone.

RESTKit: Duplicate Objects in relationship after POST

Below is my setup:
- (RKManagedObjectStore *)setupCoreDataWithRESTKit
{
NSError * error;
NSURL * modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"App" ofType:#"momd"]];
NSManagedObjectModel * managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
self.managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
[self.managedObjectStore createPersistentStoreCoordinator];
NSArray * searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentPath = [searchPaths objectAtIndex:0];
NSPersistentStore * persistentStore = [self.managedObjectStore addSQLitePersistentStoreAtPath:[NSString stringWithFormat:#"%#/App%#.sqlite", documentPath, [TBSPersistence username]] fromSeedDatabaseAtPath:nil withConfiguration:nil options:[self optionsForSqliteStore] error:&error];
NSAssert(persistentStore, #"Failed to add persistent store with error: %#", error);
NSLog(#"Path: %#", [NSString stringWithFormat:#"%#/App%#.sqlite", documentPath, [TBSPersistence username]]);
if(!persistentStore){
NSLog(#"Failed to add persistent store: %#", error);
}
[self.managedObjectStore createManagedObjectContexts];
return self.managedObjectStore;
}
POST Invite -- Invite has a to-many relationship with Activity::
-(void)sendInvite:(NSInteger)methodType
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
self.objectManager = [self getObjectManager];
self.objectManager.managedObjectStore = appDelegate.managedObjectStore;
RKEntityMapping *invitationMapping = [RKEntityMapping mappingForEntityForName:kInvite
inManagedObjectStore:self.objectManager.managedObjectStore];
RKEntityMapping *activityMapping = [RKEntityMapping mappingForEntityForName:kActivity
inManagedObjectStore:self.objectManager.managedObjectStore];
Invite *invitation;
invitationMapping = [RESTMappingProvider invitionPostMapping:invitationMapping];
invitationMapping.identificationAttributes = #[#"inviteId"];
activityMapping = [RESTMappingProvider activityPostMapping:activityMapping];
activityMapping.identificationAttributes = #[#"activityId"];
[invitationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:kActivitiesRelationship
toKeyPath:kActivitiesRelationship
withMapping:activityMapping]];
invitation = [self setupInviteProperties:STPOST];
[self setupDescriptors:invitationMapping andKeyPath:kKeyPath descriptorClass:0];
[self.objectManager.HTTPClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[self.objectManager postObject:invitation path:kKeyPath parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
}
}
Descriptor:
-(void)setupDescriptors:(RKEntityMapping *)invitationMapping andKeyPath:(NSString *)keyPath descriptorClass:(BOOL)isTemplate
{
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[invitationMapping inverseMapping] objectClass:[Invite class] rootKeyPath:nil method:RKRequestMethodAny];
NSIndexSet *statusCodeSet = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:invitationMapping
method:RKRequestMethodGET
pathPattern:keyPath
keyPath:nil
statusCodes:statusCodeSet];
self.objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[self.objectManager addRequestDescriptor:requestDescriptor];
[self.objectManager addResponseDescriptor:responseDescriptor];
}
I POST just fine. When I get a Response, I get the assigned ID's, for the created objects in the database, back from the server.
POSTING: #"inviteId" : #"0" #"activityId" : #"0"
In response, I get everything back as POSTED, however, the server issues Real IDs.
RESPONSE: #"inviteId" : #"123456" #"activityId" : #"234567"
Problem:
invite Object gets updated with the assigned ID auto-magically; however, the activity objects become duplicates in CoreData (.sqlite) with one of the duplicate will have #"0" as the activityID, while its duplicate will have the assigned Id #"234567"
Later when I GET, only the assigned Id object (#"234567") get updated. Objects with#"0"` Id's are never touched and remain in Core Data.
Question: How can I avoid the duplicate record and why is this not happening to the invite Object
* UPDATE *
Returned JSON:
{
"inviteId": 226,
"meetingType": 2,
"activities": [{
"locationAddress": "4th Floor",
"startTime": "2014-05-07T01:15:23Z",
"activityId": 263,
"latitude": "0",
"longitude": "0",
"meetupId": 226,
"locationName": "West Conference Room",
"oldId": -7360
}, {
"locationAddress": "123 Main St. ",
"startTime": "2014-05-06T20:15:45Z",
"activityId": 264,
"latitude": "0",
"longitude": "0",
"meetupId": 226,
"locationName": "Starwood Building",
"oldId": -9325
}],
"comment": "Comments",
"status": 0,
"senderId": "Userid",
"startDate": "2014-05-07T13:15:00Z"
}
activities is the name of the relationship between Invite & Activity entities
This is the expected (if perhaps not ideal) outcome - RestKit is only able to map the response onto the sent object (not its relationships).
A good option could be to use fetch request blocks to find and purge the orphan activity objects at a later date (it wouldn't run after the POST, so you would need to manually find and delete if you needed the dead objects removed immediately).

How to add the label of a Primefaces chart?

I have a JSF line chart that uses PrimeFaces. I want to add labels to both x-axis & y-axis eg Year & Populations. I have used showLabel:true but its not working.The is code,
<p:lineChart id="chart" value="#{chartBean.linearModel}" xaxisAngle="-90">
<f:convertDateTime pattern="d-M-yyyy"/>
</p:lineChart>
function phaseChartExt() {
this.cfg.axes = {
xaxis: {
renderer: $.jqplot.DateAxisRenderer,
rendererOptions: { tickRenderer: $.jqplot.CanvasAxisTickRenderer },
tickOptions: {
showLabel:true,
showGridline: true,
formatString: '%H:%M',
angle: -90
}
}
yaxis: {
renderer: $.jqplot.DateAxisRenderer,
rendererOptions: { tickRenderer: $.jqplot.CanvasAxisTickRenderer },
tickOptions: {
showLabel:true,
showGridline: true,
formatString: '%H:%M',
angle: -90
}
}
}
}
Try to use
xaxisLabel="Year" yaxisLabel="Populations"
<p:lineChart id="chart" value="#{chartBean.linearModel}" xaxisAngle="-90" xaxisLabel="Year" yaxisLabel="Populations">
<f:convertDateTime pattern="d-M-yyyy"/>
</p:lineChart>

Line chart and Scatter chart overplot [duplicate]

This question already has answers here:
How to combine scatter chart with line chart to show line of regression? JavaFX
(4 answers)
Closed 8 years ago.
This code plots a LineChart and by clicking the "Add serie" button it adds a ScatterChart
It seems all ok but just move scene left/right or up/down (left mouse click and drag) both X, Y axis and charts are displaced.
How to fix this code in order to always get axis overlap as well as both charts?
Thanks.
import java.util.Set;
import javafx.application.Application;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Side;
import javafx.scene.Group;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Node;
import javafx.scene.chart.*;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
public class RescalingSeries extends Application {
StackPane mainGraphStackPane = null;
Button btnAdd;
BorderPane pane;
XYChart.Series series1 = new XYChart.Series();
SimpleDoubleProperty rectinitX = new SimpleDoubleProperty();
SimpleDoubleProperty rectinitY = new SimpleDoubleProperty();
protected static Axis _duplicateAxis(Axis axis, Axis result) {
result.setAnimated(axis.animatedProperty().get());
result.setAutoRanging(axis.isAutoRanging());
result.setLabel(axis.getLabel());
result.setSide(axis.getSide());
result.setTickLabelFill(axis.getTickLabelFill());
result.setTickLabelFont(axis.getTickLabelFont());
result.setTickLabelGap(axis.getTickLabelGap());
result.setTickLength(axis.getTickLength());
return result;
}
protected static ValueAxis _duplicateValueAxis(ValueAxis axis, ValueAxis result) {
_duplicateAxis(axis, result);
result.setLowerBound(axis.getLowerBound());
result.setUpperBound(axis.getUpperBound());
result.setMinorTickCount(axis.getMinorTickCount());
result.setMinorTickLength(axis.getMinorTickLength());
result.setTickLabelFormatter(axis.getTickLabelFormatter());
return result;
}
/**
* Duplicate a number axis.
* #param axis The source axis.
* #return A {#code NumberAxis}, never {#code null}.
*/
public static NumberAxis duplicateNumberAxis(NumberAxis axis) {
NumberAxis result = new NumberAxis();
_duplicateValueAxis(axis, result);
result.setTickUnit(axis.getTickUnit());
result.setForceZeroInRange(axis.isForceZeroInRange());
return result;
}
/**
* Duplicate a category axis.
* #param axis The source axis.
* #return A {#code CategoryAxis}, never {#code null}.
*/
public static CategoryAxis duplicateCategoryAxis(CategoryAxis axis) {
CategoryAxis result = new CategoryAxis(axis.getCategories());
_duplicateAxis(axis, result);
result.setStartMargin(axis.getStartMargin());
result.setEndMargin(axis.getEndMargin());
result.setGapStartAndEnd(axis.gapStartAndEndProperty().get());
return result;
}
#Override
public void start(Stage stage) {
final NumberAxis xAxisLC = new NumberAxis(1, 12, 1);
final NumberAxis yAxisLC = new NumberAxis(0.53000, 0.53910, 0.0005);
yAxisLC.setSide(Side.RIGHT);
yAxisLC.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxisLC) {
#Override
public String toString(Number object) {
return String.format("%7.5f", object);
}
});
final LineChart<Number, Number> lineChart = new LineChart<>(xAxisLC, yAxisLC);
lineChart.setCreateSymbols(false);
lineChart.setAlternativeRowFillVisible(false);
lineChart.setAnimated(true);
lineChart.setLegendVisible(false);
series1.getData().add(new XYChart.Data(1, 0.53185));
series1.getData().add(new XYChart.Data(2, 0.532235));
series1.getData().add(new XYChart.Data(3, 0.53234));
series1.getData().add(new XYChart.Data(4, 0.538765));
series1.getData().add(new XYChart.Data(5, 0.53442));
series1.getData().add(new XYChart.Data(6, 0.534658));
series1.getData().add(new XYChart.Data(7, 0.53023));
series1.getData().add(new XYChart.Data(8, 0.53001));
series1.getData().add(new XYChart.Data(9, 0.53589));
series1.getData().add(new XYChart.Data(10, 0.53476));
series1.getData().add(new XYChart.Data(11, 0.530123));
series1.getData().add(new XYChart.Data(12, 0.531035));
pane = new BorderPane();
pane.setCenter(lineChart);
mainGraphStackPane = new StackPane();
mainGraphStackPane.getChildren().add(pane);
Scene scene = new Scene(mainGraphStackPane, 800, 600);
lineChart.getData().addAll(series1);
stage.setScene(scene);
scene.setOnMouseClicked(mouseHandler);
scene.setOnMouseDragged(mouseHandler);
scene.setOnMouseEntered(mouseHandler);
scene.setOnMouseExited(mouseHandler);
scene.setOnMouseMoved(mouseHandler);
scene.setOnMousePressed(mouseHandler);
scene.setOnMouseReleased(mouseHandler);
Group root = new Group();
btnAdd = new Button();
btnAdd.setText("Add serie");
root.getChildren().add(btnAdd);
pane.getChildren().add(root);
btnAdd.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
NumberAxis xAxisBC = duplicateNumberAxis(xAxisLC);
NumberAxis yAxisBC = duplicateNumberAxis(yAxisLC);
ScatterChart<Number, Number> scatterChart = new ScatterChart<>(xAxisBC, yAxisBC);
scatterChart.setAlternativeRowFillVisible(false);
scatterChart.setAnimated(true);
scatterChart.setLegendVisible(false);
XYChart.Series series2 = new XYChart.Series();
series2.getData().add(new XYChart.Data(1, 0.53185));
series2.getData().add(new XYChart.Data(2, 0.532235));
series2.getData().add(new XYChart.Data(3, 0.53234));
series2.getData().add(new XYChart.Data(4, 0.538765));
series2.getData().add(new XYChart.Data(5, 0.53442));
series2.getData().add(new XYChart.Data(6, 0.534658));
series2.getData().add(new XYChart.Data(7, 0.53023));
series2.getData().add(new XYChart.Data(8, 0.53001));
series2.getData().add(new XYChart.Data(9, 0.53589));
series2.getData().add(new XYChart.Data(10, 0.53476));
series2.getData().add(new XYChart.Data(11, 0.530123));
series2.getData().add(new XYChart.Data(12, 0.531035));
scatterChart.getData().addAll(series2);
Set<Node> chartNode = scatterChart.lookupAll(".chart-plot-background");
for(final Node chr : chartNode){
chr.setStyle("-fx-background-color: transparent;");
}
chartNode = lineChart.lookupAll(".chart-plot-background");
for(final Node chr : chartNode){
chr.setStyle("-fx-background-color: transparent");
}
mainGraphStackPane.getChildren().add(scatterChart);
xAxisBC.lowerBoundProperty().bind(xAxisLC.lowerBoundProperty());
yAxisBC.lowerBoundProperty().bind(yAxisLC.lowerBoundProperty());
}
});
stage.show();
}
EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
boolean XScaling=false;
boolean YScaling=false;
if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED || mouseEvent.getEventType() == MouseEvent.MOUSE_MOVED ){
LineChart<Number, Number> lineChart = (LineChart<Number, Number>) pane.getCenter();
NumberAxis yAxis = (NumberAxis) lineChart.getYAxis();
NumberAxis xAxis = (NumberAxis) lineChart.getXAxis();
double Tgap = xAxis.getWidth()/(xAxis.getUpperBound() - xAxis.getLowerBound());
double newXlower=xAxis.getLowerBound(), newXupper=xAxis.getUpperBound();
double newYlower=yAxis.getLowerBound(), newYupper=yAxis.getUpperBound();
double xAxisShift = xAxis.localToScene(0, 0).getX();
double yAxisShift = yAxis.localToScene(0, 0).getY();
double yAxisStep=yAxis.getHeight()/(yAxis.getUpperBound()-yAxis.getLowerBound());
double CurrentPrice=yAxis.getUpperBound()-((mouseEvent.getY()-yAxisShift)/yAxisStep);
double Delta=0.3;
if(mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED && mouseEvent.getX()<xAxisShift+yAxis.getHeight() && mouseEvent.getY()<yAxisShift+yAxis.getHeight() && (XScaling==false || YScaling==false)){
//==================================================== X-Axis Moving ==================================
if(rectinitX.get() < mouseEvent.getX()){
newXlower=xAxis.getLowerBound()-Delta;
newXupper=xAxis.getUpperBound()-Delta;
}
else if(rectinitX.get() > mouseEvent.getX()){
newXlower=xAxis.getLowerBound()+Delta;
newXupper=xAxis.getUpperBound()+Delta;
}
xAxis.setLowerBound( newXlower );
xAxis.setUpperBound( newXupper );
//===================================================== Y-Axis Moving ====================================
if(rectinitY.get() < mouseEvent.getY()){
newYlower=yAxis.getLowerBound()+Delta/1000;
newYupper=yAxis.getUpperBound()+Delta/1000;
}
else if(rectinitY.get() > mouseEvent.getY()){
newYlower=yAxis.getLowerBound()-Delta/1000;
newYupper=yAxis.getUpperBound()-Delta/1000;
}
yAxis.setLowerBound(newYlower);
yAxis.setUpperBound(newYupper);
}
//----------------------------- Re-Scale the X-Axis when dragging below it ---------------------------------
else if(mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED && mouseEvent.getY()>yAxisShift+yAxis.getHeight() ){
if(rectinitX.get() < mouseEvent.getX()){
newXlower=xAxis.getLowerBound()+Delta;
newXupper=xAxis.getUpperBound()-Delta;
}
else if(rectinitX.get() > mouseEvent.getX()){
newXlower=xAxis.getLowerBound()-Delta;
newXupper=xAxis.getUpperBound()+Delta;
}
xAxis.setLowerBound( newXlower );
xAxis.setUpperBound( newXupper );
}
//--------------------------------- Re-Scale the Y-Axis when dragging to the left of it --------------------------
else if(mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED && mouseEvent.getX()> (xAxisShift + xAxis.getWidth())){
if(rectinitY.get() < mouseEvent.getY()){
newYlower=yAxis.getLowerBound()-Delta/1000;
newYupper=yAxis.getUpperBound()+Delta/1000;
}
else if(rectinitY.get() > mouseEvent.getY()){
newYlower=yAxis.getLowerBound()+Delta/1000;
newYupper=yAxis.getUpperBound()-Delta/1000;
}
yAxis.setLowerBound(newYlower);
yAxis.setUpperBound(newYupper);
}
rectinitX.set(mouseEvent.getX());
rectinitY.set(mouseEvent.getY());
if(mouseEvent.getEventType() == MouseEvent.MOUSE_MOVED && mouseEvent.getY()>yAxisShift && mouseEvent.getY()<yAxisShift+yAxis.getHeight() && mouseEvent.getX()>xAxisShift && mouseEvent.getX()<xAxisShift+xAxis.getWidth()){
double XX=((mouseEvent.getX() - xAxisShift) / Tgap) + xAxis.getLowerBound();
double YY=CurrentPrice;
series1.setName(String.format("%.2g%n",XX) + ", " + String.format("%.4g%n",YY));
}
}
}
};
public static void main(String[] args) {
launch(args);
}
}
Found a solution: I missed this part
xAxisBC.upperBoundProperty().bind(xAxisLC.upperBoundProperty());
yAxisBC.upperBoundProperty().bind(yAxisLC.upperBoundProperty());

JavaFX 2.x : Extend vertical line on sub pane(s)

This code plots a LineChart upper pane and a bar Chart in lower pane.
There is also a vertical line plotted left/right X move with pointer.
I would like to extend this vertical line also to the lower subpane, such as the attached picture
How to accomplish this?
Thanks.
Here is the code
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.*;
import javafx.scene.control.SplitPane;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.LineBuilder;
import javafx.stage.Stage;
public class XyChartInSplitOnlyCursor extends Application {
SplitPane splitPane1 = null;
BorderPane pane1;
BorderPane pane2;
Line LV;
XYChart.Series series1 = new XYChart.Series();
XYChart.Series series2 = new XYChart.Series();
#Override
public void start(Stage stage) {
stage.setTitle("Lines plot");
final NumberAxis xAxis = new NumberAxis(1, 12, 1);
final NumberAxis yAxis = new NumberAxis(0.53000, 0.53910, 0.0005);
xAxis.setAnimated(false);
xAxis.setScaleX(0);
yAxis.setAnimated(false);
yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
#Override
public String toString(Number object) {
return String.format("%7.5f", object);
}
});
final LineChart<Number, Number> lineChart1 = new LineChart<Number, Number>(xAxis, yAxis);
lineChart1.setCreateSymbols(false);
lineChart1.setAlternativeRowFillVisible(false);
lineChart1.setAnimated(false);
lineChart1.setLegendVisible(false);
series1.getData().add(new XYChart.Data(1, 0.53185));
series1.getData().add(new XYChart.Data(2, 0.532235));
series1.getData().add(new XYChart.Data(3, 0.53234));
series1.getData().add(new XYChart.Data(4, 0.538765));
series1.getData().add(new XYChart.Data(5, 0.53442));
series1.getData().add(new XYChart.Data(6, 0.534658));
series1.getData().add(new XYChart.Data(7, 0.53023));
series1.getData().add(new XYChart.Data(8, 0.53001));
series1.getData().add(new XYChart.Data(9, 0.53589));
series1.getData().add(new XYChart.Data(10, 0.53476));
series1.getData().add(new XYChart.Data(11, 0.530123));
series1.getData().add(new XYChart.Data(12, 0.531035));
lineChart1.getData().addAll(series1);
pane1 = new BorderPane();
pane1.setCenter(lineChart1);
splitPane1 = new SplitPane();
splitPane1.setOrientation(Orientation.VERTICAL);
splitPane1.getItems().addAll(pane1);
splitPane1.setDividerPosition(0, 1);
final CategoryAxis xAxis2 = new CategoryAxis();
final NumberAxis yAxis2 = new NumberAxis();
yAxis2.setTickUnit(1);
yAxis2.setPrefWidth(35);
yAxis2.setMinorTickCount(10);
yAxis2.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis2){
#Override
public String toString(Number object){
String label;
label = String.format("%7.2f", object.floatValue());
return label;
}
});
final BarChart<String, Number>BarChart = new BarChart<String, Number>(xAxis2, yAxis2);
BarChart.setAlternativeRowFillVisible(false);
BarChart.setLegendVisible(false);
BarChart.setAnimated(false);
XYChart.Series series2 = new XYChart.Series();
series2.getData().add(new XYChart.Data("Jan", 1));
series2.getData().add(new XYChart.Data("Feb", 3));
series2.getData().add(new XYChart.Data("Mar", 1.5));
series2.getData().add(new XYChart.Data("Apr", 3));
series2.getData().add(new XYChart.Data("May", 4.5));
series2.getData().add(new XYChart.Data("Jun", 5));
series2.getData().add(new XYChart.Data("Jul", 4));
series2.getData().add(new XYChart.Data("Aug", 8));
series2.getData().add(new XYChart.Data("Sep", 16.5));
series2.getData().add(new XYChart.Data("Oct", 13.9));
series2.getData().add(new XYChart.Data("Nov", 17));
series2.getData().add(new XYChart.Data("Dec", 20));
BarChart.getData().addAll(series2);
pane2 = new BorderPane();
pane2.setCenter(BarChart);
Platform.runLater(new Runnable() {
#Override
public void run() {
double percSplit;
splitPane1.getItems().addAll(pane2);
ObservableList<SplitPane.Divider> splitDiv = splitPane1.getDividers();
percSplit = 1/(double)(splitDiv.size()+1);
for (int i = 0; i< splitDiv.size(); i++) {
splitPane1.setDividerPosition(i, percSplit);
percSplit += 1/(double)(splitDiv.size()+1);
}
}
});
Scene scene = new Scene(splitPane1, 800, 600);
stage.setScene(scene);
pane1.setOnMouseMoved(mouseHandler);
LV=LineBuilder.create()
.startX(0)
.startY(0)
.endX(10)
.endY(.535)
.strokeWidth(1)
.stroke(Color.BLACK)
.build();
pane1.getChildren().add(LV);
stage.show();
}
EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getEventType() == MouseEvent.MOUSE_MOVED) {
LineChart<Number, Number> lineChart = (LineChart<Number, Number>) pane1.getCenter();
NumberAxis yAxis = (NumberAxis) lineChart.getYAxis();
NumberAxis xAxis = (NumberAxis) lineChart.getXAxis();
double newXlower=xAxis.getLowerBound(), newXupper=xAxis.getUpperBound();
double xAxisShift = getSceneShift(xAxis);
double yAxisShift = getSceneShift(yAxis);
if(mouseEvent.getX()>xAxisShift && mouseEvent.getX()<xAxisShift+xAxis.getWidth()){
LV.setStartX(mouseEvent.getX());
LV.setStartY(yAxisShift);
LV.setEndX(mouseEvent.getX());
LV.setEndY(yAxisShift+yAxis.getHeight());
}
}
}
};
private static double getSceneShift(Node node) {
double shift = 0;
do {
shift += node.getLayoutX();
node = node.getParent();
} while (node != null);
return shift;
}
public static void main(String[] args) {
launch(args);
}
}
Edit: added picture after jewelsea modify
Don't add the line to the pane in the SplitPane, instead create a Group which layers the line over the SplitPane.
Scene scene = new Scene(new Group(splitPane1, line), 800, 600);
If you want the Scene resizable, you can use a StackPane instead of a Group and bind the lines length to the scene height to get it to fill the Scene.
Here is a sample of applying using a StackPane and binding to extend the line in a resizable scene. Note, similarly to the originally posted code, the code is explicitly coded to only move the line when the mouse is inside the plot area of the top chart.
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.scene.*;
import javafx.scene.chart.*;
import javafx.scene.control.SplitPane;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.LineBuilder;
import javafx.stage.Stage;
public class XyChartInSplitOnlyCursor extends Application {
SplitPane splitPane1 = null;
BorderPane pane1;
BorderPane pane2;
Line LV1, LV2;
XYChart.Series series1 = new XYChart.Series();
XYChart.Series series2 = new XYChart.Series();
#Override
public void start(Stage stage) {
stage.setTitle("Lines plot");
final NumberAxis xAxis = new NumberAxis(1, 12, 1);
final NumberAxis yAxis = new NumberAxis(0.53000, 0.53910, 0.0005);
xAxis.setAnimated(false);
xAxis.setScaleX(0);
yAxis.setAnimated(false);
yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
#Override
public String toString(Number object) {
return String.format("%7.5f", object);
}
});
final LineChart<Number, Number> lineChart1 = new LineChart<Number, Number>(xAxis, yAxis);
lineChart1.setCreateSymbols(false);
lineChart1.setAlternativeRowFillVisible(false);
lineChart1.setAnimated(false);
lineChart1.setLegendVisible(false);
series1.getData().add(new XYChart.Data(1, 0.53185));
series1.getData().add(new XYChart.Data(2, 0.532235));
series1.getData().add(new XYChart.Data(3, 0.53234));
series1.getData().add(new XYChart.Data(4, 0.538765));
series1.getData().add(new XYChart.Data(5, 0.53442));
series1.getData().add(new XYChart.Data(6, 0.534658));
series1.getData().add(new XYChart.Data(7, 0.53023));
series1.getData().add(new XYChart.Data(8, 0.53001));
series1.getData().add(new XYChart.Data(9, 0.53589));
series1.getData().add(new XYChart.Data(10, 0.53476));
series1.getData().add(new XYChart.Data(11, 0.530123));
series1.getData().add(new XYChart.Data(12, 0.531035));
lineChart1.getData().addAll(series1);
pane1 = new BorderPane();
pane1.setCenter(lineChart1);
splitPane1 = new SplitPane();
splitPane1.setOrientation(Orientation.VERTICAL);
splitPane1.getItems().addAll(pane1);
splitPane1.setDividerPosition(0, 1);
final CategoryAxis xAxis2 = new CategoryAxis();
final NumberAxis yAxis2 = new NumberAxis();
yAxis2.setTickUnit(1);
yAxis2.setPrefWidth(35);
yAxis2.setMinorTickCount(10);
yAxis2.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis2) {
#Override
public String toString(Number object) {
String label;
label = String.format("%7.2f", object.floatValue());
return label;
}
});
final BarChart<String, Number> BarChart = new BarChart<String, Number>(xAxis2, yAxis2);
BarChart.setAlternativeRowFillVisible(false);
BarChart.setLegendVisible(false);
BarChart.setAnimated(false);
XYChart.Series series2 = new XYChart.Series();
series2.getData().add(new XYChart.Data("Jan", 1));
series2.getData().add(new XYChart.Data("Feb", 3));
series2.getData().add(new XYChart.Data("Mar", 1.5));
series2.getData().add(new XYChart.Data("Apr", 3));
series2.getData().add(new XYChart.Data("May", 4.5));
series2.getData().add(new XYChart.Data("Jun", 5));
series2.getData().add(new XYChart.Data("Jul", 4));
series2.getData().add(new XYChart.Data("Aug", 8));
series2.getData().add(new XYChart.Data("Sep", 16.5));
series2.getData().add(new XYChart.Data("Oct", 13.9));
series2.getData().add(new XYChart.Data("Nov", 17));
series2.getData().add(new XYChart.Data("Dec", 20));
BarChart.getData().addAll(series2);
pane2 = new BorderPane();
pane2.setCenter(BarChart);
Platform.runLater(new Runnable() {
#Override
public void run() {
double percSplit;
splitPane1.getItems().addAll(pane2);
ObservableList<SplitPane.Divider> splitDiv = splitPane1.getDividers();
percSplit = 1 / (double) (splitDiv.size() + 1);
for (int i = 0; i < splitDiv.size(); i++) {
splitPane1.setDividerPosition(i, percSplit);
percSplit += 1 / (double) (splitDiv.size() + 1);
}
}
});
LV1 = LineBuilder.create()
.strokeWidth(2)
.stroke(Color.FORESTGREEN)
.build();
StackPane stack = new StackPane();
Pane glassPane = new Pane();
glassPane.getChildren().add(LV1);
glassPane.minWidthProperty().bind(splitPane1.widthProperty());
glassPane.minHeightProperty().bind(splitPane1.heightProperty());
glassPane.setMouseTransparent(true);
stack.getChildren().addAll(splitPane1, glassPane);
Scene scene = new Scene(stack, 800, 600);
LV1.endYProperty().bind(scene.heightProperty());
stage.setScene(scene);
pane1.setOnMouseMoved(mouseHandler);
stage.show();
}
EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
XYChart<Number, Number> chart1 = (XYChart<Number, Number>) pane1.getCenter();
plotLine(chart1, LV1, mouseEvent.getX() + 1);
}
};
private void plotLine(XYChart<Number, Number> chart, Line line, double x) {
Axis xAxis = chart.getXAxis(), yAxis = chart.getYAxis();
final double min = getSceneShift(xAxis);
final double max = min + xAxis.getWidth();
boolean setCrosshair = false;
if (x > min && x < min + xAxis.getWidth()) {
LV1.setStartX(x); LV1.setEndX(x);
setCrosshair = true;
} else if (x <= min){
LV1.setStartX(min); LV1.setEndX(min);
} else if (x >= max){
LV1.setStartX(max); LV1.setEndX(max);
}
if (setCrosshair) {
chart.setCursor(Cursor.CROSSHAIR);
} else {
chart.setCursor(Cursor.DEFAULT);
}
}
private static double getSceneShift(Node node) {
double shift = 0;
do {
shift += node.getLayoutX();
node = node.getParent();
} while (node != null);
return shift;
}
public static void main(String[] args) {
launch(args);
}
}

Resources