How the access the multiple fx:id efficiently (in FXML Document Controller)? - java

I have to set values for labels, I am set values by following way which is very lengthy,
public class FXMLDocumentController implements Initializable {
private TilesLogic gl = new TilesLogic();
private List<List<Integer>> game;
#FXML
private Label C1;
#FXML
private Label C2;
#FXML
private Label C3;
#FXML
.
.
.
private Label C16;
#FXML
private Label timer;
#Override
public void initialize(URL url, ResourceBundle rb) {
game = gl.shuffle();
SetValues();
}
void SetValues(){
C1.setText(String.valueOf(game.get(0).get(0)));
C2.setText(String.valueOf(game.get(0).get(1)));
.
.
C15.setText(String.valueOf(game.get(3).get(2)));
C16.setText(String.valueOf(game.get(3).get(3)));
}
}
is that any other way just like that
for(int i =1;i<17;i++)
setText("#C"+String.valueOf(i),String.valueOf(game.get(i)));
// setText("#id","Sometext");
to do it simple way and less time ?

Related

nullPointerException and how to update label the right way?

I have 2 scenes :
The first one has a "Balance" Label, which displays the balance from a variable.
The second scene is the deposit scene where the user adds to the balance.
(Each scene has its controller class)
I want the balance to be updated when the user goes back to the first scene.
what's the best way to do so? I couldn't find an event for the scene shown, I found online only a stage example which triggers an event when the window is closed, but here I am just changing scenes by changing the mainstage scene.
I have tried making an object of the first scene class inside the second scene's class and calling a method to change the label text when I click the back button but that didn't work.
Here's the code for the first scene where lbBalance is the label I want to update, and updateBal is the method I am using in the second scene class.
public class accountController extends Controller implements Initializable {
#FXML private Label gilbert;
#FXML private Label lbBalance;
#FXML private Button deposit;
#FXML private Button btn_showBalance;
private application.depositController depositController;
#Override
public void initialize(URL location, ResourceBundle resources) {
lbBalance.setText(String.valueOf(BAL));
}
#FXML
public void handleDeposit(ActionEvent event) throws IOException {
Parent depositParent = FXMLLoader.load(getClass().getResource("deposit.fxml"));
depositScene = new Scene(depositParent);
mainStage.setScene(depositScene);
mainStage.show();
}
public void updateBal() {
lbBalance.setText(String.valueOf(BAL));
}
}
Here's the second scene's class
accountController backtoscene= new accountController();
#FXML private Label info;
#FXML private Button btn_depositfinal;
#FXML private TextField depositamount;
#FXML private Button btn_back;
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
}
#FXML
public void handleDepositFinal(ActionEvent event) {
deposit(Integer.parseInt(depositamount.getText()));
info.setVisible(true);
}
#FXML
public void handleBackButton(ActionEvent event) throws IOException {
backtoscene.updateBal();
mainStage.setScene(newscene);
}
TL;DR calling the method is giving me a nullPointerException, is there any other way to update the balance label when getting back to previous scene?
NOTE: I haven't tested the code, I just wrote it freehand, but it gives you a general idea.
Your main issue is that you are creating a new AccountController in the DepositController. Meaning it's a different one than the one you originally instantiated.
public class AccountController extends Controller implements Initializable {
#FXML private Label gilbert;
#FXML private Label lbBalance;
#FXML private Button deposit;
#FXML private Button btn_showBalance;
private application.DepositController depositController;
#Override
public void initialize(URL location, ResourceBundle resources) {
lbBalance.setText(String.valueOf(BAL));
}
#FXML
public void handleDeposit(ActionEvent event) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("deposit.fxml"));
Parent depositParent = loader.load();
depositScene = new Scene(depositParent);
depositController = loader.getController();
depositController .setAccountController(this);
mainStage.setScene(depositScene);
mainStage.show();
}
public void updateBal() {
lbBalance.setText(String.valueOf(BAL));
}
}
Here's the second class where you need to set the AccountController to be the one you originally initialized :
public class DepositController extends Controller implements Initializable {
AccountController backtoscene;
#FXML private Label info;
#FXML private Button btn_depositfinal;
#FXML private TextField depositamount;
#FXML private Button btn_back;
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
}
public void setAccountController(AccountController controller){
backtoscene = controller;
}
#FXML
public void handleDepositFinal(ActionEvent event) {
deposit(Integer.parseInt(depositamount.getText()));
info.setVisible(true);
}
#FXML
public void handleBackButton(ActionEvent event) throws IOException {
backtoscene.updateBal();
mainStage.setScene(newscene);
}
}
Now you have access to the AccountController you originally initialized at the start, and the AccountController has access to the correct DepositController.

