I'm trying to get the value of the editable table using javaFX Scene builder, but I can not get the updated value.
I' have table with 2 columns: name column and value column.
whenever the user change on of the value of value column, I want to react.
But when I print the new change value, it always displays the default value.
public class MesssageField
{
private final StringProperty fieldName;
private final StringProperty fieldValue;
public MesssageField(String fieldName, String fieldValue) {
this.fieldName = new SimpleStringProperty(fieldName);
this.fieldValue = new SimpleStringProperty(fieldValue);
}
public StringProperty getFieldNameProperty() {
return fieldName;
}
public StringProperty getFieldValueProperty() {
return fieldValue;
}
public void setFieldValue(String fieldValue) {
this.fieldValue.set(fieldValue);
}
public String getFieldName() {
return fieldName.get();
}
public String getFieldValue() {
return fieldValue.get();
}
}
The controller class has:
private static ObservableList<MesssageField> obserListMsgsField;
#FXML
private TableView<MesssageField> msgTableView;
#FXML
private TableColumn<MesssageField, String> fieldNameColumn;
#FXML
private TableColumn<MesssageField, String> fieldValueColumn;
#Override
public void initialize(URL arg0, ResourceBundle arg1)
{
// create List Of fields
obserListMsgsField = FXCollections.observableArrayList();
fieldValueColumn.setCellFactory(TextFieldTableCell.forTableColumn());
// Initialize the person table with the two columns.
fieldNameColumn.setCellValueFactory(cellData -> cellData.getValue().getFieldNameProperty());
fieldValueColumn.setCellValueFactory(cellData -> cellData.getValue().getFieldValueProperty());
}
the onEditFieldValueCommit method attached to "on edit commit"
#FXML
public void onEditFieldValueCommit() {
MesssageField messageField = msgTableView.getSelectionModel().getSelectedItem();
// get field name
String fieldName = messageField.getFieldName();
// get field value
String valueString = messageField.getFieldValue();
// debug print
System.out.print("\n[DEBUG] Field Name = " + fieldName + " = " + valueString);
}
But the output is always the default value and not the changed value.
Thanks
In your onEditFieldValueCommit method you are not using the parameter required, and then you are not updating the list obserListMsgsField.
First, you need to add a parameter of the type TableColum.CellEditEvent, which is the event that is fired when a user performs an edit on the table cell.
Then you just get the new value or the row affected, updating the list:
#FXML
public void onEditFieldValueCommit(TableColumn.CellEditEvent<MesssageField, String> t) {
t.getRowValue().setFieldValue(t.getNewValue());
System.out.print("\n[DEBUG] Field Name = " + t.getRowValue().getFieldName() +
" = " + t.getRowValue().getFieldValue());
}
Related
I am using a custom TextFieldTableCell in JavaFX 8 to allow users to edit the text field. When the user hits Enter, however, I want to check to see if the text field equals a certain value. If it does equal this certain value, I do not want the entry to save and for it to revert to the text it had before the user started editing. Is there a method I can override to produce this result? I cannot find one that fits what I am looking for.
Thank you in advance!
Since the model is bound to the cell's data, you can do the validation and reset part in the modell class, in your case in the Person class.
Here is a simple example how you can do it:
public class Controller implements Initializable {
#FXML
private TableColumn<Model, String> name;
#FXML
private TableView<Model> tableView;
#Override
public void initialize(URL location, ResourceBundle resources) {
name.setCellValueFactory(data -> data.getValue().nameProperty());
name.setCellFactory(cell -> new TextFieldTableCell<>(new StringConverter<String>() {
#Override
public String toString(String object) {
return object;
}
#Override
public String fromString(String string) {
return string;
}
}));
tableView.setEditable(true);
tableView.setItems(FXCollections.observableArrayList(new Model("Test")));
}
private class Model {
private StringProperty name;
ChangeListener<String> nameChangeListener = (observable, oldValue, newValue) -> {
if (!newValue.matches("[A-Z][a-zA-Z]*")) { // a validation example insert your here.
this.name.set(oldValue);
}
};
public Model(String name) {
this.name = new SimpleStringProperty(name);
this.name.addListener(nameChangeListener);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
}
}
From your description I assume that you are talking about an editable cell in a table view.
If that's the case, the following example should be working for you. You can use the .setOnEditCommit() method to add an event handler to the colum for which you would like to check the entered value.
//Create table
TableView<Person> table = new TableView<Person>();
table.setEditable(true);
//Create column
TableColumn<Person, String> column = new TableColumn<Person, String>("Full Name");
column.setCellValueFactory(new PropertyValueFactory<>("fullName"));
column.setCellFactory(TextFieldTableCell.<Person> forTableColumn());
column.setMinWidth(200);
column.setOnEditCommit(event -> {
//Get entered value
String newFullName = event.getNewValue();
//Get selected position
TablePosition<Person, String> pos = event.getTablePosition();
//Get row of position
int row = pos.getRow();
//Get data from selected row
Person person = event.getTableView().getItems().get(row);
//Check if text equals ...
if (newFullName.equals("Test")) {
person.setFullName(newFullName);
} else {
person.setFullName(event.getOldValue());
table.refresh();
}
});
So the thing that i want to happen, is making the tableview update the data in the database after editing it. I wanted to use the SetOnEditCommit method here. The cell editing does work, but it never gets updated, with no error either. In the first place im a bit clueless if this method is actually efficient (probably not), since its hard to find some sources for this specific thing. And the sources that i found weren't really helpful. So it would be nice if someone had an idea as to why it doesn't update, or maybe provide an alternate option here.
The mentioned part:
columnType.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<UserDetails, String>>() {
#Override
public void handle(TableColumn.CellEditEvent<UserDetails, String> event) {
updataData();
}
});
tableview.setItems(null);
tableview.setItems(data);
}
public void updataData() {
Connection connection = null;
try {
connection = DriverManager.getConnection("jdbc:mysql://37.128.148.113:3306/FYS", "FYS", "Kcj8g87~");
Statement con = connection.createStatement();
//connection
TablePosition pos = tableview.getSelectionModel().getSelectedCells().get(0);
int row = pos.getRow();
TableColumn col = pos.getTableColumn();
String data1 = (String) col.getCellObservableValue(row).getValue();
//cell
UserDetails row1 = tableview.getSelectionModel().getSelectedItem();
c1 = row1.getId();
//row
//tableview variables
con.execute("UPDATE gevonden_bagage SET type = 'data1' WHERE koffer_id = 'c1' ");
//Query
} catch (SQLException ex) {
System.err.println("Error" + ex);
}
}
//get connection, get celldata, get id data from first row, update cell with selected id
full controller class:
package simple;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
/**
*
* #author admin
*/
public class FXMLUserController extends SimpleController implements Initializable {
#FXML
public TableView<UserDetails> tableview;
#FXML
public TableColumn<UserDetails, String> columnId;
#FXML
public TableColumn<UserDetails, String> columnType;
#FXML
public TableColumn<UserDetails, String> columnKleur;
#FXML
public TableColumn<UserDetails, String> columnLuchthaven;
#FXML
public TableColumn<UserDetails, String> columnKenmerken;
#FXML
public TableColumn<UserDetails, String> columnStatus;
#FXML
public TableColumn<UserDetails, String> columnDatum;
#FXML
private Button btnLoad;
//declare observable list for database data
private ObservableList<UserDetails> data;
private DbConnection dc;
String c1;
#FXML
//strings for getRow method
#Override
public void initialize(URL url, ResourceBundle rb) {
dc = new DbConnection();
loadDataFromDatabase();
}
#FXML
public void loadDataFromDatabase() {
try {
Connection conn = dc.Connect();
data = FXCollections.observableArrayList();
// Execute query and store result in a resultset
ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM gevonden_bagage");
while (rs.next()) {
//get strings
data.add(new UserDetails(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5),
rs.getString(6), rs.getString(7)));
}
} catch (SQLException ex) {
System.err.println("Error" + ex);
}
//Set cell values to tableview.
tableview.setEditable(true);
tableview.getSelectionModel().setCellSelectionEnabled(true);
columnType.setCellFactory(TextFieldTableCell.forTableColumn());
columnKleur.setCellFactory(TextFieldTableCell.forTableColumn());
columnLuchthaven.setCellFactory(TextFieldTableCell.forTableColumn());
columnKenmerken.setCellFactory(TextFieldTableCell.forTableColumn());
columnStatus.setCellFactory(TextFieldTableCell.forTableColumn());
columnDatum.setCellFactory(TextFieldTableCell.forTableColumn());
//makes columns editable
columnId.setCellValueFactory(new PropertyValueFactory<>("id"));
columnType.setCellValueFactory(new PropertyValueFactory<>("type"));
columnKleur.setCellValueFactory(new PropertyValueFactory<>("kleur"));
columnLuchthaven.setCellValueFactory(new PropertyValueFactory<>("luchthaven"));
columnKenmerken.setCellValueFactory(new PropertyValueFactory<>("kenmerken"));
columnStatus.setCellValueFactory(new PropertyValueFactory<>("status"));
columnDatum.setCellValueFactory(new PropertyValueFactory<>("datum"));
columnType.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<UserDetails, String>>() {
#Override
public void handle(TableColumn.CellEditEvent<UserDetails, String> event) {
updataData();
}
});
tableview.setItems(null);
tableview.setItems(data);
}
public void updataData() {
Connection connection = null;
try {
connection = DriverManager.getConnection("jdbc:mysql://37.128.148.113:3306/FYS", "FYS", "Kcj8g87~");
Statement con = connection.createStatement();
//connection
TablePosition pos = tableview.getSelectionModel().getSelectedCells().get(0);
int row = pos.getRow();
TableColumn col = pos.getTableColumn();
String data1 = (String) col.getCellObservableValue(row).getValue();
//cell
UserDetails row1 = tableview.getSelectionModel().getSelectedItem();
c1 = row1.getId();
//row
//tableview variables
con.execute("UPDATE gevonden_bagage SET type = 'data1' WHERE koffer_id = 'c1' ");
//Query
} catch (SQLException ex) {
System.err.println("Error" + ex);
}
}
//get connection, get celldata, get id data from first row, update cell with selected id
#FXML
public void getRow() {
TablePosition pos = tableview.getSelectionModel().getSelectedCells().get(0);
int row = pos.getRow();
TableColumn col = pos.getTableColumn();
// this gives the value in the selected cell:
String data1 = (String) col.getCellObservableValue(row).getValue();
System.out.println(data1);
//CURRENTLY UNUSED METHOD
}
}
Model class:
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
/**
*
* #author admin
*/
public class UserDetails {
private final StringProperty id;
private final StringProperty type;
private final StringProperty kleur;
private final StringProperty luchthaven;
private final StringProperty kenmerken;
private final StringProperty status;
private final StringProperty datum;
//Default constructor
public UserDetails(String id, String type, String kleur, String luchthaven, String kenmerken, String status, String datum) {
this.id = new SimpleStringProperty(id);
this.type = new SimpleStringProperty(type);
this.kleur = new SimpleStringProperty(kleur);
this.luchthaven = new SimpleStringProperty(luchthaven);
this.kenmerken = new SimpleStringProperty(kenmerken);
this.status = new SimpleStringProperty(status);
this.datum = new SimpleStringProperty(datum);
}
//getters
public String getId() {
return id.get();
}
public String getType() {
return type.get();
}
public String getKleur() {
return kleur.get();
}
public String getLuchthaven() {
return luchthaven.get();
}
public String getKenmerken() {
return kenmerken.get();
}
public String getStatus() {
return status.get();
}
public String getDatum() {
return datum.get();
}
//setters
public void setId(String value) {
id.set(value);
}
public void setType(String value) {
type.set(value);
}
public void setKleur(String value) {
kleur.set(value);
}
public void setLuchthaven(String value) {
luchthaven.set(value);
}
public void setKenmerken(String value) {
kenmerken.set(value);
}
public void setStatus(String value) {
status.set(value);
}
public void setDatum(String value) {
datum.set(value);
}
//property values
public StringProperty idProperty() {
return id;
}
public StringProperty typeProperty() {
return type;
}
public StringProperty kleurProperty() {
return kleur;
}
public StringProperty luchthavenProperty() {
return luchthaven;
}
public StringProperty kenmerkenProperty() {
return kenmerken;
}
public StringProperty statusProperty() {
return status;
}
public StringProperty datumProperty() {
return datum;
}
}
From the TableView documentation:
By default the TableColumn edit commit handler is non-null, with a
default handler that attempts to overwrite the property value for the
item in the currently-being-edited row. It is able to do this as the
Cell.commitEdit(Object) method is passed in the new value, and this is
passed along to the edit commit handler via the CellEditEvent that is
fired. It is simply a matter of calling
TableColumn.CellEditEvent.getNewValue() to retrieve this value.
It is very important to note that if you call
TableColumn.setOnEditCommit(javafx.event.EventHandler) with your own
EventHandler, then you will be removing the default handler. Unless
you then handle the writeback to the property (or the relevant data
source), nothing will happen.
So the problem is that by setting the onEditCommit on columnType, you remove the default handler that actually updates typeProperty in the UserDetails instance. Consequently
String data1 = (String) col.getCellObservableValue(row).getValue();
gives the old value, and your update to the database won't change anything.
Additionally, you have errors in the way you create the SQL statement. You are making the id in the WHERE clause the literal value 'c1' (instead of the value contained in the variable c1, and similarly setting the value of type to the literal value 'data1', instead of the value in the variable data1.
Here is a fix, along with some simplification of the code and some better practices for avoiding SQL injection attacks:
columnType.setOnEditCommit(event -> {
UserDetails user = event.getRowValue();
user.setType(event.getNewValue());
updateData("type", event.getNewValue(), user.getId());
});
and then
private void updateData(String column, String newValue, String id) {
// btw it is way better to keep the connection open while the app is running,
// and just close it when the app shuts down....
// the following "try with resources" at least makes sure things are closed:
try (
Connection connection = DriverManager.getConnection("jdbc:mysql://37.128.148.113:3306/FYS", "FYS", "Kcj8g87~");
PreparedStatement stmt = connection.prepareStatement("UPDATE gevonden_bagage SET "+column+" = ? WHERE koffer_id = ? ");
) {
stmt.setString(1, newValue);
stmt.setString(2, id);
stmt.execute();
} catch (SQLException ex) {
System.err.println("Error");
// if anything goes wrong, you will need the stack trace:
ex.printStackTrace(System.err);
}
}
I am newbie in building javafx MVVM app.
I've created a simple ViewModel:
public class PersonViewModel {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty age = new SimpleIntegerProperty();
public PersonViewModel() {}
// getters and setters
}
and simple View:
public class PersonView implements Initializable {
#FXML
TextField name;
#FXML
TextField age;
#FXML
Button ok;
#Override
public void initialize(URL location, ResourceBundle resources) {
PersonViewModel viewModel = new PersonViewModel();
name.textProperty().bindBidirectional(viewModel.name);
age.textProperty().bindBidirectional(viewModel.age);
}
}
Can you give me any idea how to make age validation? F.e. I wanna not to allow user to put characters into age (TextField) except [a-zA-Z]. And the main idea of my question to make this validation in ViewModel) Help me pls.
P.S. I wanna make it not using not standard javafx components.
You can use a TextFormatter both to filter input in a text input control, and to convert the text into a value of a specific type. If you want the view model to define the validation rules, then define a method in there representing the validation, and delegate to that method in the filter definition for the TextFormatter. For example:
public class PersonViewModel {
private final StringProperty name = new SimpleStringProperty();
public StringProperty nameProperty() {
return name ;
}
public final String getName() {
return nameProperty().get();
}
public final void setName(String name) {
nameProperty.set(name);
}
private final IntegerProperty age = new SimpleIntegerProperty();
public IntegerProperty ageProperty() {
return age ;
}
public final int getAge() {
return ageProperty().get();
}
public final void setAge(int age) {
ageProperty.set(age);
}
public boolean validAgeInput(String input) {
// must support partial entry while editing, including empty string
// accept any integer from 0 - 135 (arbitrary upper bound example)
String regex = "([0-9]{0,2})|(1[0-2][0-9])|(13[0-5])";
return input.matches(regex);
}
}
Now you can do:
public class PersonView implements Initializable {
#FXML
TextField name;
#FXML
TextField age;
#FXML
Button ok;
#Override
public void initialize(URL location, ResourceBundle resources) {
PersonViewModel viewModel = new PersonViewModel();
UnaryOperator<Change> filter = change -> {
if (viewModel.validAgeInput(change.getControlNewText()) {
// accept
return change ;
} else {
// reject
return null ;
}
};
TextFormatter<Integer> ageFormatter = new TextFormatter<>(new IntegerStringConverter(), 0, filter);
age.setTextFormatter(ageFormatter);
ageFormatter.valueProperty().bindBidirectional(viewModel.ageProperty().asObject());
name.textProperty().bindBidirectional(viewModel.nameProperty());
}
}
The filter defined here will only accept input in the control if it matches the rule defined by the method in the PersonViewModel. The valueProperty() of the TextFormatter represents the text in the TextField after passing it to the IntegerStringConverter: this is bound bidirectionally to the ageProperty() in the model. (The call to asObject() effectively just converts between an IntegerProperty and an ObjectProperty<Integer>.)
I've been stuck at a seemingly simple problem for hours and I just can't find the solution. I'm trying to implement a very simple Forum in Java and I'm trying to load the entrys at the moment.
My forum is a JList that is filled with JPanels and that accepts entries via the JLists DefaultListModel and the addMessage method. So if I add an entry without the database it looks like this:
MessageList m = new MessageList();
m.addMessage("NAME AUTOR", "<html><body style='width: 675px;'>Lorem ipsum dolor sit amet.", "22.01.13", "SOA");
The messageList class looks like this:
public class MessageList extends JList{
DefaultListModel messageModel = new DefaultListModel();
MessageRenderer messageRenderer = new MessageRenderer();
public MessageList( ){
this.setCellRenderer(messageRenderer);
this.setModel(messageModel);
}
public void addMessage(String author, String text, String date, String tag){
messageModel.addElement(new Message(author, text, date, tag));
}
}
I've also written the Code for getting an ArrayList (called allBtr) with the Message Objects (called ConBeitrag) from the database:
ArrayList<ConBeitrag> allBtr = new ArrayList<ConBeitrag>();
ConBeitrag conBtr = new ConBeitrag();
try {
allBtr = conBtr.getAllBtr();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The message objects look like this:
public class ConBeitrag {
private int beitragid;
private int projektid;
private int mitarbeiterid;
private String beitragText;
private String erstellt_am;
private String geaendert_am;
private String schlagwort1;
private String schlagwort2;
private MdBeitrag mdBtr = new MdBeitrag();
public ConBeitrag (){
}
public ConBeitrag(int beitragid, int projektid, int mitarbeiterid, String beitragText, String erstellt_am, String geaendert_am){
this.beitragid = beitragid;
this.projektid = projektid;
this.mitarbeiterid = mitarbeiterid;
this.erstellt_am = erstellt_am;
this.geaendert_am = geaendert_am;
this.beitragText = beitragText;
this.schlagwort1 = schlagwort1;
this.schlagwort2 = schlagwort2;
}
public ArrayList<ConBeitrag> getAllBtr() throws SQLException{
MdBtrInterface modInt;
modInt = new MdBeitrag();
ArrayList<ConBeitrag> AlBtr = modInt.getAllBtr();
for(ConBeitrag object: AlBtr){
System.out.println(object.beitragText);
}
return AlBtr;
}
}
Now what would be the smartest way to get the ArrayList into a form that I can pass into the addMessage method? I've kind of approached this from the GUI end, then from the database end, and now I'm stuck in the middle.
Overwritten toString() method:
#Override
public String toString() {
return mitarbeiterid + beitragstext + erstellt_am + schlagwort1 + schlagwort2;
}
"The messages are stored inside the ArrayList as Objects if that helps. So if I run "System.out.println(allBtr);" it gives me "[ConBeitrag#48f4104f, ConBeitrag#f5ad7f4, ConBeitrag#1517dc0c]"
You need to override the toString method in your ConGeitrag class. Something like this.
public class ConBeitrag {
...
#Override
public String toString(){
return author + ", " + text + ", " + date + ", " + tag;
}
}
You can make the return any format you want. Test this one out and make changes as desired to the format.
Try this out as a Helper method (after you've overridden the toString)
public JList createJList(ResultSet rs){
DefaultListModel model = new DefaultListModel();
while (rs.next()){
String author = rs.getString("author"); // Just an example. You may
String text = rs.getString("text"); // need to retrieve your
String date = rs.getString("date"); // data differently
String tag = rs.getString("tag");
Message message = new Message(author, text, date, tag);
model.addElement(message);
}
JList list = new JList(model);
return list;
}
I don't really see a need for a Custom JList for this situation.
Test run: output : 3testtestnullnull. Besides the formatting, it works fine
public class ConBeitragTest {
public static void main(String[] args) {
ConBeitrag con = new ConBeitrag(1, 2, 3, "test", "test", "test");
System.out.println(con);
}
}
class ConBeitrag {
private int beitragid;
private int projektid;
private int mitarbeiterid;
private String beitragText;
private String erstellt_am;
private String geaendert_am;
private String schlagwort1;
private String schlagwort2;
public ConBeitrag() {
}
public ConBeitrag(int beitragid, int projektid, int mitarbeiterid, String beitragText, String erstellt_am, String geaendert_am) {
this.beitragid = beitragid;
this.projektid = projektid;
this.mitarbeiterid = mitarbeiterid;
this.erstellt_am = erstellt_am;
this.geaendert_am = geaendert_am;
this.beitragText = beitragText;
this.schlagwort1 = schlagwort1; // This is null
this.schlagwort2 = schlagwort2; // This is null
}
#Override
public String toString() {
return mitarbeiterid + beitragText + erstellt_am + schlagwort1 + schlagwort2;
}
}
I'm currently trying to use jasper to help me create reports. I have the information and data that I want displayed in this method:
private void writeToFile(final List<ScenarioLoadModel> sceneLoadModel) throws Exception {
final BufferedWriter bw = new BufferedWriter(new FileWriter("/Uma/nft/result.psv"));
for (final ScenarioLoadModel slm : sceneLoadModel) {
bw.write(slm.getScenarioId() + PSP + slm.getScenarioId() + PSP + slm.getScenarioConfig().getName() + PSP + slm.getLoad() + PSP + "" + EOL);
if (!slm.getScenarios().isEmpty()) {
final int tempCount = slm.getScenarios().get(0).getTemplates().size();
final int sceneCount = slm.getScenarios().size();
for (int tempIdx = 0; tempIdx < tempCount; tempIdx++) {
String id = null;
int pass = 0;
int fail = 0;
final Map<String, BigDecimal> metricMap = new HashMap<String, BigDecimal>();
final DefaultStatisticalCategoryDataset dataset = new DefaultStatisticalCategoryDataset();
for (int sceneIdx = 0; sceneIdx < sceneCount; sceneIdx++) {
final Template temp = slm.getScenarios().get(sceneIdx).getTemplates().get(tempIdx);
if (temp.isError()) {
fail++;
} else {
pass++;
}
if (sceneIdx == 0) {
id = temp.getId();
}
final MetricGroupModel mgm = slm.getScenarios().get(sceneIdx).getMetricGroupModel().get(tempIdx);
if (mgm != null) {
for (final MetricModel mm : mgm.getMetricModel()) {
for (final MetricValue mv : mm.getMetricValue()) {
dataset.add(mv.getValue(), new BigDecimal(0.0), mv.getType(), id);
}
}
}
}
final TemplateConfig tc = TemplateManager.getTemplateConfig(id);
bw.write(slm.getScenarioId() + PSP);
bw.write(id + PSP + tc.getName() + PSP + 1 + PSP + pass + "/" + fail);
for (final Object row : dataset.getRowKeys()) {
final Number mean = dataset.getValue((String) row, id);
bw.write(PSP + row + PSP + mean);
}
bw.write(EOL);
}
}
}
bw.close();
}
From my understanding I create Beans and then put them all in a Bean Factory, to create my object that will be ready to be passed to iReport.
How can I put all this information into a Bean? I essentially want the bean to include the scenario/test case and whether or not it passed. (This is for test automation)
I tried to read your code to make a a best guess at what columns you would want, but with no context, I have no clue. All the bean is a pojo, with private fields and public getters and setters.
Assuming there is no grouping and essentially each ScenarioLoadModel will correspond to one row in the report you would end up with a bean like this:
public class ScenariaResults {
private String id;
private String name;
private String load;
private int passCount;
private int failCount;
public ScenariaResults(String id, String name, String load, int passCount,
int failCount) {
super();
this.id = id;
this.name = name;
this.load = load;
this.passCount = passCount;
this.failCount = failCount;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLoad() {
return load;
}
public void setLoad(String load) {
this.load = load;
}
public int getPassCount() {
return passCount;
}
public void setPassCount(int passCount) {
this.passCount = passCount;
}
public int getFailCount() {
return failCount;
}
public void setFailCount(int failCount) {
this.failCount = failCount;
}
#Override
public String toString() {
return "ScenariaResults [id=" + id + ", name=" + name + ", load="
+ load + ", passCount=" + passCount + ", failCount="
+ failCount + "]";
}
}
So basically in the code you have above you build instances of ScenarioResults and add them to a list. Once you have the list, all you need to do is create a JRDataSource:
List<ScenarioResults> dataBeanList = ...call your method to get the list of results
//create the datasource
JRDataSource dataSource = new JRBeanCollectionDataSource(dataBeanList);
Now when designing the report in iReport it can be a little tricky to get the fields imported automatically. Basically first add your project with the bean to the classpath in iReports (could just point it to the bin folder or jar file`): Tools -> options -> classpath tab. Now follow these steps to add the fields.
Click the following icon:
Select the JavaBean Datasource tab.
Enter the classname of your bean. (ex. ScenarioResults)
Click Read attributes
Highlight the fields you want in the report and click Add Selected Field(s).
Click OK.
Now if you want to test what the report looks like with data, and not just an empty datasource, this is where the Factory comes in. It is only for testing while using iReport. You need to create a class that will essentially create a dummy data set for you. It should look something like:
import java.util.ArrayList;
import java.util.List;
public class ScenarioResultsFactory {
public static List<ScenarioResults> createBeanCollection() {
List<ScenarioResults> list = new ArrayList<ScenarioResults>();
list.add(new ScenarioResults("1", "test", "load", 10, 5));
//add as many as you want
return list;
}
}
Now you need to create a Datasource pointing to it in iReport.
Next to the Datasource dropdown in the toolbar click the icon with the tooltip `Report Datasources.
Click New.
Select JavaBeans set datasource. Click Next.
For name enter ScenarioResultsFactory.
For the Factory class you need to put the classname including package. So if the class is in the com package you should have com.ScenarioResultsFactory here.
For the static method put createBeanCollection if not already there.
Check the Use field description check box. Click Test to make sure it worked.
Click Save.