I would like a javafx label to be automatically updated to what is being typed into a textfield, currently i have it changing only when enter is clicked. I am using a mix of swing and javafx.
is this possible?
thanks
exprField.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Platform.runLater(new Runnable() {
#Override
public void run() {
fxLabel.setText(exprField.getText());
}
});
}
});
You can use the Binding-Mechanism for this purpose.
GridPane p = new GridPane();
TextField tf = new TextField("DEFAULT");
Label l1 = new Label("...");
l1.textProperty().bind(tf.textProperty());
p.add(tf, 0, 0);
p.add(l1, 1, 0);
Scene sc = new Scene(p, 500, 500);
arg0.setScene(sc);
arg0.show();
This code sets a textbox and a label into a gridpane. The text property of the label is bound to the text property of the textfield, which means as soon as the textfields changes, the text of the label gets updated according to whatever text is now in the textfield.
More information can be found here: http://docs.oracle.com/javafx/2/binding/jfxpub-binding.htm
Related
Here i would like to create a responsive button alongwith imageview,but the problem is imageview not binding properly with button and if i clicked on the button or try to resize the window, automatically the image size increeses and lot of irrelevent scaling problems occuring,eventhough i have'nt set an eventhandler for that button.
This is my sample code
public class ImageController extends Application{
private DoubleProperty fontSize = new SimpleDoubleProperty(10);
#Override
public void start(Stage primaryStage) {
FlowPane fp=new FlowPane(); //here i used flowpane to make imagegallery(productview) that will be in responsive in thier position and i tested my problem not with the flowpane
for(int j=0;j<1;j++)
{
try {
Button button = new Button();
button.styleProperty().bind(Bindings.concat("-fx-font-size: ", fontSize.asString(), ";")); //button size binded to the scene
FileInputStream input = new FileInputStream("images/wine.png");
Image image = new Image(input, 100, 100, true,true);
ImageView imageView=new ImageView(image);
imageView.setPreserveRatio(true);
imageView.fitWidthProperty().bind(button.widthProperty()); //image size binded to the button
imageView.fitHeightProperty().bind(button.heightProperty());
button.setGraphic(imageView);
fp.getChildren().add(button);
} catch (FileNotFoundException ex) {
Logger.getLogger(ImageController.class.getName()).log(Level.SEVERE, null, ex);
}
}
Scene scene = new Scene(fp, 500, 500);
fontSize.bind(scene.widthProperty().add(scene.heightProperty()).divide(50));
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
you can see my problem dairectly by running my code and resize the window or clicking on button.I need a button alongwith imageview both will resize according to screen resize(responsive)that's all.ThankYou in advance
I have an Accordian with multiple TitledPanes. When a TitledPane is expanded, there are "dead areas" on the pane that do not have sub-components (e.g., buttons, text, etc.).
Right now, when I check MouseEvent.getSource(), it returns an instance of TitledPane for all areas. Is there a way to specifically constrain/check for a mouse-click on the "title" section of the TitledPane?
I don't think there is a public API to detect mouse click on title region, however it is possible to do that this way:
titledPane.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
EventTarget target = event.getTarget();
String clazz = "class com.sun.javafx.scene.control.skin.TitledPaneSkin$TitleRegion";
if(target.getClass().toString().equals(clazz) || // anywhere on title region except title Text
(target instanceof Node && ((Node) target).getParent().getClass().toString().equals(clazz))) // title Text
System.out.println("title was clicked");
}
});
But this method is highly discouraged as it relies on some internal implementation detail that may be subject to change.
May be it's better to think more about what you actually need. Maybe your actual requirement can be fulfilled by uisng TitledPane's public API methods and properties.
For insatnce expandedProperty()'s value gets changed every time mouse click occurs on title region (if isCollapsible() is set to true).
titledPane.expandedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
System.out.println("mouse click changed expanded from " + oldValue + " to " + newValue);
}
});
In the css reference you can find out that there is a child of the TitledPane that has the style class title. It isn't hard to guess that this part is the title. You can go from the pick result up through the scene graph until you either find a node with the style class title or until you reach the Accordion.
The following code colors the rect below the Accordion green, iff the mouse is on a title and red otherwise:
#Override
public void start(Stage primaryStage) {
TitledPane tp1 = new TitledPane("foo", new Rectangle(100, 100));
TitledPane tp2 = new TitledPane("bar", new Circle(100));
Accordion accordion = new Accordion(tp1, tp2);
Rectangle rect = new Rectangle(100, 20, Color.RED);
accordion.addEventFilter(MouseEvent.MOUSE_MOVED, evt -> {
Node n = evt.getPickResult().getIntersectedNode();
boolean title = false;
while (n != accordion) {
if (n.getStyleClass().contains("title")) {
// we're in the title
title = true;
break;
}
n = n.getParent();
}
rect.setFill(title ? Color.LIME : Color.RED);
});
Scene scene = new Scene(new VBox(accordion, rect), 100, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
Note that with an event filter for MouseEvent.MOUSE_CLICKED you could simply consume the event, if the pick result is not in a title...
I am trying to get the users input from a text box and set it as a variable but I dont know how. I have written and tried the following code:
btn = new Button("set speed");
TextField speedinput = new TextField();
btn.setOnAction(car.speed = Integer.parseInt(speedinput));
Any help would be great, thanks:)
Check out official docs for TextField and docs for Button:
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
car.speed = Integer.parseInt(speedinput.getText());
}
});
I'm new at javafx but I'm writing an app and I want my "to" value to change depending on which option is chosen in the choicebox but my current code always keeps it at 0..help? I want to be able to change the to depending on state
public void start(Stage primaryStage) {
double to=0;
primaryStage.setTitle("ShCal");
GridPane pane = new GridPane();
` pane.setAlignment(Pos.CENTER);
pane.setHgap(10);
pane.setVgap(10);
pane.setPadding(new Insets(25, 25, 25, 25));
Scene scene = new Scene(pane, 300, 275);
//button
Button button=new Button("to");
pane.add(button, 0, 3);
//Pick state
Label State=new Label("State");
pane.add(State,0,0);
//choicebox
ChoiceBox<String> choicesBox=new ChoiceBox<>();
choicesBox.getItems().addAll("NJ","NY");
pane.add(choicesBox,1,0);
//set default
choicesBox.setValue(null);
button.setOnAction(e->getChoice(choicesBox,to));
primaryStage.setScene(scene);
primaryStage.show();
}
private double getChoice(ChoiceBox<String> choicesBox, double tx) {
String state=choicesBox.getValue();
System.out.print(tx);
if(state=="NJ")
{
tx=10/100;
}
System.out.print(state);
return tx;
}
public static void main(String[] args) {
launch(args);
}
}
That is because your to value is of the primitive type double, defined in the scope of your start method. The method getChoice returns the new value, but you are not updating it.
Here are two approaches that you can try:
Define to as member:
private double to = 0;
private double getChoice(ChoiceBox<String> choicesBox) {
String state=choicesBox.getValue();
if(state=="NJ") {
tx=10/100;
}
}
However I personally would prefer a solution that is more inline with JavaFX: Define the to variable as member property:
private DoubleProperty to = new SimpleDoubleProperty(0);
private double getChoice(ChoiceBox<String> choicesBox) {
String state=choicesBox.getValue();
if(state=="NJ") {
tx.setValue(10/100);
}
}
Doing it this way you can then for example have a label displaying the value without the hassle of requiring to update it on each change:
Label lbl = new Label();
lbl.textProperty().bind(to.asString());
I have a Class that extends the CustomMenuItem. This MenuItems are added to a ContextMenu. Now i need to get the X-Coordinates from the right side of the CustomMenuItem.
The Problem is, that I have no idea how I can get the Coordinates.
The CustMenuItem has no function for getting the Coordinates like getX() or getY().
So how can I solve this problem?
This thing I would like to get:
Here we can see a Sample for a Context Menu (red lines). In the Context Menu are a lot of different CustomMenuItems implemented. Now I would like to get the right top corner Coordinate of the CustomMenuItem.
Thank you for your very nice help.
Before dealing with menu items, let's start saying that a ContextMenu is a popup window, so it has Windowproperties. You can ask for (x,y) left, top origin, and for (w,h).
But you have to take into account the effects, since by default it includes a dropshadow. And when it does, there's an extra space added of 24x24 pixels to the right and bottom.
.context-menu {
-fx-effect: dropshadow( gaussian , rgba(0,0,0,0.2) , 12, 0.0 , 0 , 8 );
}
Since this default dropshadow has a radius of 12px, and Y-offset to the bottom of 8px, the right and bottom coordinates of the context menu, including the 24x24 area, are given by:
X=t.getX()+cm.getWidth()-12-24;
Y=t.getY()+cm.getHeight()-(12-8)-24;
where t could be a MouseEvent relative to the scene, and values are hardcoded for simplicity.
Let's see this over an example. Since you don't say how your custom menu items are implemented, I'll just create a simple Menu Item with graphic and text:
private final Label labX = new Label("X: ");
private final Label labY = new Label("Y: ");
#Override
public void start(Stage primaryStage) {
final ContextMenu cm = new ContextMenu();
MenuItem cmItem1 = createMenuItem("mNext", "Next Long Option",t->System.out.println("next"));
MenuItem cmItem2 = createMenuItem("mBack", "Go Back", t->System.out.println("back"));
SeparatorMenuItem sm = new SeparatorMenuItem();
cm.getItems().addAll(cmItem1,cmItem2);
VBox root = new VBox(10,labX,labY);
Scene scene = new Scene(root, 300, 250);
scene.setOnMouseClicked(t->{
if(t.getButton()==MouseButton.SECONDARY || t.isControlDown()){
// t.getX,Y->scene based coordinates
cm.show(scene.getWindow(),t.getX()+scene.getWindow().getX()+scene.getX(),
t.getY()+scene.getWindow().getY()+scene.getY());
labX.setText("Right X: "+(t.getX()+cm.getWidth()-12-24));
labY.setText("Bottom Y: "+(t.getY()+cm.getHeight()-4-24));
}
});
scene.getStylesheets().add(getClass().getResource("root.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setTitle("Scene: "+scene.getWidth()+"x"+scene.getHeight());
}
private MenuItem createMenuItem(String symbol, String text, EventHandler<ActionEvent> t){
MenuItem m=new MenuItem(text);
StackPane g=new StackPane();
g.setPrefSize(24, 24);
g.setId(symbol);
m.setGraphic(g);
m.setOnAction(t);
return m;
}
If you remove the effect:
.context-menu {
-fx-effect: null;
}
then these coordinates are:
X=t.getX()+cm.getWidth();
Y=t.getY()+cm.getHeight();
Now that we have the window, let's go into the items.
MenuItem skin is derived from a (private) ContextMenuContent.MenuItemContainer class, which is a Region where the graphic and text are layed out.
When the context menu is built, all the items are wrapped in a VBox, and all are equally resized, as you can see if you set the border for the item:
.menu-item {
-fx-border-color: black;
-fx-border-width: 1;
}
This is how it looks like:
So the X coordinates of every item on the custom context menu are the same X from their parent (see above, with or without effect), minus 1 pixel of padding (by default).
Note that you could also go via private methods to get dimensions for the items:
ContextMenuContent cmc= (ContextMenuContent)cm.getSkin().getNode();
System.out.println("cmc: "+cmc.getItemsContainer().getBoundsInParent());
Though this is not recommended since private API can change in the future.
EDIT
By request, this is the same code removing lambdas and css.
private final Label labX = new Label("X: ");
private final Label labY = new Label("Y: ");
#Override
public void start(Stage primaryStage) {
final ContextMenu cm = new ContextMenu();
MenuItem cmItem1 = createMenuItem("mNext", "Next Long Option",action);
MenuItem cmItem2 = createMenuItem("mBack", "Go Back", action);
SeparatorMenuItem sm = new SeparatorMenuItem();
cm.getItems().addAll(cmItem1,cmItem2);
VBox root = new VBox(10,labX,labY);
Scene scene = new Scene(root, 300, 250);
scene.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
if(t.getButton()==MouseButton.SECONDARY || t.isControlDown()){
// t.getX,Y->scene based coordinates
cm.show(scene.getWindow(),t.getX()+scene.getWindow().getX()+scene.getX(),
t.getY()+scene.getWindow().getY()+scene.getY());
labX.setText("Right X: "+(t.getX()+cm.getWidth()-12-24));
labY.setText("Bottom Y: "+(t.getY()+cm.getHeight()-4-24));
}
}
});
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setTitle("Scene: "+scene.getWidth()+"x"+scene.getHeight());
}
private MenuItem createMenuItem(String symbol, String text, EventHandler<ActionEvent> t){
MenuItem m=new MenuItem(text);
StackPane g=new StackPane();
g.setPrefSize(24, 24);
g.setId(symbol);
SVGPath svg = new SVGPath();
svg.setContent("M0,5H2L4,8L8,0H10L5,10H3Z");
m.setGraphic(svg);
m.setOnAction(t);
return m;
}
private final EventHandler<ActionEvent> action = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("action");
}
};