JavaFx two diffrent classes in tableview and tablecolumn

My problem is that I have two different classes : "Book" and "User".
I want to display Books in my table after clicking button "Show all books" and then all Users in this same table after clicking button "show all users". I don't know what type I should give in tableview and tablecolumn.
What can i put instead of "?" ?
public class WorkerPaneController implements Initializable {
#FXML
private TableView<?> tab;
#FXML
private TableColumn<?, ?> c3;
#FXML
private TableColumn<?, ?> c4;
#FXML
private TableColumn<?, ?> c5;
#FXML
private TableColumn<?, ?> c6;
#FXML
private Button test;
#FXML
private ComboBox<String> wybor;
#FXML
private Button show;
#FXML
private TableColumn<Data, ?> c1;
#FXML
private TableColumn<?, ?> c2;
#Override
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
this.wybor.getItems().addAll("Książek", "Egzemplarzy", "Czytelników",
"Pracowników");
}
#FXML
public void ChangeScene(ActionEvent event) throws IOException {
Parent userMenu =
FXMLLoader.load(getClass().getResource("/LibDB/view/UserPane.fxml"));
Stage s = new Stage();
s.setTitle("test");
s.setScene(new Scene(userMenu));
s.show();
}
#FXML
public void pokaz(ActionEvent event) throws IOException {
if (wybor.getValue() != null) {
switch (this.wybor.getValue()) {
case "Czytelników":
c1.setText("id_czytelnika");
c2.setText("Imie");
c3.setText("Nazwisko");
c4.setText("Wiek");
c5.setText("PESEL");
c6.setText("id_adresu");
break;
case "Pracowników":
c1.setText("id_czytelnika");
c2.setText("Imie");
c3.setText("Nazwisko");
c4.setText("Wiek");
c5.setText("PESEL");
c6.setText("id_adresu");
break;
case "Książek":
c1.setText("id_ksiazki");
c2.setText("Tytul");
c3.setText("Ilosc stron");
c4.setText("ISBN");
c5.setText("Rok Wydania");
c6.setText("id_wydawnictwa");
break;
case "Egzemplarzy":
c1.setText("id_egzemplarza");
c2.setText("Numer katalogowy");
c3.setText("id_Typ okladki");
c4.setText("Numer ksiazki");
c5.setText("opis");
c6.setText("Dostepnosc");
break;
}
} else {
System.out.println("test");
}
}
public void initPracownikow() {
// c1.setCellValueFactory(data ->
// data.getValue().getUzytkownicy().get(0).getImieProperty());
}
}

Javafx: How to group mouse actions over an image

