I've a simple question but I'm stuck with it since hours.
I have a Class UnitMap which extends HashMap
And a Class AttackCommand which contains an UnitMap units = new UnitMap();
I'm attempting to display the value of a MapEntry in my TableView:
#FXML
private TableColumn<AttackCommand, Integer> columnlkav;
#FXML
private TableColumn<AttackCommand, Integer> columnstart;
#FXML
private TableView<AttackCommand> tableview;
#FXML
private TableColumn<AttackCommand, String> columnname;
#FXML
private TableColumn<AttackCommand, Point> columntarget;
private ObservableList<AttackCommand> tableData = FXCollections.observableArrayList();
#Override
public void initialize(URL location, ResourceBundle resources) {
AttackCommand ac = new AttackCommand();
ac.getUnits().put(ConstantsUnit.UNIT_ID_LKAV, 5);
ac.setName("Testname");
tableData.add(ac);
columnname.setCellValueFactory(new PropertyValueFactory<AttackCommand, String>("name"));
columnlkav.setCellValueFactory(new PropertyValueFactory<AttackCommand, Integer>("units"));
tableview.setEditable(true);
columnname.setEditable(true);
tableview.setItems(tableData);
}
So the shown entry in the TableColumn is logically {2=5}, because ConstantsUnit.UNIT_ID_LKAV = 2
How can i display the value proper? I tried a few examples from the net but don't get it
By the way: I don't use SimpleStringProperty for name and don't use other Property Classes in AttackCommand because I want to serialize the Data via EclipseLink to my DerbyDB.
Related
I'm trying to do some reports by hiding some rows from a tableview (I made in scenebuilder) by using a checkbox. If the object from tableview doesn't have in the column a specific String, it becomes invisible. example: By clicking the checkbox, hide all rows that dont have the exact value "Barcelona" in table_adress. I tried to do this, but I keep complicating myself. Any ideas?
the function
#FXML
void CakeRequestsFromBarcelona(ActionEvent event) throws IOException {
for(Object cake:table.getItems()) {
for (TableColumn column : table.getColumns()) {
//not sure how to write it
}
}
}
initialize
#FXML
private TableColumn<CakeRequest, Integer> table_ID;
#FXML
private TableColumn<CakeRequest, String> table_adress;
#FXML
private TableColumn<CakeRequest, String> table_design;
#FXML
private TableColumn<CakeRequest, String> table_flavour;
#FXML
private TableColumn<CakeRequest, String> table_model;
#FXML
private TableColumn<CakeRequest, String> table_name;
#FXML
private TableColumn<CakeRequest, String> table_phonenumber;
#FXML
private TableView<CakeRequest> table;
public void initialize(){
//cakeRequest
table_ID.setCellValueFactory(
p-> new SimpleIntegerProperty(p.getValue().getID()).asObject()
);
table_name.setCellValueFactory(
p -> new SimpleStringProperty(p.getValue().getOwnerName())
);
table_adress.setCellValueFactory(
p -> new SimpleStringProperty(p.getValue().getOwnerAddress())
);
table_phonenumber.setCellValueFactory(
p -> new SimpleStringProperty(p.getValue().getPhoneNumber())
);
table_flavour.setCellValueFactory(
p -> new SimpleStringProperty(p.getValue().getFlavour())
);
table_design.setCellValueFactory(
p -> new SimpleStringProperty(p.getValue().getDesign())
);
table_model.setCellValueFactory(
p -> new SimpleStringProperty(p.getValue().getModel())
);
}
CakeRequest
public class CakeRequest implements Identifiable<Integer>, Serializable{
private int ID;
private String OwnerName;
private String OwnerAddress;
private String PhoneNumber;
private String Model;
private String Flavour;
private String Design;
Use a FilteredList and change the predicate when the check box is checked/unchecked:
private ObservableList<CakeRequest> data = FXCollections.observableArrayList();
private FilteredList<CakeRequest> filteredData = new FilteredList<>(data, request -> true);
public void initialize(){
// existing code...
table.setItems(filteredData);
}
#FXML
void cakeRequestsFromBarcelona(ActionEvent event) {
if (checkBox.isChecked()) {
filteredData.setPredicate(request -> request.getOwnerAddress().contains("Barcelona"));
} else {
filteredData.setPredicate(request -> true);
}
}
i'm trying to set on top of a borderpane an fxml hbox, the borderpane is inside another borderpane that contains all.
The containers are in this form:
Stage-> PincipalBorderPane -> Vbox(Center of MainMenuBorderPane)-> ContentBorderPane(in bottom of Vbox).
Also in the left of my PrincipalBorderPane, I have a sidebar menu that contains buttons, I want to set on the top of ContentBorderPane an fxml document that will be like an small menu to show buttons that would set on the bottom of ContentMenu different panes. The problem is that I don't know how to set an fxml to a borderpane that is inside another borderpane.
public class MenuContentController implements Initializable {
private boolean flag = true;
private boolean flagsc = true;
#FXML
private JFXButton Minbtn;
#FXML
private JFXButton Maxbtn;
#FXML
private JFXButton Closebtn;
#FXML
private JFXButton Sidebarbtn;
#FXML
private JFXTextField Searchtxt;
#FXML
private JFXButton Ingressbtn;
#FXML
private JFXButton Egressbtn;
#FXML
private JFXButton Statusbtn;
#FXML
private BorderPane ContentTools;
#FXML
private void open_sidebar(ActionEvent event) throws IOException {
BorderPane border_pane = (BorderPane) ((Node) event.getSource()).getScene().getRoot();
if (flag) {
//Revisar animación más adelante
Parent sidebar = FXMLLoader.load(getClass().getResource("/app/fxml/Sidebar.fxml"));
sidebar.translateXProperty();
//
border_pane.setLeft(sidebar);
//
Timeline timeline = new Timeline();
KeyValue kv = new KeyValue(sidebar.translateXProperty(),0,Interpolator.EASE_IN);
KeyFrame kf = new KeyFrame(Duration.seconds(10), kv);
timeline.getKeyFrames().add(kf);
timeline.play();
flag = false;
} else {
border_pane.setLeft(null);
flag = true;
}
}
**#FXML
public void open_admintools_priv(ActionEvent event) throws IOException{
ContentTools = new BorderPane();
BorderPane bp = (BorderPane) ContentTools;
if (flagsc) {
Parent admintools = FXMLLoader.load(getClass().getResource("/app/fxml/AdminTools.fxml"));
bp.setTop(admintools);
flagsc=false;
} else {
ContentTools.setTop(null);
flagsc = true;
}
System.out.println(flagsc);**
}
The method open_admintools_priv should to set visible on top of ContentTools(ContentBorderpane) the Admintools.fxml by pressing a button in another fxml(sidebar.fxml) that I set on the left of my PrincipalBorderPane with the method open_sidebar, that I call creating a new controller of MenuContentController in the SidebarController:
public class SidebarController implements Initializable {
private boolean flagsc = true;
#FXML
private JFXButton condominiobtn;
#FXML
private JFXButton adminbtn;
#FXML
private JFXButton finanzasbtn;
#FXML
private JFXButton reportesbtn;
#FXML
private JFXButton confbtn;
#FXML
private void open_admintools(ActionEvent event) throws IOException{
MenuContentController aux = new MenuContentController();
aux.open_admintools_priv(event);
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
Another problem is that by this way, at the moment I create a MenuContentController, the variable flag is always on true, this variable I use it to set the fxml in borderpane when flag is true, or quit it when flag is false. I don't know if creating an instance of a controller is the way to acces to the objects of that fxml, thanks for your time.
I have a 2 columns TableView that I would like to use to display a content of Map (Key, Value).
The issue is that nothing is getting displayed in the TableView.
#FXML
private TableView tv;
#FXML
private TableColumn<Map.Entry<Integer, String>, Integer> tcKey;
#FXML
private TableColumn<Map.Entry<String, String>, String> tcValue;
ObservableMap<Integer, String> map;
ObservableList<Map.Entry<Integer, String>> observableList;
int i = 0;
#FXML
private void handleButtonAction(ActionEvent event) {
map.put(i++, "value" + i++);
for (Map.Entry<Integer, String> entry : map.entrySet()) {
System.out.println("Key: " + entry.getKey() + " Value: " + entry.getValue());
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
map = FXCollections.observableHashMap();
observableList = FXCollections.observableArrayList(map.entrySet());
tv.setItems(observableList);
tv.getColumns().setAll(tcKey, tcValue);
}
}
These definitions are definitely wrong.
#FXML
private TableColumn<Map.Entry<Integer, String>, String> tcKey;
#FXML
private TableColumn<Map.Entry<String, String>, String> tcValue;
I would assume the correct definition is:
#FXML
private TableColumn<Map.Entry<Integer, String>, Integer> tcKey;
#FXML
private TableColumn<Map.Entry<Integer, String>, String> tcValue;
Do note that although you are using ObservableList and ObservableMap, the actual result would be that the table would not respond to any changes in the ObservableMap. If you are expecting the map to change during runtime, then you must do more than this (by using MapChangeListener).
My application contains a tabpane, each tab is a nested fxml with controller included.
Each fxml file have a tableview that retrieve data from a microsoft access database.
Some of the tables that only have string columns work and get populated but another one(Demandes) that have a integer column and a localdate column wont populate.and i don't know what's causing the problem.
here the nested controller of "Demandes" tab:
public class DemandesController{
#FXML
private TableView<Demande> demandesTable;
#FXML
private TableColumn<Demande, Integer> numColumn;
#FXML
private TableColumn<Demande, String> societeColumn;
#FXML
private TableColumn<Demande, LocalDate> dateDemandeColumn;
#FXML
private TableColumn<Demande, LocalDate> dateSignatureColumn;
#FXML
private TableColumn<Demande, String> villeColumn;
private ObservableList<Demande> demandes = FXCollections.observableArrayList();
private MainApp mainApp;
String BD_URL = mainApp.getBdUrl();
public DemandesController(){
}
public ObservableList<Demande> getBulletins(){
return demandes;
}
#FXML
private void initialize() {
getDemandesData();
numColumn.setCellValueFactory(cellData -> cellData.getValue().numDemandeProperty().asObject());
societeColumn.setCellValueFactory(cellData -> cellData.getValue().societeProperty());
dateDemandeColumn.setCellValueFactory(cellData -> cellData.getValue().dateDemandeProperty());
dateSignatureColumn.setCellValueFactory(cellData -> cellData.getValue().dateSignatureProperty());
villeColumn.setCellValueFactory(cellData -> cellData.getValue().villeProperty());
}
public void setMainApp(MainApp mainApp){
this.mainApp = mainApp;
demandesTable.setItems(getBulletins());
}
public void getDemandesData(){
Task task = new Task<Void>() {
#Override
protected Void call() throws Exception {
try (Connection con = DriverManager.getConnection(BD_URL)) {
Statement stmt = con.createStatement();
ResultSet res = stmt.executeQuery("SELECT * FROM [Demandes-tab]");
while (res.next()) {
int numDemande = res.getInt(1);
String societe = res.getString(2);
LocalDate dateDemande = res.getDate(3)
.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate dateSignature = res.getDate(4)
.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
String ville = res.getString(5);
demandes.add(new Demande(numDemande,societe,dateDemande,
dateSignature,ville));
}
}return null;
}
};
new Thread(task).start();
} }
and the parent controller that initialise the nested fxmls and controllers :
public class TabsController{
private MainApp mainApp;
#FXML private AnchorPane Bulletins;
#FXML private BulletinsController BulletinsController;
#FXML private AnchorPane Demandes;
#FXML private DemandesController DemandesController;
#FXML private AnchorPane Personneltest;
#FXML private PersonnelController PersonneltestController;
#FXML private AnchorPane Personnel;
#FXML private PersonnelController PersonnelController;
#FXML private AnchorPane Produit;
#FXML private ProduitController ProduitController;
#FXML private AnchorPane Societes;
#FXML private SocietesController SocietesController;
#FXML
private void initialize() {
}
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
BulletinsController.setMainApp(mainApp);
PersonneltestController.setMainApp(mainApp);
DemandesController.setMainApp(mainApp);
} }
also this was added in the right place :
<Tab text="Demandes">
<content>
<fx:include fx:id="Demandes" source="Demandes.fxml" />
</content>
</Tab>
if someone can tell me why the tableview won't populate that will be a big help. thank you.
ps: oh also i removed the database url just to see if it matters and nothing changed. does that mean that it doesn't connect to the database at all?
I'm making a program to manage and show data about airports, their flights and so on.
The fact is that I have a tableView (in javafx) with several tableColumns, and I want to show some information (destiny, origin, company, etc) on each column so I typed this:
#FXML
private TableColumn<Flight, String> destinoCol;
#FXML
private TableColumn<Flight, String> numCol;
#FXML
private MenuButton aeropuerto;
#FXML
private MenuButton tipo;
#FXML
private Button filtrar;
#FXML
private TableColumn<Flight, LocalTime> horaCol;
#FXML
private Button este;
#FXML
private DatePicker fecha;
#FXML
private TableColumn<Flight, String> origenCol;
#FXML
private Label retrasoLabel;
#FXML
private ImageView companiaImg;
#FXML
private VBox detalles;
#FXML
private Button todos;
#FXML
private ImageView avionImg;
#FXML
private Label tipoLabel;
private mainVuelos m;
private List<Airport> aeropuertos;
private Data data;
#FXML
void initialize() {
data = Data.getInstance();
aeropuertos = data.getAirportList();
List<MenuItem> ItemAeropuertos = new LinkedList<MenuItem>();
for (int i = 0; i < aeropuertos.size(); i++) {
MenuItem item = new MenuItem(aeropuertos.get(i).getName());
item.setOnAction((event) -> cambiarAer(event));
ItemAeropuertos.add(item);
}
aeropuerto.getItems().setAll(ItemAeropuertos);
destinoCol.setCellValueFactory(cellData -> cellData.getValue().getDestiny());
}
The method getDestiny(), as it says returns the destiny of a specific flight as a String so obviously I cannot use the last instruction, it says
cannot convert from String to ObservableValue<String>
but I don't really know how to solve it in order to be able to show the destinies on that column.
According to the Javadocs, setCellValueFactory(...) expects a Callback<CellDataFeatures<Flight, String>, ObservableValue<String>>, i.e a function that takes a CellDataFeatures<Flight, String> as its parameter, and results in an ObservableValue<String>.
As the error message says, your function evaluates to a String (cellData.getValue().getDestiny()), which is not the correct type.
You have two choices, depending on your actual requirements.
Either you can create something on the fly that is of the correct type: the easiest thing to use is a ReadOnlyStringWrapper:
destinoCol.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getDestiny()));
This will display the correct value, but won't be nicely "wired" to the property of the flight object. If your table is editable, edits won't automatically propagate back to the underlying object, and changes to the underlying object from elsewhere won't automatically update in the table.
If you need this functionality (and this is probably a better approach anyway), you should implement your model class Flight to use JavaFX properties:
public class Flight {
private final StringProperty destiny = new SimpleStringProperty();
public StringProperty destinyProperty() {
return destiny ;
}
public final String getDestiny() {
return destinyProperty().get();
}
public final void setDestiny(String destiny) {
destinyProperty().set(destiny);
}
// similarly for other properties...
}
and then you can do
destinoCol.setCellValueFactory(cellData -> cellData.getValue().destinyProperty());
I am a bit late I think, but this might help others.
You can have cade as below
destinoCol.setCellValueFactory(cellData -> cellData.getValue().destinyProperty().asObject());
This code will work for property other than string, as I had problem with "LongProperty".