getSelectedRow method keep returning row 0 - swing

I try to select a row from jTable and store the value into topicId. Here are my codes.
jTable.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
if (jTable.getSelectedRow() >= 0 && jTable.getValueAt(jTable.getSelectedRow(), 0) != null) {
topicId = (Integer)jTable.getValueAt(jTable.getSelectedRow(), 0);}
System.out.println(topicId);
eForumTopics topics = new eForumTopics(topicId);
topics.retrieveThread();
getJFrame().dispose();
eForumThreadContent myWindow = new eForumThreadContent(topicId);
myWindow.getJFrame().setVisible(true);
}
});
}
Here are my codes for scroll pane.
private JScrollPane getJScrollPane() {
if (jScrollPane == null) {
jScrollPane = new JScrollPane();
jScrollPane.setBounds(new Rectangle(75, 220, 800, 450));
jScrollPane.setViewportView(getJTable());
}
return jScrollPane;
}
And here are the codes for jTable.
private JTable getJTable() {
if (jTable == null) {
Vector columnNames = new Vector(); // Vector class allows dynamic
// array of objects
Vector data = new Vector();
try {
DBController db = new DBController();
db.setUp("IT Innovation Project");
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
String dsn = "IT Innovation Project";
String s = "jdbc:odbc:" + dsn;
Connection con = DriverManager.getConnection(s, "", "");
String sql = "Select topic_title,topic_description,topic_by from forumTopics WHERE topic_category = '"+category+"'";
java.sql.Statement statement = con.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
ResultSetMetaData metaData = resultSet.getMetaData();
int columns = metaData.getColumnCount();
for (int i = 1; i <= columns; i++) {
columnNames.addElement(metaData.getColumnName(i));
}
while (resultSet.next()) {
Vector row = new Vector(columns);
for (int i = 1; i <= columns; i++) {
row.addElement(resultSet.getObject(i));
}
data.addElement(row);
}
resultSet.close();
((Connection) statement).close();
} catch (Exception e) {
System.out.println(e);
}
jTable = new JTable(data, columnNames);
TableColumn column;
for (int i = 0; i < jTable.getColumnCount(); i++) {
column = jTable.getColumnModel().getColumn(i);
if (i == 1) {
column.setPreferredWidth(400); // second column is bigger
}else {
column.setPreferredWidth(200);
}
}
String header[] = { "Title", "Description", "Posted by" };
for (int i = 0; i < jTable.getColumnCount(); i++) {
TableColumn column1 = jTable.getTableHeader().getColumnModel()
.getColumn(i);
column1.setHeaderValue(header[i]);
}
jTable.getTableHeader().setFont( new Font( "Dialog" , Font.PLAIN, 20 ));
jTable.getTableHeader().setForeground(Color.white);
jTable.getTableHeader().setBackground(new Color(102, 102, 102));
jTable.setEnabled(false);
jTable.setRowHeight(100);
jTable.getRowHeight();
jTable.setFont( new Font( "Dialog" , Font.PLAIN, 18 ));
jTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
I not sure whether is my table or scroll pane got problem. Whenever I selected any rows in the jTable, for example, 4 or 5 or 6, the result keep returning me row 0. Somebody can help? Thanks in advance.

There is no point in adding a mouse listener to store the selected row in a field. The table knows its selected row(s), and moreover, the selection can change without using the mouse.
If you want to do something (like loading details of a selected row) each time the selection changes, then add a selection listener:
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
int viewRow = table.getSelectedRow();
if (viewRow >= 0) {
int modelRow = table.convertRowIndexToModel();
Integer topicId = tableModel.getTopicIdAtRow(modelRow);
// todo load the details for topicId
}
}
}
});

Related

How the performance of a JavaFx-MySQL application can be enhanced

