Can't fill Table with items with javafx - javafx

I'm not so good at javafx and also in English^^. I programmed a TableView but I don't know why it doesn't fill the Table with the Items I created. Perhaps it fills the Table, but I don't see them. I hope somebody could help me here out. Here is the Code:
private final TableView<VerzeichnisDaten> table = new TableView();
private final ObservableList<VerzeichnisDaten> data = FXCollections.observableArrayList();
TableColumn titleCol = new TableColumn("Titel");
TableColumn lastNameCol = new TableColumn("Nachname");
TableColumn firstNameCol = new TableColumn("Vorname");
TableColumn TelCol = new TableColumn("Telefon");
TableColumn FaxCol = new TableColumn("Fax");
TableColumn EmailCol = new TableColumn("E-Mail");
// here is a loop which wait for a mouse click on an item
// item will be saved in abteilung
try {
VD.mitarbeiter(abteilung);
} catch (SQLException ex) {
/* exception */);
}
centerPane.getChildren().clear();
table.getColumns().clear();
data.clear();
for(int j = 0;j < VD.count_mi;j++) {
data.add(new VerzeichnisDaten(VD.title_speicher[j], VD.lname_speicher[j], VD.fname_speicher[j], VD.tel_speicher[j], VD.fax_speicher[j],VD.email_speicher[j] ));
}
titleCol.setMinWidth(100);
titleCol.setCellValueFactory (new PropertyValueFactory<VerzeichnisDaten, String>("Titel"));
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory (new PropertyValueFactory<VerzeichnisDaten, String>("Nachname"));
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory (new PropertyValueFactory<VerzeichnisDaten, String>("Vorname"));
TelCol.setMinWidth(100);
TelCol.setCellValueFactory (new PropertyValueFactory<VerzeichnisDaten, String>("Telefon"));
FaxCol.setMinWidth(100);
FaxCol.setCellValueFactory (new PropertyValueFactory<VerzeichnisDaten, String>("Fax"));
EmailCol.setMinWidth(100);
EmailCol.setCellValueFactory (new PropertyValueFactory<VerzeichnisDaten, String>("E-Mail"));
table.setItems(data);
table.getColumns().addAll(titleCol,lastNameCol,firstNameCol,TelCol,FaxCol,EmailCol);
centerPane.getChildren().addAll(table);
mainPane.setCenter(centerPane);
}
primaryStage.setScene(new Scene(mainPane, 855, 400));
primaryStage.show();
Here is the Class VerzeichnisDaten:
String[] title_speicher, lname_speicher, fname_speicher, tel_speicher, fax_speicher, email_speicher;
SimpleStringProperty title, lastName, firstName, Tel, Fax, Email;
public VerzeichnisDaten (String title, String lname, String fname, String tel, String fax, String email) {
this.title = new SimpleStringProperty(title);
this.lastName = new SimpleStringProperty(lname);
this.firstName = new SimpleStringProperty(fname);
this.Tel = new SimpleStringProperty(tel);
this.Fax = new SimpleStringProperty(fax);
this.Email = new SimpleStringProperty(email);
}
// Setter and Getter are now implemented, only not shown
this code belongs to VerzeichnisDaten. above them was more code but is
not relevant now.
void mitarbeiter (String Abteilung) throws SQLException {
// more code ...
stmt = conn.createStatement();
rset = stmt.executeQuery(sql_mi_stmt);
i = 0;
while (rset.next()){
title_speicher[i] = rset.getString("title");
lname_speicher[i] = rset.getString("lname");
fname_speicher[i] = rset.getString("fname");
tel_speicher[i] = rset.getString("tel");
fax_speicher[i] = rset.getString("fax");
email_speicher[i] = rset.getString("email");
i = i + 1;
}
stmt.close();
}

