JTable-Paint the content(text) in a cell - java

I have a JTable and i have a method which implements search in table rows and columns, i use regular expressions and i want to paint(eg yellow) the text which matches with the regular expression in the cell. I want to paint the text not the background of the cell and only the part of word which matches with reg expression.
The code for my search method is:
for (int row = 0; row <= table.getRowCount() - 1; row++) {
for (int col = 0; col <= table.getColumnCount() - 1; col++) {
Pattern p = Pattern.compile("(?i)" + search_txt.getText().trim());
Matcher m = p.matcher(table.getValueAt(row, col).toString().trim());
if (m.find()){
isFound = true;
table.scrollRectToVisible(table.getCellRect(row, 0, true));
table.setRowSelectionInterval(row, row);
break;
}
}
}

You will need a custom renderer to do this.
The default renderer is a JLabel. So the only way to do this would to wrap HTML around your text string and change the font color of the text you are searching for. You would need to pass the search text to the renderer so the renderer can determine which text to highlight.
The code you posted has a problem in that it will always scroll to the bottom of the table. So what is your exact requirement. Do you want to highlight all cells at one time. Or do you just want to have a "Next" button that will find the next cell with the text. In the first case you would not want to automatically scroll the table. In the second case you would scroll the table.
Also, depending on the requirement you would need to either repaint the entire table (if you show all occurrences at once) or only the current row (if you have next functionality).
Edit:
Normally when you add text to a label you use:
label.setText("user1005633");
If you want to highlight any text containing "100" then you would need to do:
label.setText("<html>user<font color="yellow">100</font>5633</html>");
This is what I mean by wrapping.

Related

JTable Column Headers with wrapped and center aligned text

I am currently trying to wrap and align center text of a column header. The problem seems to be that while the first line of column header is aligned, the second one does not get aligned properly.
I am using DefaultTableCellRenderer to render it as such:
public void centerAlign(JTable t, int numberOfColumns){
centerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
for (int i = 0; i < numberOfColumns; i++){
t.getColumnModel().getColumn(i).setCellRenderer(centerRenderer);
}
headerRender = (DefaulttableCellRenderer)
t.getTableHeader().getDefaultRenderer();
headerRenderer.setHorizontalAlignment(JLabel.CENTER);
}
In your table model class use html of column name
example:
"<html><center>First column</html>"

JTable setPreferredWidth() for columns displaying incorrectly