In my JavaFx application, i'm loading an ObservableList when a button is clicked and then display the list in a table.
the controller code:
#FXML
private void initialize() throws SQLException, ParseException, ClassNotFoundException {
searchChoice.setItems(criteriaList);
searchChoice.getSelectionModel().selectFirst();
productIdColumn.setCellValueFactory(cellData -> cellData.getValue().productIdProperty());
unitColumn.setCellValueFactory(cellData -> cellData.getValue().unitProperty());
productTitleColumn.setCellValueFactory(cellData -> cellData.getValue().titleProperty());
productTypeColumn.setCellValueFactory(cellData -> cellData.getValue().typeProperty());
productUnitPriceColumn.setCellValueFactory(cellData -> Bindings.format("%.2f", cellData.getValue().unitPriceProperty().asObject()));
productQuantityColumn.setCellValueFactory(cellData -> cellData.getValue().quantityProperty().asObject());
productStatusColumn.setCellValueFactory(cellData -> cellData.getValue().productStatusProperty());
descriptionColumn.setCellValueFactory(cellData -> cellData.getValue().descriptionProperty());
reorderPointColumn.setCellValueFactory(cellData -> cellData.getValue().reOrderPointProperty().asObject());
surplusPointColumn.setCellValueFactory(cellData -> cellData.getValue().surplusPointProperty().asObject());
productIdColumn.setSortType(TableColumn.SortType.DESCENDING);
productTable.getSortOrder().add(productIdColumn);
productTable.setRowFactory(tv -> new TableRow<Product>() {
#Override
public void updateItem(Product item, boolean empty) {
super.updateItem(item, empty);
if (item == null) {
setStyle("");
} else if (item.getQuantity() < item.getReOrderPoint()) {
setStyle("-fx-background-color: tomato;");
} else if (item.getQuantity() > item.getSurplusPoint()) {
setStyle("-fx-background-color: darkorange;");
} else {
setStyle("-fx-background-color: skyblue;");
}
}
});
try {
ObservableList<Product> productData = ProductDAO.searchProducts();
populateProducts(productData);
String[] expireDate = new String[productData.size()];
String[] id = new String[productData.size()];
String[] existingStatus = new String[productData.size()];
for (int i = 0; i < productData.size(); i++) {
expireDate[i] = productData.get(i).getExpireDate();
id[i] = productData.get(i).getProductId();
existingStatus[i] = productData.get(i).getProductStatus();
DateFormat format = new SimpleDateFormat(app.values.getProperty("DATE_FORMAT_PATTERN"), Locale.ENGLISH);
Date expireDateString = format.parse(expireDate[i]);
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date today = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
if (expireDateString.before(today) && !existingStatus[i].equals(app.values.getProperty("STATUS_TYPE2"))) {
ProductDAO.updateProductStatus(id[i], app.values.getProperty("STATUS_TYPE3"));
}
if (expireDateString.after(today) && !existingStatus[i].equals(app.values.getProperty("STATUS_TYPE2"))) {
ProductDAO.updateProductStatus(id[i], app.values.getProperty("STATUS_TYPE1"));
}
}
ObservableList<Product> productDataRefreshed = ProductDAO.searchProducts();
populateProducts(productDataRefreshed);
ObservableList<Product> productCodesData = ProductDAO.getProductCodes();
ObservableList<Product> productTitlesData = ProductDAO.getProductTitles();
ObservableList<Product> productTypesData = ProductDAO.getProductTypes();
ObservableList<Product> productStatusData = ProductDAO.getProductStatus();
String possibleProducts1[] = new String[productCodesData.size()];
for (int k = 0; k < productCodesData.size(); k++) {
possibleProducts1[k] = productCodesData.get(k).getProductId();
}
String possibleProducts2[] = new String[productTitlesData.size()];
for (int k = 0; k < productTitlesData.size(); k++) {
possibleProducts2[k] = productTitlesData.get(k).getTitle();
}
String possibleProducts3[] = new String[productTypesData.size()];
for (int k = 0; k < productTypesData.size(); k++) {
possibleProducts3[k] = productTypesData.get(k).getType();
}
String possibleProducts4[] = new String[productStatusData.size()];
for (int k = 0; k < productStatusData.size(); k++) {
possibleProducts4[k] = productStatusData.get(k).getProductStatus();
}
TextFields.bindAutoCompletion(searchField, possibleProducts1);
TextFields.bindAutoCompletion(searchField, possibleProducts2);
TextFields.bindAutoCompletion(searchField, possibleProducts3);
TextFields.bindAutoCompletion(searchField, possibleProducts4);
} catch (SQLException e) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle(app.values.getProperty("ERROR_TITLE"));
alert.setHeaderText(app.values.getProperty("FAILURE_MESSAGE"));
alert.setHeaderText(app.values.getProperty("ERROR_GETTING_INFORMATION_FROM_DATABASE_MESSAGE"));
alert.showAndWait();
throw e;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
the service mysql query :
public static ObservableList<Product> searchProducts() throws SQLException, ClassNotFoundException {
String selectStmt = "SELECT * FROM product";
ResultSet rsPrdcts = DbUtil.dbExecuteQuery(selectStmt);
ObservableList<Product> productList = getProductList(rsPrdcts);
return productList;
}
The issue here is, when there are more than 200-300 items in the list the scene gets really slow to load. What countermeasures can I take regarding this matter? Any idea will be very much appreciated.
Thanks in advance.
You need to implement an ObservableList which only retrieves the data which is rqeusted by the TableView. Currently you retrive all elements in the table and cast the retrieved list to an ObservableList.
The TableView uses the .get(int idx) method of the OL to retrieve all items which should be displayed and the .size() method for determining the size of the scrollbar. When you scroll the TableView will discard all items which are not displayed and call the get method again.
To solve your problem need to create a class which implements ObservableList<E>. First you need to implement the .get(int idx) and the .size() method, for all other methods I would throw new UnsupportedOperationException() and later on see which other method is needed. So the .size() method needs to execute the following query
SELECT count(*) FROM product
and the get(int idx) something like this
int numItems = 30;
int offset = idx - (idx % numItems)
SELECT * FROM product LIMIT offset, numItems
you can create an internal list which only holds e.g. 30 items from your db and whenever the requested idx < offset || idx > offset + numItems you issue a new db request.
I used this this approach with database tables with millions of rows and had a very performant GUI. You can also add paging to the TableView because with to many rows the scrollbar gets useless, but this is a different discussion.
edit:
I forgot to mention that this is called Lazy Loading

Having difficulty creating an array of Json objects for use in a Kendo grid

I need to convert a server response from an array to an array of JSON object format.
The rows of data coming fron the server needs to be converted in order for the Kendo UI grid widget to work properly.
I have converted the schema and column definitions into a Json format, but having some difficulty with the actual data rows.
Here's the RAW server response where
1) the "data" array contains the data schema
2) the "rows" array contains the actual values :
{"status":"SUCCESS", "messages":[],
"data":[{"attributes":[{"name":"BookingLocation","type":"string"},{"name":"SUM(CDSStress A:USD 10Y X -1.25)","type":"double"},{"name":"SUM(CDSStress A:USD 10Y X 1.25)","type":"double"},{"name":"SUM(CDSStress A:USD 8Y X 1.25)","type":"double"}],
"rows":[{"id":0,"values":["London",0,0,0]},{"id":1,"values":["Paris",0,0,0]},{"id":2,"values":["Dubai",1564.92711931719,-171.934775655824,-54539.9112355565]},{"id":3,"values":["New York",0,0,0]},{"id":4,"values":["Stockholm",0,0,0]},{"id":5,"values":["World",0,0,0]}]}]}
Essentially I need to pull the "attributes" array, and match them up with the "rows" array - and do this all dynamically for any server response.
Now pulling the schema information from the "attributes" array (within "data"), I can build the schema JSON object dynamically, then plug it into the Kendo grid - something like this :
var myModel = { // sample schema object; actually built dynamically in javascript
"id": "Id",
"fields": {
"BookingCountry": {
"type": "string"
},
"SUM(CDSStress A:USD 10Y X -1.25)": {
"type": "number"
},
"SUM(CDSStress A:USD 10Y X 1.25)": {
"type": "number"
},
"SUM(CDSStress A:USD 8Y X 1.25)": {
"type": "number"
}
}
}
var myColumns = $rootScope.reptWizard.colDefs; // build the columns def
var myData = $rootScope.reptWizard.aggrResults; // convert data rows to JSON object
var ds = {
schema: {
model: myModel
},
vm.mainHierGridOptions = {
dataSource: ds,
columns: myColumns
};
pageSize: 10,
data: myData
};
{
However, the 'myData' object needs to look like this :
[
{ "id": 0,
"BookingCountry": "London",
"SUM(CDSStress A:USD 10Y X -1.25)": 1564.92711,
"SUM(CDSStress A:USD 10Y X 1.25)": -171.9347756,
"SUM(CDSStress A:USD 8Y X 1.25)": -54539.911235
},
{ "id": 0,
"BookingCountry": "Dubai",
"SUM(CDSStress A:USD 10Y X -1.25)": 1564.92711,
"SUM(CDSStress A:USD 10Y X 1.25)": -171.9347756,
"SUM(CDSStress A:USD 8Y X 1.25)": -54539.911235
}
]
As you can see, I need to iterate the "values" array and create a nicely-formatted JSON object with the correct field:value - i.e. "BookingCountry": "London".
Here's a function I created to format the myCols var :
function buildDynamicColumnDefs(fieldAttribs) {
// creates an array of Json objects; to be used as input to the Grid's 'columns' property
var numAttribs = fieldAttribs.length;
var myType = '';
var myCols = [];
if (numAttribs > 0) {
_.each(fieldAttribs, function (field) {
myCols.push({field: field, title: field});
});
}
return myCols;
}
and another function to create the myModel var :
function buildDynamicDataSourceModel(fieldAttribs) {
// creates a valid Json object {name:value} to be used in Kendo Grid DataSource
var jsonExample = {
"BookingLocation": { "type": "string" },
"SUM(CDSStress A:USD 10Y X -1.25)": { "type": "number" },
"SUM(CDSStress A:USD 10Y X 1.25)": { "type": "number" },
"SUM(CDSStress A:USD 8Y X 1.25)": { "type": "number" }
};
var numAttribs = fieldAttribs.length;
var myType = '';
var myFields = {};
if (numAttribs > 0) {
_.each(fieldAttribs, function (field) {
myType = (field.type == "double" ? "number" : field.type); // 'number' is valid type for Kendo Grid schema
myFields[field.name] = { type: myType };
});
}
var myModel = {
id: "Id",
fields: myFields
/*fields: {
dimensions: { type: "string" },
values: { editable: false, type: "number" }
}*/
};
return myModel;
}
But now I need to create the buildJSONGridData(), and your help is greatly appreciated.
regards,
Bob
Here is a function I used to help in exporting a Kendo UI Grid to pdf and Reporting services . This function takes the client blob values (title,columns,data) and build a collection ofg strongly types objects. You could probally do the same on the client side. Notice where the if(dataObject!=null) is located that is where the data json objects are deserialzed. Hope it helps.
//------------------------------------------------------------------------------------------------------------------------------------
private CustomReportData CreateReportFromKendoData(string title, string columns, string data)
{
List<int> _ignoredColumns=new List<int>();
var columnObject = (columns == null) ? null : JsonConvert.DeserializeObject<dynamic>(columns);
var dataObject = (data == null) ? null : JsonConvert.DeserializeObject<dynamic>(data);
CustomReportData reportData = new CustomReportData();
reportData.ReportTitle = title;
if (columnObject != null)
for (int columnCount = 0; columnCount < columnObject.Count; columnCount++)
{
string fieldName = columnObject[columnCount].title == null ? columnObject[columnCount].field.ToString() : columnObject[columnCount].title.ToString();
if (ShouldDisplay(columnObject[columnCount].ToString()))
{
//IF WIDTH IS NULL THEN COLUMNS ARE EVNLY SPREAD THIS WILL BOMB
reportData.Columns.Add(new CustomReportColumn
{
FieldName = fieldName,
DataType = "",
Width = (columnObject[columnCount].width!=null)?this.GetFirstNumeric(columnObject[columnCount].width.ToString(), 250) :250
});
}
else
_ignoredColumns.Add(columnCount);
}
if (dataObject != null)
{
bool hasGrouping = dataObject[0].value != null;
for (int rowCount = 0; rowCount < dataObject.Count; rowCount++)
{
if (hasGrouping)
{
CustomReportGroup group = new CustomReportGroup();
group.GroupName = dataObject[rowCount].field.ToString();
group.GroupValue = ApplyFormat(dataObject[rowCount].value.ToString(),null);
this.RecursiveProcessGroups(group, dataObject[rowCount].items.ToString(), columnObject.ToString(),_ignoredColumns);
reportData.Groups.Add(group);
}
else
{
CustomReportDataRow row = new CustomReportDataRow();
for (int columnCount = 0; columnCount < columnObject.Count; columnCount++)
{
if (!_ignoredColumns.Contains(columnCount))
{
string format = (columnObject[columnCount].format == null ? "" : columnObject[columnCount].format.ToString());
string value = dataObject[rowCount][columnObject[columnCount].field.ToString()].ToString();
value = ApplyFormat(value, format);
row.Fields.Add(value);
}
}
reportData.DataRows.Add(row);
}
}
reportData.GroupDepth = this.GetGroupDepth(reportData.Groups);
}
return reportData;
}
Recursive function for group nesting
//------------------------------------------------------------------------------------------------------------------------------------
private void RecursiveProcessGroups(CustomReportGroup parentGroup, string items, string columns, List<int> ignoredColumns)
{
var groupItems = (items == null) ? null : JsonConvert.DeserializeObject<dynamic>(items);
var columnObject = (columns == null) ? null : JsonConvert.DeserializeObject<dynamic>(columns);
bool hasGrouping = groupItems[0]["value"] != null;
if (hasGrouping)
{
for (int rowCount = 0; rowCount < groupItems.Count; rowCount++)
{
CustomReportGroup group = new CustomReportGroup();
group.GroupName = groupItems[rowCount].field.ToString();
group.GroupValue = ApplyFormat(groupItems[rowCount].value.ToString(),null);
parentGroup.Groups.Add(group);
RecursiveProcessGroups(group, groupItems[rowCount].items.ToString(), columns.ToString(), ignoredColumns);
}
}
else
{
for (int groupItemCount = 0; groupItemCount < groupItems.Count; groupItemCount++)
{
CustomReportDataRow row = new CustomReportDataRow();
for (int columnCount = 0; columnCount < columnObject.Count; columnCount++)
if (!ignoredColumns.Contains(columnCount))
{
string value = groupItems[groupItemCount][columnObject[columnCount].field.ToString()].ToString();
string format = (columnObject[columnCount].format == null ? "" : columnObject[columnCount].format.ToString());
value = ApplyFormat(value, format);
row.Fields.Add(value);
}
parentGroup.DataRows.Add(row);
}
}
}
Domain Objects
public class CustomReportColumn
{
public string FieldName { get; set; }
public string DataType { get; set; }
public float Width { get; set; }
}
public class CustomReportColumns : List<CustomReportColumn> { }
public class CustomReportDataRow
{
public CustomReportDataRow()
{
Fields = new List<string>();
}
public List<string> Fields { get; set; }
}
public class CustomReportDataRows : List<CustomReportDataRow> { }
public class CustomReportGroup
{
public CustomReportGroup()
{
DataRows = new CustomReportDataRows();
Groups = new CustomReportGroups();
}
public string GroupName { get; set; }
public string GroupValue { get; set; }
public CustomReportGroups Groups { get; set; }
public CustomReportDataRows DataRows { get; set; }
}
public class CustomReportGroups : List<CustomReportGroup> { }
public class CustomReportData
{
public CustomReportData()
{
Groups = new CustomReportGroups();
Columns = new CustomReportColumns();
DataRows = new CustomReportDataRows();
}
public int GroupDepth { get; set; }
public CustomReportColumns Columns { get; set; }
public CustomReportGroups Groups { get; set; }
public CustomReportDataRows DataRows { get; set; }
public string ReportTitle { get; set; }
}
PDF Conversion
using iTextSharp.text;
using iTextSharp.text.pdf;
using Svg;
public class PDFServiceiTextSharp:IPDFService
{
private int _GroupDepth=0;
private int _ColumnCount = 0;
//-----------------------------------------------------------------------------------------------------------------------------------------
public byte[] RenderCustomReport(CustomReportData data)
{
try
{
using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("INMEMORYPDF.pdf", 1000000))
{
PDFPageMargins margins = new PDFPageMargins(10, 10, 10, 10);
_GroupDepth = data.GroupDepth;
_ColumnCount = data.Columns.Count;
float _pageWidth = this.GetPageWidth(data.Columns, margins);
var document=new Document((_pageWidth>540)?PageSize.A4.Rotate(): PageSize.A4, margins.Left,margins.Right, margins.Top, margins.Bottom);
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
PdfWriter.GetInstance(document, stream);
document.Open();
var pdfTable = new PdfPTable(_ColumnCount + _GroupDepth);
int[] columnWidths = new int[_ColumnCount + _GroupDepth];
for(int x=0;x<_GroupDepth;x++)
columnWidths[x]=3;
for(int y=0;y<data.Columns.Count;y++)
columnWidths[_GroupDepth + y] = Convert.ToInt32(data.Columns[y].Width);
pdfTable.SetWidths(columnWidths);
pdfTable.DefaultCell.Padding = 3;
pdfTable.DefaultCell.BorderWidth = 1;
pdfTable.DefaultCell.HorizontalAlignment = Element.ALIGN_TOP;
this.CreateHeaderColumns(pdfTable, data.Columns);
pdfTable.HeaderRows = 1;
pdfTable.DefaultCell.BorderWidth = 1;
if (data.Groups.Count > 0)
this.CreateGroupData(pdfTable, data.Groups, 0);
else
for (int x = 0; x < data.DataRows.Count; x++)
this.CreateDetailColumns(pdfTable, data.DataRows[x]);
document.Add(pdfTable);
document.Close();
}
byte[] content;
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryReader rdr = new BinaryReader(stream);
content = new byte[mmf.CreateViewStream().Length];
rdr.Read(content, 0, (int)mmf.CreateViewStream().Length);
}
return content;
}
}
catch
{
throw;
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
public float GetPageWidth(CustomReportColumns columns, PDFPageMargins margins)
{
float width=0;
foreach (CustomReportColumn c in columns)
width += c.Width;
return width + margins.Left + margins.Right + (_GroupDepth * 3);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateHeaderColumns(PdfPTable table,CustomReportColumns columns)
{
Font headerFont = this.GetHeaderFont();
for(int gc=0;gc<_GroupDepth;gc++)
{
PdfPCell cell = new PdfPCell(new Phrase("", headerFont));
cell.BorderWidth=0;
table.AddCell(cell);
}
for (int x = 0; x < columns.Count; x++)
{
PdfPCell cell = new PdfPCell(new Phrase(columns[x].FieldName, headerFont));
cell.BorderColor = new BaseColor(100, 149, 237);
cell.HorizontalAlignment = Element.ALIGN_CENTER;
cell.BorderWidth=0.75f;
cell.Border = Rectangle.BOTTOM_BORDER | Rectangle.TOP_BORDER | Rectangle.RIGHT_BORDER | Rectangle.LEFT_BORDER;
cell.PaddingBottom = 10;
cell.PaddingLeft = 3;
cell.PaddingRight = 3;
cell.PaddingTop = 10;
table.AddCell(cell);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateGroupData(PdfPTable table, CustomReportGroups parentgroups, int groupDepth)
{
if ((parentgroups == null)||(parentgroups.Count==0))
return;
groupDepth++;
foreach (CustomReportGroup group in parentgroups)
{
this.CreateGroupHeader(table, group, groupDepth);
for (int x = 0; x < group.DataRows.Count; x++)
this.CreateDetailColumns(table, group.DataRows[x]);
CreateGroupData(table, group.Groups, groupDepth);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateDetailColumns(PdfPTable table, CustomReportDataRow row)
{
Font detailFont = this.GetDetailFont();
for (int gc = 1; gc <= _GroupDepth; gc++)
{
BaseColor groupColor = this.GetGroupHeaderColor(_GroupDepth);
PdfPCell cell = new PdfPCell(new Phrase("", detailFont));
cell.BackgroundColor = groupColor;
cell.BorderColor = groupColor;
cell.BorderWidth = 0.75f;
table.AddCell(cell);
}
for (int x = 0; x < row.Fields.Count; x++)
{
PdfPCell cell = new PdfPCell(new Phrase(row.Fields[x], detailFont));
cell.BorderColor = new BaseColor(211, 211, 211);
cell.HorizontalAlignment = Element.ALIGN_CENTER;
cell.BorderWidth = 0.75f;
cell.Border = Rectangle.BOTTOM_BORDER | Rectangle.TOP_BORDER | Rectangle.RIGHT_BORDER | Rectangle.LEFT_BORDER;
cell.PaddingBottom = 1;
cell.PaddingLeft = 3;
cell.PaddingRight = 3;
cell.PaddingTop = 1;
table.AddCell(cell);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateGroupHeader(PdfPTable table, CustomReportGroup group, int depth)
{
Font detailFont = this.GetDetailFont();
for (int gc = 1; gc <= _GroupDepth; gc++)
{
BaseColor depthColor = this.GetGroupHeaderColor(depth);
PdfPCell ecell = new PdfPCell(new Phrase("", detailFont));
ecell.BackgroundColor = depthColor;
ecell.BorderColor = depthColor;
ecell.BorderWidth = 0.75f;
table.AddCell(ecell);
}
BaseColor groupColor = this.GetGroupHeaderColor(depth);
PdfPCell cell = new PdfPCell(new Phrase( group.GroupValue, detailFont));
cell.Colspan = _ColumnCount + ((_GroupDepth - depth));
cell.BorderColor = groupColor;
cell.BackgroundColor = groupColor;
cell.HorizontalAlignment = Element.ALIGN_LEFT;
cell.BorderWidth = 0.75f;
cell.Border = Rectangle.BOTTOM_BORDER | Rectangle.TOP_BORDER | Rectangle.RIGHT_BORDER | Rectangle.LEFT_BORDER;
cell.PaddingBottom = 3;
cell.PaddingLeft = 3;
cell.PaddingRight = 3;
cell.PaddingTop = 3;
table.AddCell(cell);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private Font GetHeaderFont()
{
return FontFactory.GetFont("Arial", 10, Font.BOLD, BaseColor.BLACK);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private Font GetDetailFont()
{
return FontFactory.GetFont("Arial", 8, Font.NORMAL, BaseColor.BLACK);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private BaseColor GetGroupHeaderColor(int groupDepth)
{
switch (groupDepth)
{
case 1: return new BaseColor(211,211,211);
case 2: return new BaseColor(100, 149, 237);
case 3: return new BaseColor(255,165,0);
case 4: return new BaseColor(169,169,169);
case 5: return new BaseColor(211, 211, 211);
default: return new BaseColor(211, 211, 211);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
public void MergeFiles(System.Collections.Generic.List<string> sourceFiles, string destinationFile)
{
Document document=null;
if (System.IO.File.Exists(destinationFile))
System.IO.File.Delete(destinationFile);
try
{
PdfCopy writer = null;
int numberOfPages=0;
foreach(string sourceFile in sourceFiles)
{
PdfReader reader = new PdfReader(sourceFile);
reader.ConsolidateNamedDestinations();
numberOfPages = reader.NumberOfPages;
if(document==null)
{
document = new Document(reader.GetPageSizeWithRotation(1));
writer = new PdfCopy(document, new FileStream(destinationFile, FileMode.Create));
document.Open();
}
for (int x = 1;x <= numberOfPages;x++ )
{
if (writer != null)
{
PdfImportedPage page = writer.GetImportedPage(reader, x);
writer.AddPage(page);
}
}
PRAcroForm form = reader.AcroForm;
if (form != null && writer != null)
{
writer.CopyAcroForm(reader);
}
}
}
catch
{
throw;
}
finally
{
if (document != null && document.IsOpen())
document.Close();
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
public byte[] RenderReportFromSVG(string svgFileContents)
{
System.Drawing.Bitmap _bitmap=null;
byte[] byteArray = Encoding.ASCII.GetBytes(svgFileContents);
using (var stream = new MemoryStream(byteArray))
{
XmlDocument xdoc=new XmlDocument();
xdoc.LoadXml(svgFileContents);
var svgDocument = SvgDocument.Open(xdoc);
_bitmap = svgDocument.Draw();
}
using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("INMEMORYPDF.pdf", 1000000))
{
PDFPageMargins margins = new PDFPageMargins(10, 10, 10, 10);
float _pageWidth = margins.Left + margins.Right + _bitmap.Width;
var document = new Document((_pageWidth > 540) ? PageSize.A4.Rotate() : PageSize.A4, margins.Left, margins.Right, margins.Top, margins.Bottom);
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
PdfWriter.GetInstance(document, stream);
document.Open();
iTextSharp.text.Image pdfImage = iTextSharp.text.Image.GetInstance(_bitmap, System.Drawing.Imaging.ImageFormat.Bmp);
var pdfTable = new PdfPTable(1);
pdfTable.SetWidths(new int[]{_bitmap.Width});
pdfTable.DefaultCell.HorizontalAlignment = Element.ALIGN_TOP;
PdfPCell cell = new PdfPCell(pdfImage);
//cell.FixedHeight = fixedHeight;
cell.HorizontalAlignment = Element.ALIGN_CENTER;
cell.VerticalAlignment = Element.ALIGN_MIDDLE;
//img.ScaleAbsolute(200, fixedHeight);
pdfTable.AddCell(cell);
document.Add(pdfTable);
document.Close();
}
byte[] content;
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryReader rdr = new BinaryReader(stream);
content = new byte[mmf.CreateViewStream().Length];
rdr.Read(content, 0, (int)mmf.CreateViewStream().Length);
}
return content;
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
}
Finally the ExcelService to render grid to excel with column groupings
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
public class ExcelServiceNPOI:IExcelService
{
//-----------------------------------------------------------------------------------------------------------------------------------------
public byte[] RenderCustomReport(CustomReportData data)
{
try
{
if (data == null)
throw new ArgumentNullException("Report data cannot be null");
HSSFWorkbook workBook = new HSSFWorkbook();
ISheet sheet = workBook.CreateSheet(data.ReportTitle);
if (data.Groups.Count > 0)
{
int maxDepth = data.GroupDepth;// this.GroupDepth(data.Groups, 0);
this.CreateColumnHeader(sheet,maxDepth, data.Columns );
this.CreateGroupData(sheet, data.Groups, 0, maxDepth);
}
else
{
this.CreateColumnHeader(sheet, data.Columns);
this.CreateRowData(sheet, data.DataRows);
}
this.SetColumnWidth(sheet, data.Columns);
sheet.CreateFreezePane(0, 1);
MemoryStream ms = new MemoryStream();
workBook.Write(ms);
return ms.ToArray();
}
catch
{
throw;
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateColumnHeader(ISheet sheet,CustomReportColumns columns)
{
this.CreateColumnHeader(sheet, 0, columns);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateColumnHeader(ISheet sheet, int columnOffset, CustomReportColumns columns )
{
if (columns == null || columns.Count == 0)
return;
IRow headerRow = sheet.CreateRow(0);
int colCount = columnOffset;
foreach (CustomReportColumn column in columns)
{
headerRow.CreateCell(colCount).SetCellValue(column.FieldName);
colCount++;
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateGroupData(ISheet sheet, CustomReportGroups parentgroups,int groupDepth, int maxDepth)
{
if (parentgroups == null)
return;
groupDepth++;
foreach (CustomReportGroup group in parentgroups)
{
CustomReportDataRow groupHeader = new CustomReportDataRow();
groupHeader.Fields.Add(group.GroupValue);
this.CreateRowData(sheet,groupDepth-1, groupHeader);
int groupBeginRowNum = sheet.LastRowNum+1;
this.CreateRowData(sheet,maxDepth, group.DataRows);
CreateGroupData(sheet,group.Groups, groupDepth, maxDepth);
sheet.GroupRow(groupBeginRowNum, sheet.LastRowNum);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateRowData(ISheet sheet, int startColumnIndex, CustomReportDataRow row)
{
int colNum = startColumnIndex;
IRow newRow = sheet.CreateRow(sheet.LastRowNum + 1);
foreach (string field in row.Fields)
newRow.CreateCell(colNum++).SetCellValue(field);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateRowData(ISheet sheet, CustomReportDataRows rows)
{
CreateRowData(sheet, 0, rows);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateRowData(ISheet sheet, int startColumnIndex, CustomReportDataRows rows)
{
foreach (CustomReportDataRow row in rows)
{
int colNum = startColumnIndex;
IRow newRow = sheet.CreateRow(sheet.LastRowNum + 1);
foreach (string field in row.Fields)
newRow.CreateCell(colNum++).SetCellValue(field);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void SetColumnWidth(ISheet sheet, CustomReportColumns columns)
{
if (columns == null || columns.Count == 0)
return;
for (int x = 0; x < columns.Count;x++ )
sheet.AutoSizeColumn(x);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
}
Feel free to use it. It works with the latest version of Kendo. I have also added a function RenderReportFromSVG() It will print a Kendo Chart to pdf using chart.svgContents

JTable unable to change cell value

I have created a method to created JTable as per below:
public void refTable(String jobNo) {
Report rp = new Report();
final String noJob = jobNo;
Map<Integer, String> jMap = rp.getReportInfo(jobNo);
Map<Integer, String> sortedMap = new TreeMap<Integer, String>(jMap);
String[] row = new String[sortedMap.size()];
Integer[] no = new Integer[sortedMap.size()];
String[] stat = new String[sortedMap.size()];
Boolean[] dev = new Boolean[sortedMap.size()];
String[] remark = new String[sortedMap.size()];
Boolean[] rem = new Boolean[sortedMap.size()];
userRemark = new String[sortedMap.size()];
tabSize = sortedMap.size();
int i = 0;
for (Integer key : sortedMap.keySet()) {
no[i] = key;
String[] val = sortedMap.get(key).split("###");
if (val[0].trim().equals("DEV")) {
stat[i] = "FAIL";
} else {
stat[i] = val[0].trim();
}
row[i] = val[1].trim();
dev[i] = false;
remark[i] = "";
//remark[i] = false;
//if(userRemark1[i]!=null)
userRemark[i] = RemarkDropDownList.userOthersReamrk;
//else
//userRemark[i] ="";
rem[i] = false;
i++;
}
DefaultTableModel model = new DefaultTableModel();
model.fireTableDataChanged();
jTable1.setModel(model);
model.addColumn("No:", no);
model.addColumn("Status:", stat);
model.addColumn("Details:", row);
model.addColumn("Non-Deviation", dev);
model.addColumn("Remarks", remark);
model.addColumn("Remove", rem);
model.addColumn("UR", userRemark);
TableColumn col1 = jTable1.getColumnModel().getColumn(0);
col1.setPreferredWidth(30);
TableColumn col2 = jTable1.getColumnModel().getColumn(1);
col2.setPreferredWidth(30);
TableColumn col3 = jTable1.getColumnModel().getColumn(2);
TextRenderer renderer = new TextRenderer();
col3.setCellRenderer(renderer);
col3.setPreferredWidth(350);
CellRenderer cellRender = new CellRenderer();
TableColumn col4 = jTable1.getColumnModel().getColumn(3);
col4.setCellEditor(jTable1.getDefaultEditor(Boolean.class));
col4.setCellRenderer(cellRender);
col4.setPreferredWidth(50);
TableButton buttonEditor = new TableButton("Button");
buttonEditor.addTableButtonListener(new TableButtonListener() {
//#Override
public void tableButtonClicked(int row, int col) {
RemarkDropDownList rmk = new RemarkDropDownList(noJob, row);
rmk.setVisible(true);
//userRemark1[row] = RemarkDropDownList.userOthersReamrk;
//String test = RemarkDropDownList.userOthersReamrk;
}
});
TableColumn col5 = jTable1.getColumnModel().getColumn(4);
col5.setCellRenderer(buttonEditor);
col5.setCellEditor(buttonEditor);
TableColumn col6 = jTable1.getColumnModel().getColumn(5);
col6.setCellEditor(jTable1.getDefaultEditor(Boolean.class));
col6.setCellRenderer(jTable1.getDefaultRenderer(Boolean.class));
col6.setPreferredWidth(50);
jTable1.setShowGrid(true);
jTable1.setGridColor(Color.BLACK);
jTable1.setAutoCreateRowSorter(true);
}
In my JTable I've created a button in column 5 like this.
TableButton buttonEditor = new TableButton("Button");
buttonEditor.addTableButtonListener(new TableButtonListener() {
//#Override
public void tableButtonClicked(int row, int col) {
RemarkDropDownList rmk = new RemarkDropDownList(noJob, row);
rmk.setVisible(true);
//userRemark1[row] = RemarkDropDownList.userOthersReamrk;
//String test = RemarkDropDownList.userOthersReamrk;
}
});
TableColumn col5 = jTable1.getColumnModel().getColumn(4);
col5.setCellRenderer(buttonEditor);
col5.setCellEditor(buttonEditor);
The button basically create a new JFrame with combobox inside it like this.
public class RemarkDropDownList extends javax.swing.JFrame {
public static String userOthersReamrk = "test";
private String userSelectedItem = "File Issue";
String jobno;
int rowNo;
public RemarkDropDownList() {
initComponents();
this.lblOthers.setVisible(false);
this.txtOthers.setVisible(false);
}
public RemarkDropDownList(String jobNo, int row) {
initComponents();
this.lblOthers.setVisible(false);
this.txtOthers.setVisible(false);
this.jobno = jobNo;
this.rowNo = row;
}
private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
JComboBox cb = (JComboBox)evt.getSource();
userSelectedItem = (String)cb.getSelectedItem();
if(userSelectedItem.equalsIgnoreCase("others"))
{
this.lblOthers.setVisible(true);
this.txtOthers.setVisible(true);
}
else
{
this.lblOthers.setVisible(false);
this.txtOthers.setVisible(false);
}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if(userSelectedItem.equalsIgnoreCase("others"))
{
userOthersReamrk = txtOthers.getText().toString();
if(userOthersReamrk == null || userOthersReamrk.equalsIgnoreCase(""))
{
JOptionPane.showMessageDialog(null, "Please enter Remark");
}
}
else
{
userOthersReamrk = userSelectedItem;
//String [] remark = new String [1000];
///remark[rowNo] = userOthersReamrk;
ReportPanelMin rpm = new ReportPanelMin();
//rpm.userRemark1[rowNo] = remark[rowNo];
rpm.refTable(jobno);
this.setVisible(false);
}
}
}
Everything is working, but the last part. I've created a static global variable (userOthersReamrk) in RemarkDropDownList class (the new class) to hold user drop down selected value. I call the refTable function again to reload the table so i can assign the userOthersReamrk value to column no 7 like this userRemark = new String[sortedMap.size()];. When i debug, I can see the user selected value is assigned touserRemark array but its not population in the table. The column showing the default value test which i decalred in RemarkDropDownList. I know the code is so long, but i post everything to give better understanding on what im doing. What/where i need to make change so my user's selected value is shown in column 7 instead the default value.

Unable to populate table with data from database

I have problem when trying to fetch the data from database and display in database. I get from user input and store as a search variable. This is how I set up my table:
//I get the user input to perform search
#FXML
public void searchResident(ActionEvent event){
String search=getTb_search().getText();
if(search.equals("")){
Dialogs.showErrorDialog(null, "Please enter something", "Blank fields detected", "");
}else{
setUpSearchTable(search);
}
}
//How I set up my table
public void setUpSearchTable(String search) {
TableColumn rmNameCol = new TableColumn("Name");
rmNameCol.setVisible(true);
rmNameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<SearchNeedyResidentController, String>, ObservableValue<String>>() {
public ObservableValue<String> call(TableColumn.CellDataFeatures<SearchNeedyResidentController, String> p) {
return p.getValue().searchNameProperty();
}
});
TableColumn rmNricCol = new TableColumn("NRIC");
rmNricCol.setCellValueFactory(new PropertyValueFactory<SearchNeedyResidentController, String>("search_nric"));
rmNricCol.setMinWidth(150);
TableColumn rmPhNoCol = new TableColumn("Phone Number");
rmPhNoCol.setCellValueFactory(new PropertyValueFactory<SearchNeedyResidentController,String>("search_phNo"));
rmPhNoCol.setMinWidth(350);
TableColumn rmIncomeCol = new TableColumn("Income($)");
rmIncomeCol.setCellValueFactory(new PropertyValueFactory<SearchNeedyResidentController, String>("search_income"));
rmIncomeCol.setMinWidth(100);
ResidentManagement.entity.NeedyResidentEntity searchValue= new ResidentManagement.entity.NeedyResidentEntity();
//viewProduct.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table_search.setEditable(false);
table_search.getColumns().addAll(rmNricCol, rmNameCol, rmIncomeCol, rmPhNoCol);
table_search.getItems().setAll(searchValue.searchResident(search));
}
}
//How I populate the table data
public List<SearchNeedyResidentController> searchResident(String search){
List ll = new LinkedList();
try {
DBController db = new DBController();
db.getConnection();
String sql = "SELECT * FROM rm_needyresident WHERE name LIKE '" + search + "%'";
ResultSet rs = null;
// Call readRequest to get the result
rs = db.readRequest(sql);
while (rs.next()) {
String nric=rs.getString("nric");
String name = rs.getString("name");
double income = rs.getDouble("familyIncome");
String incomeStr = new DecimalFormat("##.00").format(income);
String phNo = rs.getString("phNo");
SearchNeedyResidentController row = new SearchNeedyResidentController();
row.setSearchNric(nric);
row.setSearchName(name);
row.setSearchIncome(incomeStr);
row.setSearchPhNo(phNo);
ll.add(row);
}
rs.close();
} catch (SQLException ex) {
ex.printStackTrace();
System.out.println("Error SQL!!!");
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
}
return ll;
}
}
When search button is on click, the table column is displayed. However, it's just show a blank table even though there's matching result. I debug already and I think the error is at the retrieving data in the searchResident method. It's not retriving the data from database. Anybody know what's wrong?
Thanks in advance.
try dis one...
#FXML private void SearchButton()
{
Connection c ;
datamem = FXCollections.observableArrayList();
try
{
c = Dao.getCon();
String SQL =SELECT * FROM `Member`;
ResultSet rs = c.createStatement().executeQuery(SQL);
if(table.getColumns().isEmpty())
{
for(int i=0 ; i<rs.getMetaData().getColumnCount(); i++)
{
final int j = i;
TableColumn col = new TableColumn(rs.getMetaData().getColumnName(i+1));
col.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList,String>,ObservableValue<String>>(){
public ObservableValue<String> call(TableColumn.CellDataFeatures<ObservableList, String> param) {
return new SimpleStringProperty(param.getValue().get(j).toString());
}
});
table.getColumns().addAll(col);
}//for
}//if
while(rs.next())
{
ObservableList<String> row = FXCollections.observableArrayList();
for(int i=1 ; i<=rs.getMetaData().getColumnCount(); i++)
{
row.add(rs.getString(i));
}// for
datamem.add(row);
}//while
table.setItems(datamem);
}//try
catch(Exception e)
{
JOptionPane.showMessageDialog(null, "Problem in Search Button "+e);
}
}//else
}//else
} //search method

How to make the jList selectable inside a jTable

How to make the jList selectable and jScrollPane scrollable inside a jTable.
This is my table code :
private JTable getCalendarTable() {
if (calendarTable == null) {
calendarTable = new JTable() {
public boolean isCellEditable(int nRow, int nCol) {
if (nRow % 2 != 0) {
return true;
} else
return false;
}
};
DefaultTableModel mtblCalendar = (DefaultTableModel) calendarTable
.getModel();
String[] headers = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
"Sat" };
for (int i = 0; i < 7; i++) {
mtblCalendar.addColumn(headers[i]);
}
calendarTable.setCellSelectionEnabled(true);
calendarTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
calendarTable.setRowHeight(60);
mtblCalendar.setColumnCount(7);
mtblCalendar.setRowCount(12);
GregorianCalendar cal = new GregorianCalendar();
realDay = cal.get(GregorianCalendar.DAY_OF_MONTH); // Get day
realMonth = cal.get(GregorianCalendar.MONTH); // Get month
realYear = cal.get(GregorianCalendar.YEAR); // Get year
currentMonth = realMonth; // Match month and year
currentYear = realYear;
refreshCalendar(currentMonth, currentYear);
}
return calendarTable;
}
class tblCalendarRenderer extends JTextArea implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean selected, boolean focused, int row,
int column) {
this.setText(value == null ? "" : value.toString());
this.setLineWrap(true);
this.setWrapStyleWord(true);
if (column == 0 || column == 6) { // Week-end
setBackground(new Color(255, 220, 220));
} else { // Week
setBackground(new Color(255, 255, 255));
}
if (row % 2 == 0) {
if (value != null) {
if (Integer.parseInt(value.toString()) == realDay
&& currentMonth == realMonth
&& currentYear == realYear) { // Today
setBackground(new Color(220, 220, 255));
}
}
} else {
if (value != null) {
// Here is just an test data I want to make sure the jList is working. When
// the date has event, show jList
JList list = new JList(new Object[] { "werwre", "fsdfsd",
"details", "computer", "folder", "computer" });
list.setVisibleRowCount(4);
JScrollPane pane = new JScrollPane(list);
list.setCellRenderer(new Incorenderer());
return pane;
}
}
return this;
}
}
}
The JList and JScrollPanel appeared when the date has event. But the jList was unselectable and the scrollpanel was unscrollable.
You need to use your code that draws a JList in a TableCellRenderer implementation and use it as an editor, i.e.:
class CalendarCellEditor extends AbstractCellEditor implements TableCellEditor {
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
if (value != null) {
// Here is just an test data I want to make sure the jList is
// working. When
// the date has event, show jList
JList list = new JList(new Object[] { "werwre", "fsdfsd",
"details", "computer", "folder", "computer" });
list.setVisibleRowCount(4);
JScrollPane pane = new JScrollPane(list);
list.setCellRenderer(new Incorenderer());
return pane;
} else {
// TODO return whatever you need
return null;
}
}
public Object getCellEditorValue() {
// TODO return whatever you need
return 1;
}
}
And add this editor to your table by overriding the following method in you anonymous inner JTable class:
public TableCellEditor getCellEditor(int row, int column) {
return new CalendarCellEditor();
}