Let's say I want to make a "note taking swt program", so every time I press a button, the program is going to create a new label about 50 pixels lower to the label before. What's an efficient way of implementing that?
I did it with simple ListView and ObservableList, but observable list isn't necessary. Here is my version of this.
public class Controller {
#FXML
private ListView<Label> listView;
private ObservableList<Label> yourList;
public void initialize() {
yourList = FXCollections.observableArrayList();
listView.setItems(yourList);
}
public void onButtonPressed(){
// You can do really bigger processing here
Label label = new Label();
label.setText("some text maybe");
label.setPadding(new Insets(10));
yourList.add(label);
}
}
Result after three times button pressed:
some text maybe
some text maybe
some text maybe
this can come with padding, customizable fonts, color etc.
Hope it helps
Related
Hi I have problem with huge amount of similar drag and drop events for images, which i move with label to other image views.
Example of code:
//drag and drope for imageview01
#FXML
private void handleDragDetected1(MouseEvent event) {
Dragboard db = imageview01.startDragAndDrop(TransferMode.ANY);
ClipboardContent cb = new ClipboardContent();
cb.putImage(imageview01.getImage());
cb.putString(imageview01_label.getText());
db.setContent(cb);
System.out.println("Picture 1 is draged");
}
...
...
//drag and drope for imageview100
#FXML
private void handleDragDetected100(MouseEvent event) {
...
...
}
Is there any solution to make code shorten ?
You could assign the Labels as userData of the corresponding ImageViews which allows you to use the event source to retrieve the Label and therefore allows you to use the same event handler for all ImageViews.
The following example uses a Button and the onMouseClicked event for simplicity, but the same approach works for your problem too:
FXML
<Label text="Hello World" fx:id="label1"/>
<Button text="Print Label 1" onMouseClicked="#click" userData="$label1"/>
Controller
#FXML
private void click(MouseEvent event) {
// retrieve the node the event occured on
Button btn = (Button) event.getSource();
// retrieve Label associated with event source
Label label = (Label) btn.getUserData();
// now we've got all info we need without using any field of the controller
System.out.println(label.getText());
}
(You do not even need a label1 field in the controller.)
I have FirstFxml.fxml file and its controller as FirstFxmlController. I need to create custom run time buttons depending upon the sizeOfList(Currently assuming it as 4). I created following code and added action for it. But it cant apply this action to last button. Means by clicking on last button(i.e. Click Me 4), setOnAction not working for it. I tried this with lambda and handler but same issue with them also. Is there any javafx issue for following code, suggest me changes for this issue.
public class FirstFxmlController implements Initializable{
#FXML
public VBox centerVBox;
#Override
public void initialize(URL location, ResourceBundle resources) {
//Adding multiple buttons
int sizeOfList = 5;
StackPane stack[] = new StackPane[sizeOfList];
Button b[] = new Button[sizeOfList];
for(int i = 1; i<sizeOfList; i++){
b[i] = new Button("Click me "+i);
b[i].setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
System.out.println("Clicked");
}
});
stack[i] = new StackPane();
stack[i].setMargin(b[i], new Insets(20, 0, 0, 0));
stack[i].getChildren().add(b[i]);
centerVBox.getChildren().add(stack[i]);
}
}
Sorry it was my mistake, as vbox is in center part of border pane and size for this border pane was fixed. So what happens is bottom element of borderpane overrides on last button. So it causes not functioning of this last button. Problem solved. I just increase the size of main screen. Thanks buddies for your instant replay and suggestions.
I'm currently made an Form with JavaFX.
Always i press a Button, i call the "addAnswer()"-Method.
In that I create a RadioButton, a Label and a delete-Button, which i bundle in a HBox. All that HBoxes i pack in a vBox.
The Problem now is the delete-Button. I want to delte just THAT HBox in which the clicked Button is.
Here is my code:
public void addAnswer() {
this.rB = new RadioButton();
checkAnswer.getToggles().add(rB);
hBox = new HBox();
tF = new TextField();
delAnswer = new Button("Löschen");
delAnswer.setId(Integer.toString(counter));
hBox.getChildren().addAll(rB, tF, delAnswer);
hBox.setId(Integer.toString(counter));
delAnswer.setOnAction(e -> delAnswer(Integer.parseInt(hBox.getId())));
System.out.println(delAnswer.getId());
vBox.getChildren().addAll(hBox);
counter++;
}
public void delAnswer(int e){
vBox.getChildren().remove(delAnswer.getId());
}
i tried this one above but i realized, that all the delAnswers-Buttons have the same ID: the number of how often i pressed the add-Button.
Is there any solution where i can just select that one i pressed with that dynamic way? Cause i don't kow how often somebody will press or delete something.
Thanks
hbox is a field and this is why always the HBox last added is used. (hBox is evaluated, when lambda body is executed, not at the time of the lambda creation). This would be different, if you used a (effectively) final local variable:
final HBox hBoxLocal = hBox;
delAnswer.setOnAction(e -> delAnswer(Integer.parseInt(hBoxLocal.getId())));
However I'd like to present a different solution which would allow you to use the same EventHandler<ActionEvent> for all delete Buttons:
You can get the Node that triggered the event using getSource. From this Node you can get the parent, which is the HBox. You can remove this from the VBox using the remove(Object) method
delAnswer.setOnAction(e -> {
// get button
Node source = (Node) e.getSource();
// remove parent of button from VBox
vBox.getChildren().remove(source.getParent());
});
I think your problem is that you give the same event to all your button,Begin by creating a list that stores your buttons and then increments the value of the ID after affecting it to an item :
List<Button> buttons = new ArrayList<>();
/*
Create Button and call IDEvt method to create new event
for each button
*/
private void IDEvt(Button btn){
btn.setId(String.valueOf(IDRank));
btn.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println(btn.getId());
}
});
IDRank++;
}
I want to have several JavaFX Buttons that update one Label in my Application with text. For testing purposes it's just Button Text.
What I did at first worked fine and looked like this:
String Text = "...";
public void kons() {
System.out.println("Works...");
System.out.println(Text);
Tekst.setText(Text);
Button G4 = new Button("Spadantes");
G4.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Text = G4.getText();
kons();
}
});
Then I decided to stylize my buttons with CSS and because I wanted to have several groups of buttons stylized in different way I subclassed JavaFX Button class in this way:
public class Buttons extends Button {
public Buttons(String text) {
super(text);
getStylesheets().clear();
getStylesheets().add("./Buttons.css");
Which still worked. But now I want my event handler to be moved to Button subclass (to avoid copy-pasting exactly same code into each and every button of mine). What I did looks like this:
public class Buttons extends Button {
public Buttons(String text) {
super(text);
getStylesheets().clear();
getStylesheets().add("./Buttons.css");
setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Main.Text = getText();
Main.kons();
}
});
}
}
Main is my extend Application class
Tekst is my label.
And sadly it throws me exception about calling non-stathic method and variable from static context. From what I understand instances are static and definitions are non-static. I tried to change everything "in the way" to static but it gives me red wall of errors after clicking button (nothing in compilation process). I also tried to call instance of my Application somehow but I have no idea how (from what I understand extend Application class intantiates itself on it's own while starting program so there's no "name" by which I can call it's Label.
What I'm looking for is "quick and dirty solution" to be able to use subclassed buttons (or other sliders, text-fields, etc.) that can call a method that updates something "on screen".
[EDIT] I'm using newest Java there is of course. In case it matters.
Instead of subclassing, why not just write a utility method that creates the buttons for you? I would also not recommend making the text variable an instance variable: just reference the Label directly.
public class SomeClass {
private Label tekst ;
// ...
private Button createButton(String buttonText) {
Button button = new Button(buttonText);
button.getStylesheets().add("Buttons.css") ;
button.setOnAction(e -> tekst.setText(buttonText));
return button ;
}
}
Then, from within the same class, when you need one of those buttons you just do
Button button = createButton("Text");
If you really want to subclass (which just seems unnecessary to me), you need to pass a reference to the label to the subclass:
public class LabelUpdatingButton extends Button {
public LabelUpdatingButton(String text, Label labelToUpdate) {
super(text);
getStylesheets().add("Buttons.css");
setOnAction(e -> labelToUpdate.setText(getText()) );
}
}
Then from your class that assembles the UI you can do
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
Label tekst = new Label();
Button someButton = new LabelUpdatingButton("Button text", tekst);
// etc...
}
}
But again, creating a subclass that does nothing other than define a constructor that calls public API methods is redundant, imo.
Also, it's a bit unusual to create an entire stylesheet just for your buttons. Typically you would set a style class on the Button:
button.getStyleClass().add("my-button-class");
and then in the stylesheet you add to the Scene do
.my-button-class {
/* styles for this type of button */
}
I am working on an application in java FX. I need a data structure similar to JList in java swings.I have to use it in my project for displaying data on a scroll pane. I have tried using observable arraylist, with listview and Vbox. Here is my code snippet of the controller class.
public class Controller_class
implements Initializable {
#FXML // fx:id="myButton"
private Button dfctsave;
#FXML
final TextField dfctname = new TextField();
#FXML
ScrollPane dfctscroll = new ScrollPane ();
static ArrayList<String> jlstDefects=new ArrayList<String>();
#Override // This method is called by the FXMLLoader when initialization is complete
public void initialize(URL fxmlFileLocation, ResourceBundle resources)
{
dfctsave.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
ObservableList ad;
VBox v;
String d=dfctname.getText();
jlstDefects.add(d);
System.out.println(jlstDefects);
ad = FXCollections.observableArrayList(jlstDefects);
System.out.println(ad);
ListView lv = new ListView();
lv.setItems(ad);
v=new VBox();
v.getChildren().addAll(lv);
dfctscroll.setContent(v);
}
});
}}
It worked well and I got entries on to the scrollpane, but I need the index of the selected data items for swapping and further processing on scrollpane. I heard about SwingList which would work like the same. Can anyone explain the best alternates for Jlist in FX or explain how to use SwingList in FX.
I tried working with List view. Its working fine.For selecting a particular value on the list view and getting its index, I used the following code snippet.
public ListView<String> jlstDefects ;
public TextField fldDefectName;
private void jltDefectsListItemSelected()
{
int ndx = jlstDefects.getSelectionModel().getSelectedIndex();
if (ndxJlstDefectSelector == ndx)
return;
ndxJlstDefectSelector = ndx;
String strSelectedDefectName = lstDefectList.getDefect(ndx);
fldDefectName.setText(strLocalDefectName);
}
I have assigned the item which I got from the list view to a text field in my application.
Thanks for the suggestions provided.