The string that you supply to the PropertyValueFactory, e.g. as here:
new PropertyValueFactory<VerzeichnisDaten, String>("Titel")
must match the variable name of the property in your data class.
That is, if you have:
class Person {
StringProperty firstNameProperty; // note: must end in "Property", per convention
StringProperty lastNameProperty;
}
the respective property value factories would be:
new PropertyValueFactory<Person, String>("firstName") // property name sans "Property" postfix
new PropertyValueFactory<Person, String>("lastName")
In your code, you 1) have property names that do not end with "Property", i.e. you have:
SimpleStringProperty title, lastName, firstName, Tel, Fax, Email;
and 2) you have used the names of the columns headers instead of the property names in your property value factories.
And thus you have discovered the joys of string-based, or type-unsafe in general, programming: the compiler is happy, but nothing works.
The PropertyValueFactory supplied with JavaFX is at best a hack, and more generally a bad practice. If you look at its Javadoc, you see exactly what it does: it provides a simpler way of creating a value factory instead of having to deal with the ugly Callback SAM, by using reflection and special naming conventions (the latter to which you were victim) to find the right property value.
With Java 8's lambda syntax you can write those value factories in a much simpler way and I would disadvice the usage of PropertyValueFactory.

Related

How to add data to associative table in asp.net core