I am a newbie in Javafx and I am trying to fix a cropping over an image. I found an interesting solution for cropping with rubber band and now I try to modified this in my scenario.
I have two controllers. One controller has the crop button (CropController) and another controller which contain an image as ImageController.
CropController:
public class CropController {
#FXML
private void initialize() {}
#FXML
private void handleCrop(){
}
}
ImageController:
public class ImageController {
#FXML
private ImageView MainImage;
#FXML
private void initialize() {
modelSharedOne.imageProperty()
.addListener((obs, oldImage,newImage)-> MainImage.setImage(newImage));
}
#FXML
private void handleMousePresses(){}
#FXML
private void handleMouseDragged(){}
#FXML
private void handleMouseReleased(){}
}
Based on the rubber band solution I need to group those three mouse handlers. I do not know what could be the best solution for this. I have tried many solutions like creating a model between these two controllers but I have not managed to solve this solution.
Anyone knows how can I solve this?
My current solution
CropController:
public class ToolboxController {
#FXML
private void initialize() {
}
#FXML
private void handleCrop(){
SharedModelTwo.callHandlerInWorkstation();
}
}
SharedModelTwo:
public class CropImageModel {
ImageController imageController;
public void callHandlerInImage(){
imageController = new ImageController();
imageController.handleCrop();
}
}
ImageController:
public class ImageController {
#FXML
private ImageView MainImage;
#FXML
private void initialize() {
modelSharedOne.imageProperty()
.addListener((obs, oldImage,newImage)-> MainImage.setImage(newImage));
}
public void handleCrop() {
Image image = getImage();
ImageView imageView = new ImageView(image);
rect = new Rectangle( 0,0,0,0);
rect.setStroke(Color.BLUE);
rect.setStrokeWidth(1);
rect.setStrokeLineCap(StrokeLineCap.ROUND);
rect.setFill(Color.LIGHTBLUE.deriveColor(0, 1.2, 1, 0.6));
Group imageLayer = new Group();
imageLayer.getChildren().add(imageView);
rubberBandSelection = new RubberBandSelection(imageLayer);
}
}
And rubberBandSelection is a class as it was in the linked. when I run that it does not hit when mouse pressed on image.

Dynamically adding UI controls when button is clicked

I a have tabPane with multiple tabs and inside one of the tabPane i have scrollPane. Inside the scrollPane i have a number of UI controls As shown on this image that i want to be dynamically added when i click a button.
This image here shows the UI setup of what i have. The UI controls are in an Hbox which is inside a Vbox.
When a user clicks the add button i would like to add another row with all the controls as shown in this image.
I have looked at post such as these and still cannt get to achieve the same effect on my code.
JavaFX continuous form dynamically add new row with content in gridpane,
Dynamically add elements to a fixed-size GridPane in JavaFX,
How to maintain GridPane's fixed-size after adding elemnts dynamically
When i followed the approach suggested by another stack-overflow member on the first question cited above, to use a listView the code worked. However his suggestion programmatically codes UI controls and when i try to change and use UI controls i created within scene builder it doesn't work. Also when i put the controls inside a tabPane my code doesn't work. Meaning when i click the add button it doesn't add the UI controls as expected.
My question is how can i dynamically add UI controls within a tab inside a tabPane when a button which is also in that tab is clicked.
Here is my code :
public class DynamicalyAddControlsController {
#FXML
private VBox vbox;
#FXML
private HBox hbox;
#FXML
private StackPane stack1;
#FXML
private Label taskid;
#FXML
private TextField taskname;
#FXML
private ComboBox<String> combobox;
#FXML
private TextArea textarea;
#FXML
private Button save;
private ObservableList<Car> cars = FXCollections.observableArrayList();
public void initialize(URL url, ResourceBundle rb) {
cars.addAll(new Car(CAR_TYPE.CAR1), new Car(CAR_TYPE.CAR2), new Car(CAR_TYPE.CAR3));
ListView<Car> carsListView = new ListView<>();
carsListView.setCellFactory(c -> new CarListCell());
carsListView.setItems(cars);
stack1.getChildren().add(carsListView);
}
private class CarListCell extends ListCell<Car> {
private ChoiceBox<CAR_TYPE> choiceBox = new ChoiceBox<>();
public CarListCell(){
choiceBox.setItems(FXCollections.observableArrayList
(CAR_TYPE.values()));
hbox.getChildren().addAll(taskid,taskname,combobox,choiceBox);
vbox.getChildren().addAll(hbox,textarea);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setGraphic(vbox);
}
#Override
protected void updateItem(Car item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setGraphic(null);
} else {
setGraphic(vbox);
choiceBox.setValue(item.getType());
save.setOnAction(e -> {
Car newCar = new Car(choiceBox.getValue());
cars.add(newCar);
});
}
}
}
private enum CAR_TYPE {
CAR1, CAR2, CAR3;
}
private class Car {
private CAR_TYPE type;
public Car(CAR_TYPE type) {
this.type = type;
}
public CAR_TYPE getType() {
return type;
}
public void setType(CAR_TYPE type) {
this.type = type;
}
}
public void initialize(URL url, ResourceBundle rb) {
}
}
JavaApplication main class
#Override
public void start(Stage primaryStage) throws Exception{
Parent viewB = FXMLLoader.load(getClass().getResource("DynamicalyAddControls.fxml"));
Stage stageB = new Stage();
stageB.setScene(new Scene(viewB));
stageB.show();
}
public static void main(String[] args) {
launch(args);
}

