How to combine Strings and SVG within a Combobox? - svg

I have to know how to combine strings and SVGs within a combobox.
For example the SVG should be at the end of a string to show if the String has already been set somewhere.
So an item that already appears should be something like:
"This string already appears somewhere else" + mySVG.
If the string doesnt appear somewhere else the items value is simply the string itself.
Showing the string is no problem, my problem starts at adding the SVG.
My SVG is this:
SVGPath mySVG = new SVGPath();
mySVG.setContent("M0,4.2l1.4,-0.3L3,5.7A13,13 0 0,1 7.4,0H8.5A15,15 0 0,0 4,7.2L2.5,7.5Z");
I hope you understand what I want to do.

You can do it by setting a cell factory to the ComboBox:
public class JavaFxTest2 extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
ComboBox<String> comboBox = new ComboBox<>();
comboBox.getItems().addAll("apple", "banana", "orange");
comboBox.setCellFactory(l -> new ListCell<String>() {
private SVGPath mySVG;
{
setContentDisplay(ContentDisplay.RIGHT);
mySVG = new SVGPath();
mySVG.setContent("M0,4.2l1.4,-0.3L3,5.7A13,13 0 0,1 7.4,0H8.5A15,15 0 0,0 4,7.2L2.5,7.5Z");
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
if ("banana".equals(item)) {
setGraphic(mySVG);
} else {
setGraphic(null);
}
setText(item);
} else {
setGraphic(null);
setText(null);
}
}
});
primaryStage.setScene(new Scene(comboBox));
primaryStage.show();
}
public static final void main(String[] args) {
launch(args);
}
}

Related

How to determine if the text has changed or no in the TextField with JavaFX?

i have TextField contains a text like: "hello!" and this text if it changed to another text should do something the main problem is how to check if this TextField contains new value (new text) instead of the first text wrote should do something. can any body show me how to do that and thanks in advance :)
You can add a ChangeListener to the textProperty of the TextField like this:
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
FlowPane root = new FlowPane();
TextField textField = new TextField();
textField.textProperty().addListener(new ChangeListener<String>(){
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
System.out.println(observable + ", " + oldValue + ", " + newValue);
}
});
root.getChildren().add( textField);
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}

How to add more than one same custom view to a grid layout in android from Java code