I have a JTable with an AbstractTabelModel displayed. I tried to create a void method in my project that sets the width of each column to the length of the longest value in the column. Here is the method that I am using right now, where "accountWindow" is the JTable:
public void setColumnWidths(){
accountWindow.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
for (int i = 0; i < accountWindow.getColumnCount(); i++){
int greatestStringLength = 2;
for (int z = 0; z < accountWindow.getRowCount(); z++){
if (accountWindow.getValueAt(z, i).toString().length() > greatestStringLength){
System.out.println("Width SET");
greatestStringLength = accountWindow.getValueAt(z, i).toString().length();
accountWindow.getColumnModel().getColumn(i).setPreferredWidth(greatestStringLength);
}
//System.out.println(accountWindow.getValueAt(z, i).toString());
//System.out.println("Greatest Value: " + greatestValueWidth);
}
}
}
The method is called correctly in my Controller class (MVC), but it is setting the width of each column to essentially 0. Method is called after the table is updated and the fireTableData() method is called and account information is displayed. I have added the JTable to a scroll pane. Any comments or suggestions would be appreciated.
The width needs to be specified in pixels not characters in the String.
if (accountWindow.getValueAt(z, i).toString().length() > greatestStringLength){
Looks to me like you are just getting the number of characters in the String, not the width it takes to render the String. That is 20 characters will NOT render in 20 pixels. The width of the String will vary for different Fonts.
Check out Table Column Adjuster for the solution on how to determine the rendered width. It gives a simple usage and a custom class that you can use which has more features.
Both solutions will actually invoke the renderer used by the table to determine the maximum width.

Keep cell content on one page

I have a table, with one column. Each cell contains a paragraph.
How can I stop paragraphs from splitting across two pages?
PdfPtable table = new PdfPTable(1);
//report must be printed as compat as possible
table.setSplitLate(false);
//I can't set keep together, because table can be larger than page size
//table.setKeepTogether(true);
for (int i = 0; i < 100; i++) {
//Random text. Can contain ~400 chars.
String text = "aaaaaaaaaaaaaaa sssssssssssss ddddddddddd ffffffffff";
Paragraph p = new Paragraph(text);
//That instruction does not work. I don't know why, may be because paragraph printed in cell.
p.setKeepTogether(true);
table.addCell(p);
}
Change
table.setSplitLate(false);
into
table.setSplitLate(true);
This way, your cell will not be split unless the complete cell doesn't fit on a single page.

Highlight found data in JTable row

I want to search data from JTable when data found then I want to highlight table row. This code is work properly search record but I don't know what I do for highlight the row.
String target = jTextField1.getText();
for(int row = 0; row < jTable1.getRowCount(); row++)
for(int col = 0; col < jTable1.getColumnCount(); col++)
{
String next = (String)jTable1.getValueAt(row, col);
if(next.equals(target))
{
System.out.println("found");// here what change for highlight row.
}
}
The answer depends on your idea of "highlighting"
You could use JTable#addRowSelection to highlight a row using the default selection
Or, you could setup your cell renders to apply additional highlighting support via an additional lookup to determine if the cell/row should be highlighted
Or, you could use the inbuilt filtering capabilities of the JTable to filter out unwanted content
See How to use tables for more details
Or, you could use the highlighting support from the SwingLabs, SwingX librRies
We can achieve that with a custom JLabel and TableCellRenderer.
Following example does the highlighting on the found (filtered) rows in JTable. The rows are filtered via RowFilter:
http://www.logicbig.com/tutorials/core-java-tutorial/swing/jtable-row-filter-highlighting/
else if(e.getSource()==field){
int z;
for(z = 0;z<table.getRowCount();z++){
if(Integer.parseInt(field.getText()) == Integer.parseInt((String)table.getValueAt(z, 1))){
break;
}
}
table.setRowSelectionInterval(z, z);
}
i had the same problem and this was how i went about it.

Java JTable setting Column Width

I have a JTable in which I set the column size as follows:
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getColumnModel().getColumn(0).setPreferredWidth(27);
table.getColumnModel().getColumn(1).setPreferredWidth(120);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(90);
table.getColumnModel().getColumn(4).setPreferredWidth(90);
table.getColumnModel().getColumn(6).setPreferredWidth(120);
table.getColumnModel().getColumn(7).setPreferredWidth(100);
table.getColumnModel().getColumn(8).setPreferredWidth(95);
table.getColumnModel().getColumn(9).setPreferredWidth(40);
table.getColumnModel().getColumn(10).setPreferredWidth(400);
This works fine, but when the table is maximized, I get empty space to the right of the last column. Is it possible to make the last column resize to the end of the window when resized?
I found AUTO_RESIZE_LAST_COLUMN property in docs but it does not work.
Edit: JTable is in a JScrollPane its prefered size is set.
What happens if you call setMinWidth(400) on the last column instead of setPreferredWidth(400)?
In the JavaDoc for JTable, read the docs for doLayout() very carefully. Here are some choice bits:
When the method is called as a result of the resizing of an enclosing window, the
resizingColumn is null. This means that resizing has taken place "outside" the JTable
and the change - or "delta" - should be distributed to all of the columns regardless of
this JTable's automatic resize mode.
This might be why AUTO_RESIZE_LAST_COLUMN didn't help you.
Note: When a JTable makes adjustments to the widths of the columns it respects their
minimum and maximum values absolutely.
This says that you might want to set Min == Max for all but the last columns, then set Min = Preferred on the last column and either not set Max or set a very large value for Max.
With JTable.AUTO_RESIZE_OFF, the table will not change the size of any of the columns for you, so it will take your preferred setting. If it is your goal to have the columns default to your preferred size, except to have the last column fill the rest of the pane, You have the option of using the JTable.AUTO_RESIZE_LAST_COLUMN autoResizeMode, but it might be most effective when used with TableColumn.setMaxWidth() instead of TableColumn.setPreferredWidth() for all but the last column.
Once you are satisfied that AUTO_RESIZE_LAST_COLUMN does in fact work, you can experiment with a combination of TableColumn.setMaxWidth() and TableColumn.setMinWidth()
JTable.AUTO_RESIZE_LAST_COLUMN is defined as "During all resize operations, apply adjustments to the last column only" which means you have to set the autoresizemode at the end of your code, otherwise setPreferredWidth() won't affect anything!
So in your case this would be the correct way:
table.getColumnModel().getColumn(0).setPreferredWidth(27);
table.getColumnModel().getColumn(1).setPreferredWidth(120);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(90);
table.getColumnModel().getColumn(4).setPreferredWidth(90);
table.getColumnModel().getColumn(6).setPreferredWidth(120);
table.getColumnModel().getColumn(7).setPreferredWidth(100);
table.getColumnModel().getColumn(8).setPreferredWidth(95);
table.getColumnModel().getColumn(9).setPreferredWidth(40);
table.getColumnModel().getColumn(10).setPreferredWidth(400);
table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
Use this method
public static void setColumnWidths(JTable table, int... widths) {
TableColumnModel columnModel = table.getColumnModel();
for (int i = 0; i < widths.length; i++) {
if (i < columnModel.getColumnCount()) {
columnModel.getColumn(i).setMaxWidth(widths[i]);
}
else break;
}
}
Or extend the JTable class:
public class Table extends JTable {
public void setColumnWidths(int... widths) {
for (int i = 0; i < widths.length; i++) {
if (i < columnModel.getColumnCount()) {
columnModel.getColumn(i).setMaxWidth(widths[i]);
}
else break;
}
}
}
And then
table.setColumnWidths(30, 150, 100, 100);
Reading the remark of Kleopatra (her 2nd time she suggested to have a look at javax.swing.JXTable, and now I Am sorry I didn't have a look the first time :) )
I suggest you follow the link
I had this solution for the same problem: (but I suggest you follow the link above)
On resize the table, scale the table column widths to the current table total width.
to do this I use a global array of ints for the (relative) column widths):
private int[] columnWidths=null;
I use this function to set the table column widths:
public void setColumnWidths(int[] widths){
int nrCols=table.getModel().getColumnCount();
if(nrCols==0||widths==null){
return;
}
this.columnWidths=widths.clone();
//current width of the table:
int totalWidth=table.getWidth();
int totalWidthRequested=0;
int nrRequestedWidths=columnWidths.length;
int defaultWidth=(int)Math.floor((double)totalWidth/(double)nrCols);
for(int col=0;col<nrCols;col++){
int width = 0;
if(columnWidths.length>col){
width=columnWidths[col];
}
totalWidthRequested+=width;
}
//Note: for the not defined columns: use the defaultWidth
if(nrRequestedWidths<nrCols){
log.fine("Setting column widths: nr of columns do not match column widths requested");
totalWidthRequested+=((nrCols-nrRequestedWidths)*defaultWidth);
}
//calculate the scale for the column width
double factor=(double)totalWidth/(double)totalWidthRequested;
for(int col=0;col<nrCols;col++){
int width = defaultWidth;
if(columnWidths.length>col){
//scale the requested width to the current table width
width=(int)Math.floor(factor*(double)columnWidths[col]);
}
table.getColumnModel().getColumn(col).setPreferredWidth(width);
table.getColumnModel().getColumn(col).setWidth(width);
}
}
When setting the data I call:
setColumnWidths(this.columnWidths);
and on changing I call the ComponentListener set to the parent of the table (in my case the JScrollPane that is the container of my table):
public void componentResized(ComponentEvent componentEvent) {
this.setColumnWidths(this.columnWidths);
}
note that the JTable table is also global:
private JTable table;
And here I set the listener:
scrollPane=new JScrollPane(table);
scrollPane.addComponentListener(this);
This code is worked for me without setAutoResizeModes.
TableColumnModel columnModel = jTable1.getColumnModel();
columnModel.getColumn(1).setPreferredWidth(170);
columnModel.getColumn(1).setMaxWidth(170);
columnModel.getColumn(2).setPreferredWidth(150);
columnModel.getColumn(2).setMaxWidth(150);
columnModel.getColumn(3).setPreferredWidth(40);
columnModel.getColumn(3).setMaxWidth(40);
fireTableStructureChanged();
will default the resize behavior ! If this method is called somewhere in your code AFTER you did set the column resize properties all your settings will be reset. This side effect can happen indirectly. F.e. as a consequence of the linked data model being changed in a way this method is called, after properties are set.
No need for the option, just make the preferred width of the last column the maximum and it will take all the extra space.
table.getColumnModel().getColumn(0).setPreferredWidth(27);
table.getColumnModel().getColumn(1).setPreferredWidth(120);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(90);
table.getColumnModel().getColumn(4).setPreferredWidth(90);
table.getColumnModel().getColumn(6).setPreferredWidth(120);
table.getColumnModel().getColumn(7).setPreferredWidth(100);
table.getColumnModel().getColumn(8).setPreferredWidth(95);
table.getColumnModel().getColumn(9).setPreferredWidth(40);
table.getColumnModel().getColumn(10).setPreferredWidth(Integer.MAX_INT);
Use this code. It worked for me. I considered for 3 columns. Change the loop value for your code.
TableColumn column = null;
for (int i = 0; i < 3; i++) {
column = table.getColumnModel().getColumn(i);
if (i == 0)
column.setMaxWidth(10);
if (i == 2)
column.setMaxWidth(50);
}

Categories