Binding double value to JavaFX gui

I have implemented fft for my school project(tuner), although, im not able to pass calculated frequency to GUI. I tried binding, keyframes, i just cant seem to get a grasp of it, im really new to java.
public class FrequencyBean {
double freq;
private SimpleDoubleProperty value = new SimpleDoubleProperty(this, "value");
public void setValue(double value){
this.value.set(value);
System.out.println(value+" set");
}
public DoubleProperty getDoublePropertyValue(){
System.out.println("gotvals");
return value;
}
public FrequencyBean(){
freq = 10.0;
}
that is part of my controller, also i got reccomended to use something called tight binding or so, which would be abstracting of this class. Is that good for my code?
This is my main controller:
public class Controller implements Initializable{
FrequencyBean fbean;
#FXML
private Label otherFq;
#FXML
private Text frequency;
#FXML
private Text sharpFq;
#FXML
private Rectangle sharp6;
#FXML
private Text flatFq;
#FXML
private Rectangle center_rectangle;
#FXML
private Rectangle sharp1;
#FXML
private Rectangle sharp2;
#FXML
private Rectangle sharp3;
#FXML
private Rectangle sharp4;
#FXML
private Rectangle sharp5;
#FXML
private Text centerFq;
#FXML
private Rectangle flat6;
#FXML
private Rectangle flat5;
#FXML
private Rectangle flat4;
#FXML
private Rectangle flat3;
#FXML
private Rectangle flat2;
#FXML
private Rectangle flat1;
#Override
public void initialize(URL location, ResourceBundle resources) {
fbean = new FrequencyBean();
otherFq = new Label();
frequency = new Text();
boolean stop = false;
InputThread input = new InputThread();
Task<Void> in = new Task<Void>() {
#Override
protected Void call() throws Exception {
input.run();
return null;
}
};
Thread th0 = new Thread(in);
th0.start();
frequency.textProperty().bind(fbean.getDoublePropertyValue());
}
Rewrite your FrequencyBean correctly as a 'JavaFX-Bean':
public class FrequencyBean {
private SimpleDoubleProperty frequency = new SimpleDoubleProperty();
/**
* #param frequency the frequency to set
*/
public void setFrequency(double value){
this.frequency.set(value);
}
/**
* #return the frequency as double
*/
public double getFrequency(){
return this.frequency.get();
}
/**
* #return the frequency property
*/
public DoubleProperty frequencyProperty(){
return value;
}
public FrequencyBean(){
frequency = 10.0;
}
}
As Jame_D pointed it out: don't initialize a control annotated with #FXML.
Just bind the control in question like so:
...
#FXML
TextField tf_Frequency;
...
fbean = new FrequencyBean(20.3);
tfFrequency.textProperty().bind(fbean.frequencyProperty().asString("%.2f"));
Note that this is correct if you need a uni-directional binding.
There is also a bindBidirectional method.

Categories