I am learning custom views in android.
I made one custom view, with a rectangle and a text. The code of the custom view is:
public class TileGenerator extends View {
// rectangle parameters
private Rect rect = new Rect();
private Paint rectPaint = new Paint();
private Integer rectEndX;
private Integer rectEndY;
private Integer rectStartX;
private Integer rectStartY;
private Integer rectFillColor;
private Float rectTextStartX;
private Float rectTextStartY;
//rectangle text
private String rectText;
private Paint rectTextPaint = new Paint();
public TileGenerator(Context context) {
super(context);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void setTileTitleText(String rectText) {
this.rectText = rectText;
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
rectEndX = getrectEndX();
rectEndY = getrectEndY();
rectStartX = getRectStartX();
rectStartY = getRectStartY();
rectTextStartX = rectEndX/4f + rectStartX;
rectTextStartY = 3.5f * rectEndY/4f + rectStartY;
rectTextPaint.setTextSize(rectEndY/8);
rectTextPaint.setColor(Color.BLACK);
rect.set(rectStartX,rectStartY,rectEndX,rectEndY);
rectPaint.setColor(getRectFillColor());
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(rect, rectPaint);
canvas.drawText(rectText,rectTextStartX,rectTextStartY,rectTextPaint );
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
public Integer getrectEndX() {
return rectEndX;
}
public void setrectEndX(Integer rectEndX) {
this.rectEndX = rectEndX;
}
public Integer getrectEndY() {
return rectEndY;
}
public void setrectEndY(Integer rectEndY) {
this.rectEndY = rectEndY;
}
public Integer getRectStartX() {
return rectStartX;
}
public void setRectStartX(Integer rectStartX) {
this.rectStartX = rectStartX;
}
public Integer getRectStartY() {
return rectStartY;
}
public void setRectStartY(Integer rectStartY) {
this.rectStartY = rectStartY;
}
public Integer getRectFillColor() {
return rectFillColor;
}
public void setRectFillColor(Integer rectFillColor) {
this.rectFillColor = rectFillColor;
}
public String getRectText() {
return rectText;
}
}
After that I created an blank activity. I am doing all with JAVA code. No XML. Then I try to add above custom view to a gridview layout. I want to add two custom views with different text in a horizontal gridview. So far my code is as below:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GridLayout gridLayout = new GridLayout(this);
// first custom view
CustomRectWithText customRectWithText = new CustomRectWithText(this);
customRectWithText.setRectEndX(200);
customRectWithText.setRectEndY(200);
customRectWithText.setRectStartX(2);
customRectWithText.setRectStartY(2);
customRectWithText.setImage(image);
customRectWithText.setRectText("Text");
customRectWithText.setRectFillColor(Color.BLUE);
gridLayout.addView(customRectWithText);
// second custom view
CustomRectWithText customRectWithText1 = new CustomRectWithText(this);
customRectWithText1.setRectEndX(400);
customRectWithText1.setRectEndY(200);
customRectWithText1.setRectStartX(200 + 5);
customRectWithText1.setRectStartY(2);
customRectWithText1.setTileTitleText("Text 1");
customRectWithText1.setRectFillColor(Color.GREEN);
gridLayout.addView(customRectWithText1);
setContentView(gridLayout);
}
But still I am not getting both of the rectangles in a grid view. Only one rectangle is displayed at a time. In above case only first custom view is displayed.
Where am I doing wrong.
All I want is to make a repetitive rectangle of varying labels of any size inside a grid view.
Is this the way to do it. I mean is there any other way around.
I dont want to use ListItems.
Sorry but i do not have enough repo to comment.
But why dont you make an adapter?
Gridview behaves same as listView.
Use adapter to fill your grid.
This is the proper way to populate listView and gridView also.

JavaFX typewriter effect for label

i have some problem with this method. it works fine, but with one little problem. there is too little time among i call this method. so only the last String is printed on a label. but i want that the next String starting printed, only after previous String is finished.
Sorry for my English((
public void some(final String s) {
final Animation animation = new Transition() {
{
setCycleDuration(Duration.millis(2000));
}
protected void interpolate(double frac) {
final int length = s.length();
final int n = Math.round(length * (float) frac);
javafx.application.Platform.runLater(new Runnable() {
#Override
public void run() {
status.setValue(s.substring(0, n));
}
}
);
}
};
animation.play();
}
Use the following code to get a typewriting effect.
public void AnimateText(Label lbl, String descImp) {
String content = descImp;
final Animation animation = new Transition() {
{
setCycleDuration(Duration.millis(2000));
}
protected void interpolate(double frac) {
final int length = content.length();
final int n = Math.round(length * (float) frac);
lbl.setText(content.substring(0, n));
}
};
animation.play();
}
I don't know if it is an effect that you are trying to achieve, but I have created (ugly) demo how you can do this with TimeLine
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
IntegerProperty letters= new SimpleIntegerProperty(0);
Label label = new Label();
Button animate = new Button("animate");
letters.addListener((a, b, c) -> {
label.setText("animate".substring(0, c.intValue()));
});
animate.setOnAction((e)->{
Timeline timeline = new Timeline();
KeyValue kv = new KeyValue(letters, "animate".length());
KeyFrame kf = new KeyFrame(Duration.seconds(3), kv);
timeline.getKeyFrames().add(kf);
timeline.play();
});
BorderPane pane = new BorderPane(label, null, null, animate, null);
primaryStage.setScene(new Scene(pane, 300,300));
primaryStage.show();
}
}

Is there way to conditionally control mouse event in javafx

Trying to control the display of a message based on the value in a TextField. I have a fade away timed message display based on certain value input in the TextField box. Like to have a mouse hover over to display the same message while the input value is still invalid. Looks like the code I have below would still show the message even after the input value has beed changed to be valid.
...
errorLimit.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable,
String oldValue, String newValue) {
if (newValue.trim().length() > 0) {
int enteredValue = Integer.parseInt(newValue);
if (enteredValue <1 || enteredValue >25000) {
errorLimit.setStyle("-fx-text-fill: red");
Dialogs.flash(errorLimit, "The error limit can not be zero or blank or greater than 25,000");
if (errorLimit.getStyle().equals("-fx-text-fill: red")) {
errorLimit.setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
Dialogs.flash(errorLimit, "The error limit can not be zero or blank or greater than 25,000");
}
});
}
} else {
errorLimit.setStyle("-fx-text-fill: black");
}
}
}
});
...
Any idea how I can do this? Thanks!
Just put the if(...) clause inside the handle(...) method...
errorLimit.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable,
String oldValue, String newValue) {
if (newValue.trim().length() > 0) {
int enteredValue = Integer.parseInt(newValue);
if (enteredValue <1 || enteredValue >25000) {
errorLimit.setStyle("-fx-text-fill: red");
Dialogs.flash(errorLimit, "The error limit can not be zero or blank or greater than 25,000");
} else {
errorLimit.setStyle("-fx-text-fill: black");
}
}
}
});
errorLimit.setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
if (errorLimit.getStyle().equals("-fx-text-fill: red")) {
Dialogs.flash(errorLimit, "The error limit can not be zero or blank or greater than 25,000");
}
}
});
I would strongly suggest creating a BooleanProperty to indicate if the field is valid or not, instead of checking the value of the style; but that's a different issue I guess.

How to unselect a selected table row upon second click/selection in javaFX

On my JavaFX table, when I click on a row, it selects that row. Now when I click for the second time on same row which was previously selected, I want to deselect that particular row. Is it possible ? Please share some example code, if its possible.
Below piece of code worked for this requirement.
tableView.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() {
#Override
public TableRow<Person> call(TableView<Person> tableView2) {
final TableRow<Person> row = new TableRow<>();
row.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
final int index = row.getIndex();
if (index >= 0 && index < tableView.getItems().size() && tableView.getSelectionModel().isSelected(index) ) {
tableView.getSelectionModel().clearSelection();
event.consume();
}
}
});
return row;
}
});
Used the same Person class from oracle's table view example. Original answer was given by #James_D in oracle's forum.
Basically you can choose anything invalid as the index. Generally -1 is preferred
table.getSelectionModel().select(-1);
which calls the int select. Alternative:
table.getSelectionModel().select(null);
which calls the object select
if you want to see the whole code used/confirm for this
public class Main extends Application {
#SuppressWarnings("unchecked")
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
TableView<Person> table = new TableView<Person>();
stage.setTitle("Table View Sample");
stage.setWidth(300);
stage.setHeight(500);
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
table.setEditable(true);
TableColumn<Person, String> firstNameCol = new TableColumn<Person, String>("Test Name");
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("name"));
table.getColumns().addAll(firstNameCol);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table);
table.itemsProperty().get().add(new Person("Hans"));
table.itemsProperty().get().add(new Person("Dieter"));
((Group) scene.getRoot()).getChildren().addAll(vbox);
table.getSelectionModel().select(-1);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
public class Person {
final StringProperty name = new SimpleStringProperty();
Person(String name) {
this.name.set(name);
}
public StringProperty nameProperty() { return this.name; }
}
}

Resources