I have a javaFX 8 pane that contains a Piles TableView. When I select a Pile from the TableView, it queries a database and populates a second TableView with instances of LogExt. This second TableView includes a column of checkboxes mapped to the LogExt.selected boolean property.
When I run the application, I can't select any of the checkboxes.
LogExt:
public class LogExt {
private BooleanProperty selected = new SimpleBooleanProperty();
private Log log;
public LogExt(Log log) {
this.setSelected(false);
this.log = log;
}
public boolean isSelected() {
return selected.get();
}
public BooleanProperty selectedProperty() {
return selected;
}
public void setSelected(boolean selected) {
this.selected.set(selected);
}
public Log getLog() {
return log;
}
public void setLog(Log log) {
this.log = log;
}
}
The controller:
public class CustomOrderController {
#FXML
private RadioButton openRadio;
#FXML
private ToggleGroup stageGroup;
#FXML
private TableView<Pile> pileTableView;
#FXML
private TableColumn<Pile, String> pileNoCol;
#FXML
private TableColumn<Pile, String> speciesCol;
#FXML
private TableColumn<Pile, String> gradeCol;
#FXML
private TableColumn<Pile, String> logTypeCol;
#FXML
private TableColumn<Pile, String> pileStartCol;
#FXML
private TableView<LogExt> logTable;
#FXML
private TableColumn<LogExt, Boolean> selectedCol;
#FXML
private TableColumn<LogExt, String> logSpeciesCol;
#FXML
private TableColumn<LogExt, String> logGradeCol;
#FXML
private TableColumn<LogExt, String> lengthCol;
#FXML
private TableColumn<LogExt, String> diameterCol;
#FXML
private TableColumn<LogExt, String> footageCol;
#FXML
private TextField totalFootageField;
#FXML
private TextField selectedFootageField;
#FXML
private Button clearButton;
#FXML
private TextField reportNoField;
#FXML
private Button saveButton;
private ObservableList openPileList = null;
private ObservableList finishedPileList = null;
private final static Logger LOG = LoggerFactory.getLogger(CustomOrderController.class);
#FXML
protected void initialize() {
super.initialize();
// Set table columns to display proper values.
pileNoCol.setCellValueFactory(new PropertyValueFactory<>("pileNo"));
speciesCol.setCellValueFactory(param -> {
StringProperty stringProperty;
if (param.getValue().getSpecies() != null)
stringProperty = new SimpleStringProperty(param.getValue().getSpecies().getName());
else stringProperty = new SimpleStringProperty("All");
return stringProperty;
});
gradeCol.setCellValueFactory(param -> {
StringProperty grade;
if (param.getValue().getGrade() != null)
grade = new SimpleStringProperty(param.getValue().getGrade().getName());
else grade = new SimpleStringProperty("All");
return grade;
});
logTypeCol.setCellValueFactory(param -> {
StringProperty logType;
if (param.getValue().getLogType() != null)
logType = new SimpleStringProperty(param.getValue().getLogType().getName());
else logType = new SimpleStringProperty("All");
return logType;
});
pileStartCol.setCellValueFactory(param -> {
StringProperty startDate;
if (param.getValue().getPileStart() != null)
startDate = new SimpleStringProperty(
param.getValue().getPileStart().format(DATETIMEFORMATTER));
else startDate = null;
return startDate;
});
// Add listener to catch table selections.
pileTableView.getSelectionModel().selectedItemProperty().addListener(
(observable, oldValue, newValue) -> selectPile());
// Add listener to catch radio button selections.
stageGroup.selectedToggleProperty().addListener((
observable, oldValue, newValue) -> changeList());
// Ensure values entered in the limit/warning fields are acceptable.
reportNoField.setTextFormatter(new TextFormatter<>(INTEGERSTRINGCONVERTER
, 0, POSINTEGERFILTER));
selectedCol.setCellValueFactory(new PropertyValueFactory<>("selected"));
selectedCol.setCellFactory(CheckBoxTableCell.forTableColumn(selectedCol));
logSpeciesCol.setCellValueFactory(param ->
new SimpleStringProperty(param.getValue().getLog().getSpecies().getName()));
logGradeCol.setCellValueFactory(param ->
new SimpleStringProperty(param.getValue().getLog().getLogGrade().getName()));
lengthCol.setCellValueFactory(param ->
new SimpleStringProperty(String.format("%d", param.getValue().getLog().getDeductionLength())));
diameterCol.setCellValueFactory(param ->
new SimpleStringProperty(String.format("%d", param.getValue().getLog().getDeductionDiameter())));
footageCol.setCellValueFactory(param ->
new SimpleStringProperty(String.format("%d", param.getValue().getLog().getNetFootage())));
}
protected void refreshPane() {
// Get the list of piles.
openPileList = FXCollections.observableList(HibernateUtil.getProgramsCommonDB().
query("from Pile where pileEnd = '" + NODATETIME.format(QUERYDATETIMEFORMATTER) + "'"));
finishedPileList = FXCollections.observableList(HibernateUtil.getProgramsCommonDB().
query("from Pile where pileEnd > '" + NODATETIME.format(QUERYDATETIMEFORMATTER) +
"' and consumeStart = '" + NODATETIME.format(QUERYDATETIMEFORMATTER) + "'"));
changeList();
// Set buttons and fields off to start.
clear();
}
private void changeList() {
clear();
if (openRadio.isSelected()) pileTableView.setItems(openPileList);
else pileTableView.setItems(finishedPileList);
}
private void enableWidgets(boolean yes) {
clearButton.setDisable(!yes);
logTable.setDisable(!yes);
reportNoField.setDisable(!yes);
LOG.info("OpenRadio: {}, enable: {}", openRadio.isSelected(), yes);
saveButton.setDisable(true);
}
private void clearWidgets() {
pileTableView.getSelectionModel().clearSelection();
logTable.getItems().clear();
totalFootageField.clear();
selectedFootageField.clear();
reportNoField.clear();
}
#FXML
private void clear() {
clearWidgets();
enableWidgets(false);
}
private void selectPile() {
Pile currentPile = pileTableView.getSelectionModel().getSelectedItem();
if (currentPile != null) {
// Fill the logs list with logs from this pile that have not been consumed.
List oList = HibernateUtil.getLogsDB().query("from Log where pileID = "
+ currentPile.getId()
+ " and (consumeTime is null or consumeTime = '"
+ NODATETIME.format(QUERYDATETIMEFORMATTER) + "')");
List<LogExt> logList = new ArrayList<>();
oList.forEach(o -> {
LogExt logExt = new LogExt((Log) o);
logList.add(logExt);
});
totalFootageField.setText(String.format("%d", logList.stream()
.mapToInt(value -> value.getLog().getNetFootage())
.sum()));
logTable.setItems(FXCollections.observableList(logList));
enableWidgets(true);
}
}
}
You need to enable editing on your table.
logTable.setEditable(true);
possibly on your column as well
selectedCol.setEditable(true);
Related
I have these items:
#FXML
private Button bttnRemove;
#FXML
private TableView<EventsBean> eventsTable;
#FXML
private TableColumn<EventsBean, String> eventCol;
#FXML
private TableColumn<EventsBean, LocalDate> dateCol;
#FXML
private TableColumn<EventsBean, Boolean> doneCol;
#FXML
private TableColumn<EventsBean, String> observationCol;
#FXML
private TableColumn<EventsBean, Boolean> removeCol;
and in removeCol I create checkboxes:
ObservableList<EventsBean> dataList = FXCollections.observableArrayList();
#Override
public void initialize(URL location, ResourceBundle resources) {
removeCol.setCellFactory(CheckBoxTableCell.forTableColumn(removeCol));
removeCol.setCellValueFactory(new PropertyValueFactory<EventsBean, Boolean>("remove"));
eventsTable.setItems(dataList);
bttnAddEvent.setOnAction((ActionEvent e) -> {
text = eventsSelector.getValue().toString();
dataList.add(new EventsBean(text, isoDate, ""));
});
bttnRemove.setOnAction((ActionEvent e) -> {
//code here...
});
}
I want to use bttnRemove to delete a row that have checkbox checked from removeCol.
I find next solution that works very good:
public class EventsBean {
private SimpleStringProperty event;
private SimpleObjectProperty<LocalDate> date;
private SimpleStringProperty observation;
private SimpleBooleanProperty selected;
public EventsBean(String event, LocalDate date, String observation, boolean selected) {
this.event = new SimpleStringProperty(event);
this.date = new SimpleObjectProperty<LocalDate>(date);
this.observation = new SimpleStringProperty(observation);
this.selected = new SimpleBooleanProperty(selected);
}
// the other getters and setters
public boolean getSelected(){
return selectedProperty().get();
}
public SimpleBooleanProperty selectedProperty() {
return this.selected;
}
}
In my Controller class in initialize method:
removeCol.setCellValueFactory(cellData -> cellData.getValue().selectedProperty());
bttnRemove.setOnAction((ActionEvent e) -> {
ObservableList<EventsBean> dataListToRemove = FXCollections.observableArrayList();
for (EventsBean bean : dataList) {
if (bean.getSelected()) {
dataListToRemove.add(bean);
}
}
dataList.removeAll(dataListToRemove);
I am trying to make editable checkbox in a tableview, but it always display unchecked checkbox no matter the "selected" value in the object. Could someone hint me what is wrong in my code please? (it works for all others columns)
DataModel:
public class Kosmetyk
{
private final SimpleIntegerProperty lp;
private final SimpleStringProperty nazwa;
private final SimpleDoubleProperty cena;
private final SimpleStringProperty uwagi;
private final SimpleBooleanProperty czyZakupiono;
public Kosmetyk(Integer lp, String nazwa, Double cena, String uwagi, Boolean czyZakupiono)
{
super();
this.lp = new SimpleIntegerProperty(lp);
this.nazwa = new SimpleStringProperty(nazwa);
this.cena = new SimpleDoubleProperty(cena);
this.uwagi = new SimpleStringProperty(uwagi);
this.czyZakupiono = new SimpleBooleanProperty(czyZakupiono);
}
public Integer getLp()
{
return lp.get();
}
public String getNazwa()
{
return nazwa.get();
}
public Double getCena()
{
return cena.get();
}
public String getUwagi()
{
return uwagi.get();
}
public Boolean getCzyZakupiono()
{
return czyZakupiono.get();
}
public void setNazwa(String nazwa)
{
this.nazwa.set(nazwa);
}
public void setCena(Double cena)
{
this.cena.set(cena);
}
public void setUwagi(String uwagi)
{
this.uwagi.set(uwagi);
}
public void setCzyZakupiono(Boolean czyZakupiono)
{
this.czyZakupiono.set(czyZakupiono);
}
}
TableView controller:
public class SecondController implements Initializable
{
#FXML private TableView<Kosmetyk> tabela;
#FXML private TableColumn<Kosmetyk, Integer> lp;
#FXML private TableColumn<Kosmetyk, String> nazwa;
#FXML private TableColumn<Kosmetyk, Double> cena;
#FXML private TableColumn<Kosmetyk, String> uwagi;
#FXML private TableColumn<Kosmetyk, Boolean> czyZakupiono;// = new TableColumn<>("");
#FXML private Button buttonCancelMain;
#FXML private Button buttonAdd;
#FXML private Button buttonDelete;
String COMMA_DELIMITTER = ";";
String NEW_LINE_SEPARATOR = "\n";
String FILE_HEADER = "Lp.;Nazwa;Cena;Uwagi;Zakupiono";
private static ObservableList<Kosmetyk> ViewAble = FXCollections.observableArrayList();
public void Add(Kosmetyk kosmetyk)
{
ViewAble.add(kosmetyk);
}
#Override
public void initialize(URL location, ResourceBundle resources)
{
tabela.setEditable(true);
lp.setSortable(false);
lp.setCellValueFactory(column-> new ReadOnlyObjectWrapper<Integer>(tabela.getItems().indexOf(column.getValue()) + 1));
nazwa.setCellValueFactory(new PropertyValueFactory<Kosmetyk, String>("nazwa"));
cena.setCellValueFactory(new PropertyValueFactory<Kosmetyk, Double>("cena"));
uwagi.setCellValueFactory(new PropertyValueFactory<Kosmetyk, String>("uwagi"));
czyZakupiono.setCellValueFactory(new PropertyValueFactory<Kosmetyk, Boolean>("czyZakupiono"));
czyZakupiono.setCellFactory(CheckBoxTableCell.forTableColumn(czyZakupiono));
tabela.setItems(ViewAble);
//tabela.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
tabela.getSelectionModel().clearSelection();
nazwa.setCellFactory(TextFieldTableCell.<Kosmetyk>forTableColumn());
nazwa.setOnEditCommit
(
(CellEditEvent<Kosmetyk, String> t) ->
{
((Kosmetyk) t.getTableView().getItems().get(t.getTablePosition().getRow())).setNazwa(t.getNewValue());;
}
);
cena.setCellFactory(TextFieldTableCell.<Kosmetyk, Double>forTableColumn(new DoubleStringConverter()));
cena.setOnEditCommit
(
(CellEditEvent<Kosmetyk, Double> t) ->
{
((Kosmetyk) t.getTableView().getItems().get(t.getTablePosition().getRow())).setCena(t.getNewValue());;
}
);
uwagi.setCellFactory(TextFieldTableCell.<Kosmetyk>forTableColumn());
uwagi.setOnEditCommit
(
(CellEditEvent<Kosmetyk, String> t) ->
{
((Kosmetyk) t.getTableView().getItems().get(t.getTablePosition().getRow())).setUwagi(t.getNewValue());;
}
);
}
}
AddControler (used to get values and then add it to tableview):
public class AddController
{
#FXML private TextField txtNazwa;
#FXML private TextField txtCena;
#FXML private TextField txtUwagi;
#FXML private CheckBox cboxKupione;
#FXML private Button buttonCancelAdd;
#FXML private Button buttonAddWish;
SecondController SC = new SecondController();
public void AddWish()
{
if(txtNazwa.getText().length() > 0 && txtCena.getText().length() > 0 && txtUwagi.getText().length() > 0)
{
SC.Add(new Kosmetyk(0, txtNazwa.getText(), Double.valueOf(txtCena.getText()), txtUwagi.getText(), Boolean.valueOf(cboxKupione.isSelected())));
buttonAddWish.getScene().getWindow().hide();
}
}
}
How can I get a selected item in a row from tableview in javaFX with Sqlite Database.
I am now using this to get the Index of the row:
(...)
#FXML
private ObservableList<UserData> data;
#FXML
private TableView table;
#FXML
private void pressTableAction() {
System.out.println("Selected index: " +table.getSelectionModel().getSelectedIndex());
}
(...)
public void initialize (URL url, ResourceBundle rb) {
try {
con = DataBaseConnection.getConnected();
stat = con.createStatement();
data = FXCollections.observableArrayList();
ResultSet rs = con.createStatement().executeQuery("SELECT * FROM person");
while (rs.next()) {
data.add(new UserData(rs.getInt("p_id"), rs.getString("Name")));
}
column1.setCellValueFactory(new PropertyValueFactory("p_id"));
column2.setCellValueFactory(new PropertyValueFactory("Name"));
table.setItems(null);
table.setItems(data);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Error on Building Data");
}
Public static class UserData {
private IntegerProperty p_id;
private StringProperty Name;
private UserData(Integer p_id, String Name) {
this.p_id = new SimpleIntegerProperty (p_id);
this.Name = new SimpleStringProperty(Name);
}
public IntegerProperty p_idProperty() {
return p_id;
}
public StringProperty NameProperty() {
return Name;
}
}
My db looks like this:
CREATE TABLE person (p_id INTEGER PRIMARY KEY AUTOINCREMENT, Name VARCHAR(30) NOT NULL);
How can I get the p_id or the Name of the row I clicked?
#FXML
private void pressTableAction() {
System.out.println("Selected index: " + table.getSelectionModel().getSelectedIndex());
System.out.println("Selected p_id: " + ????)
}
First, do not use raw types for your table and table columns. Your IDE should be generating lots of warnings for this. So you should do
#FXML
TableView<UserData> table ;
instead of the declaration you have. Similarly the columns should be declared with the appropriate types.
If your model class UserData follows the standard JavaFX properties pattern, it will have a getP_id() method, and you can do
UserData selected = table.getSelectionModel().getSelectedItem();
System.out.println("Selected p_id: "+selected.getP_id());
I am building on Java FX application 3 weeks now and i have a problem i search things about that over the internet but i can't find the solution. I have to Populate Data on rows in a tableview i am getting data from database but i can't put it in the table i have this code that i use in order to take the data from Database.
public ObservableList<ObservableList> GetCustomerData(){
ObservableList<ObservableList> Data = FXCollections.observableArrayList();
try{
ConnectToDB();
DBStatement = DBConnection.createStatement();
DataRetrive = DBStatement.executeQuery("SELECT * FROM Customer");
while (DataRetrive.next()){
ObservableList<String> Row = FXCollections.observableArrayList();
Row.add(String.valueOf(DataRetrive.getInt(1)));
Row.add(DataRetrive.getString(2));
Row.add(DataRetrive.getString(3));
Row.add(DataRetrive.getString(4));
Row.add(DataRetrive.getString(5));
Row.add(DataRetrive.getString(6));
Row.add(DataRetrive.getString(7));
Row.add(DataRetrive.getString(8));
Row.add(DataRetrive.getString(9));
Data.add(Row);
}
CloseDB();
}catch(SQLException e){
e.printStackTrace();
}
return Data;
}
How can I add Data in table cells from this ObservableList?
It is good practice to have a separate class to CRUD operations:
public abstract class CustomerDML {
public static final String TABLE_NAME = "Customer";
QueryClass qc = new QueryClass();
public ObservableList<Map> getCustomerData() {
ObservableList<Map> productList = FXCollections.observableArrayList();
try {
qc.setPs(qc.getConn().prepareStatement("SELECT * FROM " + TABLE_NAME));
qc.setRs(qc.getPs().executeQuery());
while (qc.getRs().next()) {
Map<String, String> product = new HashMap<>();
product.put("cus_id", String.valueOf(qc.getRs().getInt("cus_id")));
product.put("name", qc.getRs().getString("name"));
product.put("age", String.valueOf(qc.getRs().getInt("age")));
product.put("telephone", qc.getRs().getString("telephone"));
productList.add(product);
}
return customerList;
} catch (SQLException ex) {
return null;
}
}
You can implement your QueryClass like below :
public class QueryClass {
private Connection conn;
private PreparedStatement ps;
private ResultSet rs;
//private String query;
public QueryClass() {
conn = DBConnectionClass.myConnection();
}
//getters and setters
...
Lets assume the we have injected something like below to your controller from your fxml:
public class Customer_fxmlController extends CustomerDML implements Initializable {
#FXML
private TableView<Map> cusTable;
#FXML
private TableColumn idCol;
#FXML
private TableColumn nameCol;
#FXML
private TableColumn ageCol;
#FXML
private TableColumn telCol;
...
public void loadCustomers() {
idCol.setCellValueFactory(new MapValueFactory("cus_id"));
nameCol.setCellValueFactory(new MapValueFactory("name"));
ageCol.setCellValueFactory(new MapValueFactory("age"));
telCol.setCellValueFactory(new MapValueFactory("telephone"));
cusTable.setItems(getCustomerData());//Which returns a ObservableList<Map>
}
i followed the instructions from this question to set a ComboBoxCell in the TableView of my application. (How to put ComboBoxTableCell in a TableView?)
The declaration of the Cell works fine, but the comboBox doesn't appear in the table. I think it's like this, because only col1 and col2 are in my model. col3 is not written in my table-entry after the database connection.
I don't know how to takte the ComboBox in the TableView and need your help.
Here is my code:
controller:
package controller;
imports
public class main_controller implements Initializable {
private ObservableList<model> tableData = FXCollections.observableArrayList();
private ObservableList<String> cbValues = FXCollections.observableArrayList("1", "2", "3");
#FXML
private TableView<model> ComboTable;
#FXML
private TableColumn<model, String> col1;
#FXML
private TableColumn<model, String> col2;
#FXML
private TableColumn<model, String> col3;
public main_controller() {
}
#Override
public void initialize(URL location, ResourceBundle resources) {
tableData.clear();
col1.setCellValueFactory(new PropertyValueFactory<model, String>("rCol1"));
col2.setCellValueFactory(new PropertyValueFactory<model, String>("rCol2"));
col3.setCellFactory(ComboBoxTableCell.forTableColumn(new DefaultStringConverter(), cbValues));
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
System.out.println("*** Loaded Oracle-Driver ***");
} catch (ClassNotFoundException e1) {
System.out.println("Driver-Loading failed.");
e1.printStackTrace();
}
try {
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:lukas/1234#10.140.79.56:1521:OTTO");
Statement statement = conn.createStatement();
ResultSet resultset = statement.executeQuery("SELECT NUMMER, DATEN1, DATEN2 FROM LUKAS order by NUMMER");
String Daten1 = "empty";
String Daten2 = "empty";
// Zum einfügen kann man später auf diese Variable zurückgreifen.
int columnIndex;
System.out.println("*** Connected with Database ***");
while (resultset.next()) {
columnIndex = resultset.getInt("NUMMER");
System.out.println("Tabellenindex der Zeile:\t" + columnIndex);
Daten1 = resultset.getString("DATEN1");
Daten2 = resultset.getString("DATEN2");
System.out.println("Daten1:\t " + Daten1 + "\t\t\tDaten2: " + Daten2);
**model entry = new model(Daten1, Daten2);
tableData.add(entry);**
}
System.out.println("*** Database data saved to Observable List named 'data' ***");
ComboTable.setItems(tableData);
System.out.println("*** Table Items setted ***");
statement.close();
} catch (SQLException e) {
System.out.println("Login fehlgeschlagen.");
e.printStackTrace();
}
}
}
model:
package model;
import javafx.beans.property.SimpleStringProperty;
public class model {
private final SimpleStringProperty rCol1;
private final SimpleStringProperty rCol2;
public model(String sCol1, String sCol2) {
this.rCol1 = new SimpleStringProperty(sCol1);
this.rCol2 = new SimpleStringProperty(sCol2);
}
public String getRCol1() {
return rCol1.get();
}
public void setRCol1(String set) {
rCol1.set(set);
}
public String getRCol2() {
return rCol2.get();
}
public void setRCol2(String set) {
rCol2.set(set);
}
}
The application looks like this right now:
Picture
Hope you can help me!
The declaration of the Cell works fine, but the comboBox doesn't
appear in the table.
The combobox of ComboBoxTableCell will be appeared when this cell is in edit mode. To do that you need to set the tableview to editable and then double click the over mentioned cell.
The quote from the ComboBoxTableCell javadoc:
By default, the ComboBoxTableCell is rendered as a Label when not
being edited, and as a ComboBox when in editing mode. The ComboBox
will, by default, stretch to fill the entire table cell.