I want to reproduce that combobox in JavaFX
With swing there is a way by using a renderer where HTML code can be passed.
I haven't found a way yet to do it in JAVAFX. I saw the cellFactory but it seems to handle only one line of text.
I tried to use an observableList of WebView. I was able to display the information as desired, but then the onAction was never called. I tried by setting an event and a listener, but nothing worked. I tried the next examples separately.
cbOrderLine.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<WebView>() {
@Override
public void changed(ObservableValue<? extends WebView> arg0, WebView arg1, WebView arg2) {
int uasbdviadn = 0;
if (arg2 != null) {
System.out.println("Selected employee: " + arg2.getId() + " " + uasbdviadn);
}
}
});
cbOrderLine.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent ev) {
int index = cbOrderLine.getSelectionModel().getSelectedIndex();
initComboBox(index);
}
});
this is the code to create my dummy values
private List<WebView> createListFakeOrderLineItem() {
List<WebView> list = new ArrayList<>();
list.add(createFakeOrderLineItem(1));
list.add(createFakeOrderLineItem(2));
list.add(createFakeOrderLineItem(3));
list.add(createFakeOrderLineItem(4));
return list;
}
private WebView createFakeOrderLineItem(int id) {
WebView wv = new WebView();
wv.setPrefSize(684, 90);
ProductionOrderHeader header = new ProductionOrderHeader();
header.setPoNumber("PONumber1234");
ProductionOrderLine line = new ProductionOrderLine();
line.setId(3333);
ManufactureProduct product = new ManufactureProduct();
product.setId(1111);
product.setPartNumber("Product.PartNumber1111");
ManufacturePart part = new ManufacturePart();
part.setId(9999);
part.setPartNumber("Part.Partnumber9999");
part.setHardwareId(666666);
part.setHardwareName("Hardware Name");
OrderLineItem item = new OrderLineItem(id, header, line, part, product);
// return item;
wv.getEngine().loadContent(item.toString());
return wv;
}
This is my OrderLineItem
public class OrderLineItem {
Integer index;
ProductionOrderHeader header;
ProductionOrderLine line;
ManufacturePart part;
ManufactureProduct product;
public OrderLineItem(Integer index, ProductionOrderHeader header, ProductionOrderLine line, ManufacturePart part,
ManufactureProduct product) {
this.index = index;
this.header = header;
this.line = line;
this.part = part;
this.product = product;
}
public Integer getIndex() {
return index;
}
public void setIndex(Integer index) {
this.index = index;
}
public ProductionOrderHeader getHeader() {
return header;
}
public void setHeader(ProductionOrderHeader order) {
this.header = order;
}
public ProductionOrderLine getLine() {
return line;
}
public void setLine(ProductionOrderLine orderLine) {
this.line = orderLine;
}
public ManufacturePart getPart() {
return part;
}
public void setPart(ManufacturePart part) {
this.part = part;
}
public ManufactureProduct getProduct() {
return product;
}
public void setProduct(ManufactureProduct product) {
this.product = product;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("<html>");
sb.append("<table>");
sb.append("<tr>");
sb.append("<td valign=\"middle\" style=\"font-size: 32px; padding-right:5px;\">");
sb.append((index + 1));
sb.append("</td>");
sb.append("<td style=\"border: 1px solid #919191; width:616px; font-size:12px; padding:10px;\">");
sb.append("<b>");
sb.append(header.getPoNumber());
sb.append(" [");
sb.append(line.getId());
sb.append("] </b> -");
sb.append("<b>P/N: </b> #");
sb.append(product.getId());
sb.append("<b> ");
sb.append(product.getPartNumber());
sb.append("</b><br/>");
sb.append("Part: # ");
sb.append(part.getId());
sb.append("<b> ");
sb.append(part.getPartNumber());
sb.append("</b> H/W: # ");
sb.append(part.getHardwareId());
sb.append("<b> ");
sb.append(part.getHardwareName());
sb.append("</b>");
sb.append("</td>");
sb.append("</tr>");
sb.append("</table>");
sb.append("</html>");
return sb.toString();
}
} I'm using JAVAFX 8.
Thanks
I saw the cellFactory but it seems to handle only one line of text.
Firstly your understanding of cellFactory is wrong. And also setting a WebView as your comboBox item is really a horrible idea :). Instead you can build a simple layout and set it as graphic in your cell factory.
And by the way, never set Nodes as items to your controls (ComboBox, ListView..etc), you can just pass your model and build the appropriate layout in cellFactories.
Below is a quick demo to give you an idea of how to build your desired comboBox. Hope this can help you to have a better understanding.
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class MultiLineComboBoxDemo extends Application {
@Override
public void start(Stage stage) throws Exception {
VBox root = new VBox();
root.setSpacing(15);
root.setPadding(new Insets(25));
root.setAlignment(Pos.TOP_LEFT);
Scene sc = new Scene(root, 600, 600);
stage.setScene(sc);
stage.show();
final ObservableList<Person> items = FXCollections.observableArrayList();
for (int i = 1; i < 4; i++) {
items.add(new Person(i,"Name " + i, i + 30, "email" + i + "@test.com"));
}
final ComboBox<Person> comboBox = new ComboBox<>();
comboBox.setItems(items);
comboBox.setCellFactory(param -> new ListCell<Person>() {
@Override
protected void updateItem(Person item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
setGraphic(buildLayout(item));
} else {
setGraphic(null);
}
}
});
comboBox.setButtonCell(new ListCell<Person>(){
@Override
protected void updateItem(Person item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
setGraphic(buildLayout(item));
} else {
setGraphic(null);
}
}
});
comboBox.getSelectionModel().selectedItemProperty().addListener((obs,oldVal,selectedPerson)->{
System.out.println("Name : "+selectedPerson.getName());
// Do what you want..
});
root.getChildren().add(comboBox);
}
private HBox buildLayout(Person person) {
VBox layout = new VBox();
HBox.setHgrow(layout,Priority.ALWAYS);
layout.setStyle("-fx-border-width:1px;-fx-border-color:#444444;");
layout.setSpacing(5);
layout.setPadding(new Insets(2));
HBox topRow = new HBox();
topRow.setSpacing(5);
topRow.getChildren().addAll(getLabel("Name :","bold"),getLabel(person.getName(),"normal"), getLabel("Age :","bold"),getLabel(person.getAge()+"","normal"));
HBox bottomRow = new HBox();
bottomRow.setSpacing(5);
bottomRow.getChildren().addAll(getLabel("Email :","bold"),getLabel(person.getEmail(),"normal"));
layout.getChildren().addAll(topRow, bottomRow);
HBox pane = new HBox();
pane.setAlignment(Pos.CENTER_LEFT);
pane.setSpacing(5);
pane.setPadding(new Insets(2));
Label num = new Label(person.getId()+"");
num.setStyle("-fx-font-size:20px;-fx-font-weight:bold;-fx-text-fill:black;");
pane.getChildren().addAll(num,layout);
return pane;
}
private Label getLabel(String txt, String style){
Label lblName = new Label(txt);
lblName.setStyle("-fx-font-weight:"+style+";-fx-text-fill:black;");
return lblName;
}
public static void main(String[] args) {
Application.launch(args);
}
class Person {
IntegerProperty id = new SimpleIntegerProperty();
StringProperty name = new SimpleStringProperty();
IntegerProperty age = new SimpleIntegerProperty();
StringProperty email = new SimpleStringProperty();
public Person(int id,String name, int age, String email) {
setId(id);
setName(name);
setAge(age);
setEmail(email);
}
public int getId() {
return id.get();
}
public IntegerProperty idProperty() {
return id;
}
public void setId(int id) {
this.id.set(id);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public int getAge() {
return age.get();
}
public IntegerProperty ageProperty() {
return age;
}
public void setAge(int age) {
this.age.set(age);
}
public String getEmail() {
return email.get();
}
public StringProperty emailProperty() {
return email;
}
public void setEmail(String email) {
this.email.set(email);
}
}
}