java - Better practice for custom rows and cells in a tableview JavaFX -
i made table-view looks following:
for doing made following:
1.- create , observable list of pojo represents table "modulo" in mysql database, list created columns of table-view code:
public observablelist<modulo> cargatablahabilitadosmashoras(connection conex){ observablelist<modulo> listamod = fxcollections.observablearraylist(); string sql = "select id_mod, nombre_mod, \n" + " turno_mod, capacidad_mod, id_us, \n" + " status_mod \n"+ "from modulo;"; //static first column listamod.add(new modulo("123", "horario", "rhut", 10, "123", true)); try(preparedstatement stta = conex.preparestatement(sql); resultset res = stta.executequery()) { while (res.next()) { if (res.getboolean("status_mod")) { listamod.add(new modulo( res.getstring ("id_mod"), res.getstring ("nombre_mod"), res.getstring ("turno_mod"), res.getint ("capacidad_mod"), res.getstring ("id_us"), res.getboolean("status_mod"))); } } }catch (sqlexception ex) { ex.printstacktrace(); } return listamod; }
2.- create table custom data code:
public void otratabla(connection conex){ //loads observable list of pojo represents table modulo columns = modu.cargatablahabilitadosmashoras(conex); /* creates , observable list going base of tableview creating grid of 8 x number of colums obtained of first list + 1 column represents hours */ observablelist<string> row = fxcollections.observablearraylist(); row.addall("1","2","3","4","5","6","7","8"); //for loop iterates tableview columns for(modulo columname : columns) { //creates , column object integrated , manipulated //whit name of column in first list tablecolumn<string, string> col = new tablecolumn(columname.getnombre_mod()); //verify if first column contains hours if (columname.getnombre_mod().equals("horario")) { //if 1 creates rows hours staring @ 6 col.setcellvaluefactory(celldata -> { //star @ 6 localtime lol = localtime.of(6, 0); //get value of observablelist<string> row for adding localtime integer p = integer.valueof(celldata.getvalue()); //adds value localtime lol = lol.plushours(p); //gives format hour datetimeformatter kk = datetimeformatter.ofpattern("hh:mm"); //returns new string return new simplestringproperty(lol.format(kk)); }); }else{ //if column load dinamically gets //the next date there space in column @ time col.setcellvaluefactory(celldata -> { string regresafecha = ""; //conection database conection database //have inside of loop or else conection lost try(connection localconnection = dbconn.conectarbd()) { //get level of row in case hour localtime lol = localtime.of(6, 0); integer p = integer.valueof(celldata.getvalue()); lol = lol.plushours(p); //calls method calculed next date there space in table of database localdate fechaapunter = rehab.comparardiaadia(localconnection, date.valueof(localdate.now()), time.valueof(lol), columname.getid_mod(), columname.getcapacidad_mod(), 30); //date sent row of tableview regresafecha = fechaapunter.tostring(); } catch (sqlexception e) { e.printstacktrace(); } return new simplestringproperty(regresafecha); }); } //change color of date depending of //distant relevant day making query database if (!columname.getnombre_mod().equals("horario")) { col.setcellfactory (coli -> { tablecell<string, string> cell = new tablecell<string, string>() { @override public void updateitem(string item, boolean empty) { super.updateitem(item, empty); if (item != null) { localdate lol = localdate.parse(item); text text = new text(item); if (lol.isafter(localdate.now())) { if (lol.isafter(localdate.now().plusdays(5))) { text.setstyle(" -fx-fill: #990000;" + " -fx-text-alignment:center;"); }else text.setstyle(" -fx-fill: #cccc00;" + " -fx-text-alignment:center;"); } this.setgraphic(text); } } }; return cell; }); } //add column tableview tvdisponivilidad.getcolumns().addall(col); } //add observable list place holder tvdisponivilidad.setitems(row); }
for loading data used method:
public localdate comparardiaadia(connection conex, date fecha, time hora, string id_mod, int capacidad, int dias){ localdate contador = fecha.tolocaldate(); localdate disdehoy = localdate.now(); (int = 0; < dias; i++) { contador = fecha.tolocaldate(); contador = contador.plusdays(i); string sttm = "select count(id_reab) resultado\n" + "from rehabilitacion\n" + "where '"+contador+"' between inicio_reab , fin_reab\n" + "and horario_reab = '"+hora+"'\n" + "and id_modulo = '"+id_mod+"';"; try(preparedstatement stta = conex.preparestatement(sttm); resultset res = stta.executequery(); ) { if (res.next()) { if (res.getint("resultado") < capacidad || res.getint("resultado") == 0) { disdehoy = contador; break; }else disdehoy = contador; } } catch (sqlexception ex) { ex.printstacktrace(); } } return disdehoy; }
what method each column checks next day there less of capacity of module (each module has different capacity) @ hour , returns day, in calling of method hour changes populate rows in table.
there several problems approach, first time, cost load table, takes 1 minute make query , populate table combination of factors principal factor every day made query database , example of this:. here table made queries:
mysql> select * imssrehab.rehabilitacion; +---------+-------------+------------+-----------------+---------+-----------+ | id_reab | inicio_reab | fin_reab | horario_reab | id_prog | id_modulo | +---------+-------------+------------+-----------------+---------+-----------+ | 1 | 2016-06-01 | 2016-06-10 | 07:00:00.000000 | 1 | 215a3 | | 2 | 2016-06-01 | 2016-06-10 | 07:00:00.000000 | 1 | 215a3 | | 3 | 2016-06-01 | 2016-06-10 | 07:00:00.000000 | 1 | 215a3 | | 4 | 2016-06-01 | 2016-06-10 | 07:00:00.000000 | 1 | 215a3 | | 5 | 2016-06-01 | 2016-06-10 | 07:00:00.000000 | 1 | 215a3 | | 6 | 2016-06-01 | 2016-06-10 | 07:00:00.000000 | 1 | 215a3 | +---------+-------------+------------+-----------------+---------+-----------+
here query:
select count(id_reab) resultado rehabilitacion '2016-06-01' between inicio_reab , fin_reab , horario_reab = '07:00' , id_modulo = '215a3';
the result 6 in module capacity 5 have advance day , ask again until finds day less 5 in example until 2016-06-11. here have make 10 queries , open 10 connections. use connection pool , it's efficient, gets overwhelmed these 10 queries first row in first column, there between 15 20 columns assuming there 1 query row, still around 120-160 connections.
i try reuse connection every time can, first instinct use connection pass method loading observable list of modules when method makes query of dates receives connection closed out , apparent reason. after many tests came conclusion has lambda of setcellvaluefactory method, , if want make connection has inside creating more connections. try alleviate loading table in different thread task results similar.
a solution make pojo table don't think it's possible create class dynamically. have pojo whit 20 possible columns , load columns use, happens when there more 20 columns or name of modules changes?
so question this: how make creation of table more rapidly? , there better way achieve table? don't solution code it's more complex i'm hoping better , cleaner way.