I am new to asp.net core. I am building a web application for book management. I have a table called Author and books. Being a many to many relationships I made an associative entity that consists of the bookId and authorId. When I try to create I am able to create author and book. I successfully added the author and book to the database.
My author class looks like this
public class Author
{
private int _ID
private string _Name;
public string ID {
get { return _ID; }
set { _ID = value; }
public string Name {
get { return _Name; }
set { _Name = value; }
}
My book class is
public class Author
{
private int _ID
private string _Name;
private string _Title;
public string ID {
get { return _ID; }
set { _ID = value; }
}
public string Title {
get { return _Name; }
set { _Name = value; }
}
public string Name {
get { return _Name; }
set { _Name = value; }
}
I have a data access called db.cs to help to create the book and author in database.
public static int AddAuthor(Author A)
{
int renum = -1;
SqlConnection conn = null;
conn = new SqlConnection(ConnectionString);
conn.Open();
SqlCommand comm = new SqlCommand("sproc_AuthorAdd", conn);
comm.CommandType = System.Data.CommandType.StoredProcedure;
comm.Parameters.AddWithValue("#Name", A.Name);
comm.Parameters.AddWithValue("#Title", a.Title);
SqlParameter output = new SqlParameter();
output.ParameterName = "#AuthorID";
output.DbType = System.Data.DbType.Int32;
output.Direction = System.Data.ParameterDirection.Output;
comm.Parameters.Add(output);
int affect = comm.ExecuteNonQuery();
renum = affect;
c.ID = (int)output.Value;
I have done the same for books as well. I want to fill out the association table as well when the user filled out a book and author using their ID. I tried to do various things like using a cookie to pass data. But I cannot store data. Any kind of help is appreciated. Thanks in advance.
I'm not really sure I understand your last code snippet, but if you're having issues managing your many-to-many relationship between Books and Authors, have you considered just using Entity Framework Core?
Instead of writing a bunch of code that accesses your database, you just create models of your tables (similar to the classes you have defined above), and it handles the many-to-many relationship for you. The code to query for Authors and/or Books could then look as simple as:
using (var db = new dbContext())
{
var books = db.Books
.Where(b => b.ID > 1234)
.OrderBy(b => b.Title)
.ToList();
}
And creating a new Book or Author would be similarly simple:
using (var db = new dbContext())
{
var book = new Book { ID = 1234, Title = "Some Title", Name = "Some Name" };
db.Books.Add(book);
db.SaveChanges();
}
You might have to reimplement a bunch of things to take advantage of Entity Framework Core in your app, but it sounds like it would save you time in the long run.

How to refresh a ChoiceBox in JavaFX?

I would like to refresh the choice box after I added a new value it should be shown there.
I read all the topics about this that I found on stackoverflow but none of these worked.
public void setNamesChoiceBoxes() {
ArrayList<Worker> workers = new ArrayList<>();
ArrayList<String> names = new ArrayList<>();
workers = db.getWorkers();
for (Worker i : workers) {
String tmp = i.getName() + " (" + i.getID() + ")";
names.add(tmp);
}
ArrayList<String> searchNames = new ArrayList<>(names);
searchNames.add(0, "All");
ObservableList<String> search = FXCollections.observableList(searchNames);
searchNameChoiceBox.setItems(search);
searchNameChoiceBox.setValue(search.get(0));
ArrayList<String> addNames = new ArrayList<>(names);
addNames.add(0, "");
ObservableList<String> add = FXCollections.observableList(addNames);
addNameChoiceBox.setItems(add);
addNameChoiceBox.setValue(add.get(0));
}
#Override
public ArrayList<Worker> getWorkers() {
ArrayList<Worker> workers = new ArrayList<>();
String sql = "select * from names";
try {
ResultSet rs = statement.executeQuery(sql);
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
workers.add(new Worker(id, name));
}
} catch (Exception ex) {
System.out.println("Exception in class \"DB\" (\" public ArrayList<Worker> getWorkers()\" failed): " + ex);
}
return workers;
}
#FXML
public void addNewWorkerButton(ActionEvent event) {
String name = workerNameTextField.getText();
workerNameTextField.setText("");
db.addWorker(name);
addWorkerAnchorPane.setVisible(false);
mainAnchorPane.setOpacity(1);
mainAnchorPane.setDisable(false);
setNamesChoiceBoxes();
}
I get the worker names from the database when I start the program, it works perfectly. When I add a new name to the DB, and call the "setNamesChoiceBoxes" method (to refresh the choicebox from DB), it gives alot of errors, although the new name is in the Choice Box list, but the "searchNameChoiceBox" value should be "All" but it is "".
After I added a new name choice box looks like this: https://imgur.com/a/N4JarK7
It should be like this... (since I set the value to "All" in method...): https://imgur.com/a/ZAEB7A3
I think i understood that you want a particular item to be selected and shown in your ChoiceBox?
If so, I would recommend to remove this line(and analoguous for the other Box):
//addNameChoiceBox.setValue(add.get(0));
And use instead a real selection for the Item to show. This selects the first Item:
addNameChoiceBox.getSelectionModel().select(0);
Alternativly there is a seperate method that also selects the first Item:
addNameChoiceBox.getSelectionModel().selectFirst();
And then again you may want to select the Item shown by value:
addNameChoiceBox.getSelectionModel().select("All"); //or whatever value you want to select.
I hope this helps you at least with a part of your problem.

Java8 convert list<P> in to Map<Integer, List<P>>

I have List<Person> object and would like to convert this in to Map<Integer, List<Person>> where the key of the map denotes a person's property grade. Its possible to have multiple Person object with the same grade in the source list, in that case i want to group them all in to List against the corresponding grade in the resulting Map.
I have the below code, so far
public class PersonMain
{
public static void main(String[] args)
{
Person person1 = new Person();
person1.setName("person1");
person1.setGrade(1);
Person person2 = new Person();
person2.setName("person2");
person2.setGrade(2);
Person person3 = new Person();
person3.setName("person3");
person3.setGrade(1);
List<Person> persons = Arrays.asList(person1, person2, person3);
Map<Integer, List<Person>> personsMap = persons.stream()
.collect(Collectors.toMap(Person::getGrade, PersonMain::getPerson, PersonMain::combinePerson));
System.out.println(personsMap);
}
private static List<Person> getPerson(Person p)
{
List<Person> persons = new ArrayList<>();
persons.add(p);
return persons;
}
private static List<Person> combinePerson(List<Person> oldVal, List<Person> newVal)
{
oldVal.addAll(newVal);
return oldVal;
}
}
Is there a better way of implementing this?
Your current solution is fine, but it's more intuitive to do it with the groupingBy collector:
Map<Integer, List<Person>> personsMap =
persons.stream()
.collect(Collectors.groupingBy(Person::getGrade));
This overload of the groupingBy collector is pretty straightforward as all it does is take a classifier (Person::getGrade) function which will extract the key to group the objects of the stream by.
Much simpler solution if using Java 8:
Map<Integer, List<Person>> map = persons.stream()
.collect(Collectors.groupingBy(Person::getGrade));

How can I associate data (List<SimpleStringProperty> with the table columns of a table view

I have a class called Result (data that I want to show in my table) with several attributes.
public class Result
{
private final SimpleStringProperty object;
private List<SimpleStringProperty> listObject= new ArrayList<SimpleStringProperty>();
private final Util util = new Util();
public Result(String object, String[] listObject)
{
this.object= new SimpleStringProperty(object);
this.objectList= util.transformar(listObject);
}
public String getObject()
{
return this.object.get();
}
public void setObject(String object)
{
this.hash.set(hash);
}
public String[] getListObject()
{
return util.transformar2(this.listObject);
}
public void setListObject(String[] listObject)
{
this.listObject= transformar(listObject);
}
}
And I have my controller where I have an empty table and I add the columns and the objetcs Result. The controller has the attribute:
#FXML
private TableView tablaResultado;
The method were I do that is:
private List<TableColumn> load()
{
List<TableColumn> listColumn = new ArrayList<TableColumn>();
Object2 object2= new Object2();
List<Result> listaResultado = object2.getResultado();
ObservableList<Result> prueba = FXCollections
.observableArrayList(listaResultado);
TableColumn<Result, String> object= new TableColumn<Result, String>("object");
direccion.setCellValueFactory(
new PropertyValueFactory<Result, String>(
"object"));
listColumn.add(object);
List<TableColumn<Result, String>> listObject = new ArrayList<TableColumn<Result, String>>();
for (int i = 0; i < ((Result) listaResultado
.get(0)).getListObject().length; i++)
{
TableColumn<Result, String> columna = new TableColumn<Result, String>(
this.lenguaje.getProperty("listObject"+i);
columna.setCellValueFactory(
new PropertyValueFactory<Result, String>(
"listObject[" + i + "]"));
objectList.add(columna);
}
listColumn.addAll(objectList);
ObservableList<TableColumn<Result, String>> prueba2 = FXCollections
.observableArrayList(listObject);
this.tablaResultado.setItems(prueba);
this.tablaResultado.getColumns().addAll(object);
for (int i = 0; i < prueba2.size(); i++)
{
this.tablaResultado.getColumns().addAll(prueba2.get(i));
}
}
return listColumn ;
The result is the columns with their names and the data in the column object but the data in the columns listObject is empty. It has to be a list or something because I don't know the size of listObject.
If I change:
columna.setCellValueFactory(new PropertyValueFactory<Result, String ("listObject[" + i + "]"));
and I write:
columna.setCellValueFactory(new PropertyValueFactory<Result, String ("listObject"));
I got something like Ljava.lang.String;#bda3303 in that columns.
Do
final int index = i ;
columna.setCellValueFactory(cellData ->
new SimpleStringProperty(cellData.getValue().getListObject()[index]));
PropertyValueFactory does not "evaluate" an expression. It just tries to access a property of the table item. The default TableCells will use the toString method to get the text to display, which is why you get something like Ljava.lang.String;#bda3303 in the third version, see Java arrays printing out weird numbers, and text .
However you can write your own cellValueFactory:
public class Result
public StringProperty listObjectProperty(int index) {
return listObject.get(index);
}
final int columnIndex = i;
columna.setCellValueFactory(cellData -> cellData.getValue().listObjectProperty(columnIndex));
Alternatively simply create a ObservableValue<String> with a constant value for the column value:
final int columnIndex = i;
columna.setCellValueFactory(cellData -> Bindings.createStringBinding(() -> cellData.getValue().getListObject()[columnIndex]));

I can't seem to get the datafield i want from an object in a TableView

This is the code for the TableView:
TableView<KontaktPerson> tableKontaktPerson = new TableView<>();
TableColumn KontaktPersonFornavn = new TableColumn("Fornavn");
KontaktPersonFornavn.setCellValueFactory(new PropertyValueFactory<KontaktPerson, String>("fornavn"));
TableColumn KontaktPersonEtternavn = new TableColumn("Etternavn");
KontaktPersonEtternavn.setCellValueFactory(new PropertyValueFactory<KontaktPerson, String>("etternavn"));
TableColumn KontaktPersonNr = new TableColumn("Medlemsnummer");
KontaktPersonNr.setCellValueFactory(new PropertyValueFactory<KontaktPerson, Integer>("medlemsNr"));
tableKontaktPerson.getColumns().addAll(KontaktPersonFornavn,KontaktPersonEtternavn,KontaktPersonNr);
tableKontaktPerson.getSelectionModel().cellSelectionEnabledProperty();
tableKontaktPerson.setPrefSize(800, 300);
i wish to display the "fornavn","etternavn" and "medlemsNr" of that Object
Here is the "KontaktPerson" Class:
public class KontaktPerson extends Bruker implements Serializable {
private String fornavn, etternavn, telefon, epost;
private static int nestenr = 1000;
private int medlemsNr;
public KontaktPerson(String br, String pas, String fn, String en, String tlf, String ep) { // Tar in oppgitte Stirng verdier
super(br,pas);
fornavn = fn;
etternavn = en;
telefon = tlf;
epost = ep;
medlemsNr = ++nestenr;
}
}
For some reason i cant seem to get the "fornavn" and "etternavn" out, i just get the medlemsNr...

Resources