I'm trying to implement a search method in JTable, the search code is:
private void searchTable()
{
String id = inputIdField.getText();
for(int row = 0; row <= listAllTable.getRowCount() - 1; row++)
{
System.out.println(row);
if(id.equals(listAllTable.getValueAt(row, 0)))
{
listAllTable.scrollRectToVisible(listAllTable.getCellRect(row, 0, true));
listAllTable.setRowSelectionInterval(row, row);
for (int i = 0; i <= listAllTable.getColumnCount() - 1; i++)
{
listAllTable.getColumnModel().getColumn(i).setCellRenderer(new HighlightRenderer());
}
}
else
{
}
}
}
The method works only when I add String and Object:
final String[] columnNames = {"Name", "Surname", "Age"};
final Object[][] data = {{"Jhon", "Java", "23"}, {"Stupid", "Stupido", "500"},
{"Michael", "Winnie", "20"}, {"Winnie", "Thepoor", "23"},
{"Michael", "Winnie", "20"}, {"Winnie", "Thepoor", "23"}};
JTable listAllTable = new JTable(data, columnNames);
But when I fetch from DB, put it in the array and display it in the JTable the search method does not work, it get the rows perfectly, but it does not pass the if(id.equals(listAllTable.getValueAt(row, 0))) when the value exists, can somebody check the code and explain me why? Here is the code for building my JTable:
private void buildJTable(ArrayList<SalesOrder> list)
{
DefaultTableModel model = new DefaultTableModel()
{
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int row, int column)
{
return false;
}
};
model.setColumnIdentifiers(new String[] {"ID", "Customer ID", "Employee ID", "Voucher ID", "Status", "Date", "Price"});
model.setRowCount(list.size());
int row = 0;
for(SalesOrder so : list)
{
model.setValueAt(so.getId(), row, 0);
model.setValueAt(so.getCustomerId().getId(), row, 1);
model.setValueAt(so.getEmployeeId().getId(), row, 2);
model.setValueAt(so.getVoucherId().getId(), row, 3);
model.setValueAt(so.getStatus(), row, 4);
model.setValueAt(so.getDate(), row, 5);
model.setValueAt(so.getPrice(), row, 6);
row++;
}
listAllTable.setRowSelectionAllowed(true);
listAllTable.setModel(model);
}
Can somebody look at the code and explain me why it does not search my JTable when build from a method private void buildJTable(ArrayList<SalesOrder> list) ? It builds everything correclty but it does not search.
Thank you.
You are simply compare incompatible values. Try to change your search method as following
private void searchTable()
{
String id = inputIdField.getText();
for(int row = 0; row <= listAllTable.getRowCount() - 1; row++)
{
System.out.println(row);
String strVal = null == listAllTable.getValueAt(row, 0)? null : listAllTable.getValueAt(row, 0).toString();
if(id.equals(strVal))
{
listAllTable.scrollRectToVisible(listAllTable.getCellRect(row, 0, true));
listAllTable.setRowSelectionInterval(row, row);
for (int i = 0; i <= listAllTable.getColumnCount() - 1; i++)
{
listAllTable.getColumnModel().getColumn(i).setCellRenderer(new HighlightRenderer());
}
}
else
{
}
}
}
Related
I have a problem with my JTable. Firstly I selected some entries in my table. However when I deselect some of them, the table could not understand it.
Example scenario: I select job1 and 2 for the testing after that I change my mind and de-select job2. But in the result I saw job1 job1 and job2 ( job 1 seen 2 times and even though I dis-select job 2 I saw them.) Or after selected all the jobs ( choose all button) I want to deselect all of them (Clear button) when I click clear all the table seems empty. It is good but somehow the background of the program still protect the all old selection. How can I solve this?
Try:
I created the row of my table by read csv file.
public class JobSelectionListPanel extends JPanel {
private static final long serialVersionUID = 5198916547962359735L;
private static JobSelectionListPanel INSTANCE = new JobSelectionListPanel();
public static JobSelectionListPanel getInstance() {
return INSTANCE;
}
private JTable table;
private JButton next, back, btnClear, btnNewButton, btnChooseAll;
private JobList fnnJobList = new JobList();
private JobSelectionListPanel() {
table = new JTable();
JScrollPane scrollPane = new JScrollPane(table);
table.setBorder(new CompoundBorder());
// Read all FNN jobs from file
try {
fnnJobList.readFromFile("rules.csv");
} catch (IOException e1) {
System.out.println("You are not able to read the rules.csv file");
}
// Create ArrayList of JobNames
Object[][] initialData = new Object[fnnJobList.size()][1];
int i = 0;
for (Job jobDes : fnnJobList) {
initialData[i][0] = (Object) jobDes.getJobname();
i++;
}
String[] columnNames = new String[] { "", "Your preferences" };
table.setModel(new DefaultTableModel(initialData, columnNames) {
private static final long serialVersionUID = 1L;
#SuppressWarnings("rawtypes")
Class[] columnTypes = new Class[] { Object.class, Boolean.class };
#SuppressWarnings({ "unchecked", "rawtypes" })
public Class getColumnClass(int columnIndex) {
return columnTypes[columnIndex];
}
});
table.getColumnModel().getColumn(1).setPreferredWidth(80);
table.getColumnModel().getColumn(1).setMinWidth(40);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setCellSelectionEnabled(true);
I user want to choose all rows then I implemented this.
btnChooseAll = new JButton("Choose all");
btnChooseAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTableModel chooseAllData = (DefaultTableModel) table.getModel();
if (DeviceGroups.DeviceAList.size() == 0 || DeviceGroups.DeviceBList.size() == 0
|| DeviceGroups.DeviceCList.size() == 0 || DeviceGroups.DeviceDList.size() == 0)
JOptionPane.showMessageDialog(null,
"You should choose at least 1 device for each test device to apply this test case", "Invalid OPTION",
JOptionPane.ERROR_MESSAGE);
else
for (int i = 0; i < chooseAllData.getRowCount(); i++) {
for (int j = 1; j < chooseAllData.getColumnCount(); j++) {
chooseAllData.setValueAt(true, i, j);
}
}
}
});
For clear all preferences :
btnClear = new JButton("Clear all");
// Clear button create a model of JTable and delete all the rows of table!!
btnClear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTableModel clearTableData = (DefaultTableModel) table.getModel();
for (int i = 0; i < clearTableData.getRowCount(); i++) {
for (int j = 1; j < clearTableData.getColumnCount(); j++) {
clearTableData.setValueAt(null, i, j);
}
}
}
});
I see the following problem in your code: mixing up view indexes and model indexes. This is the offending snippet:
for (int i = 0; i < table.getRowCount(); i++) {
if (table.getValueAt(i, 1) != null) {
if (((Boolean) table.getValueAt(i, 1)).booleanValue()) {
String jobName = (((DefaultTableModel) table.getModel()).getValueAt(i, 0).toString());
You are using the i variable to denote view row indices, since you are checking values in this statement: table.getValueAt(i, 1) != null.
But then a bit further you are using i to index the model:
String jobName = ((DefaultTableModel) table.getModel()).getValueAt(i, 0).toString();
If i is to be a view index, you need to convert it to a model index before indexing the model:
String jobName = ((DefaultTableModel) table.getModel()).getValueAt(table.convertRowIndexToModel(i), 0).toString();
Also, when columns would be switched around in the view (ie on screen in your GUI), the following will probably not work as intended:
table.getValueAt(i, 1) != null
You most likely mean to say, get the second column value in the model, not the view. Best rewrite then as
table.getValueAt(i, table.convertColumnIndexToView(1)) != null
I am looking to get the value of the selected row in an AbstractTableModel and I am noticing some things. It is correctly reporting what sell (row) I am on, when it is selected, but as soon as I click my button to remove, the selected row value goes to 0. Resulting in the 0 row always being removed. I want to get the value int selectedRow and use it to remove it from the table and my ArrayLists.
ListSelectionModel rsm = table.getSelectionModel();
ListSelectionModel csm = table.getColumnModel().getSelectionModel();
csm.addListSelectionListener(new SelectionDebugger(columnCounter,csm));
columnCounter = new JLabel("(Selected Column Indices Go Here)");
columnCounter.setBounds(133, 62, 214, 14);
csm.addListSelectionListener(new SelectionDebugger(columnCounter,csm));
contentPane1.add(columnCounter);
rowCounter = new JLabel("(Selected Column Indices Go Here)");
rowCounter.setBounds(133, 36, 214, 14);
rsm.addListSelectionListener(new SelectionDebugger(rowCounter, rsm));
contentPane1.add(rowCounter);
SelectionDebugger:
public class SelectionDebugger implements ListSelectionListener {
JLabel debugger;
ListSelectionModel model;
public SelectionDebugger(JLabel target, ListSelectionModel lsm) {
debugger = target;
model = lsm;
}
public void valueChanged(ListSelectionEvent lse) {
if (!lse.getValueIsAdjusting()) {
// skip all the intermediate events . . .
StringBuffer buf = new StringBuffer();
int[] selection = getSelectedIndices(model.getMinSelectionIndex(),
model.getMaxSelectionIndex());
if (selection.length == 0) {
buf.append("none");
//selectedRow = buf.toString();
}
else {
for (int i = 0; i < selection.length -1; i++) {
buf.append(selection[i]);
buf.append(", ");
}
buf.append(selection[selection.length - 1]);
}
debugger.setText(buf.toString());
System.out.println("CampaignConfiguration: Selected Row: " + selection[selection.length - 1]);
// Set the selected row for removal;
selectedRow = selection[selection.length - 1];
}
}
// This method returns an array of selected indices. It's guaranteed to
// return a nonnull value.
protected int[] getSelectedIndices(int start, int stop) {
if ((start == -1) || (stop == -1)) {
// no selection, so return an empty array
return new int[0];
}
int guesses[] = new int[stop - start + 1];
int index = 0;
// manually walk through these . . .
for (int i = start; i <= stop; i++) {
if (model.isSelectedIndex(i)) {
guesses[index++] = i;
}
}
// ok, pare down the guess array to the real thing
int realthing[] = new int[index];
System.arraycopy(guesses, 0, realthing, 0, index);
return realthing;
}
}
}
The TableModel has nothing to do with selection. The View(JTable) is responsible for the selection.
I want to get the value int selectedRow and use it to remove it from the table and my ArrayLists.
You should NOT have separate ArrayLists. The data should only be contained in the TableModel.
If you want to delete a row from the table (and the TableModel) then you can use the getSelectedIndex() method of the table in your ActionListener added to the "Delete" button. Something like:
int row = table.getSelectedIndex();
if (row != -1)
{
int modelRow = table.convertRowIndexToModel( row );
tableModel.removeRow( modelRow );
}
If you are not using the DefaultTableModel, then your custom TableModel will need to implement the "removeRow(...)" method.
I was wondering if it's possible to grey out or render some rows in my JTable to be invisible using the data from my data base?
These are the columns in my JTable:
public DutyModel(ArrayList<Duty> listOfObjects) {
rowCount = listOfObjects.size();
colCount = columnNames.length;
data = new Object[rowCount][colCount];
for (int i = 0; i < rowCount; i++) {
/* Copy an ArrayList element to an instance of MyObject */
Duty d1 = (Duty) (listOfObjects.get(i));
data[i][0] = d1.getDutyId();
data[i][1] = d1.getDutyName();
data[i][2] = d1.getDutyDesc();
data[i][3] = d1.getDutySectorName();
data[i][4] = d1.getDutyStatus();
}
}
When my table is displayed, I want the rows with d1.getDutyStatus() where dutyStatus = "Inactive" to be greyed out. My table can currently be updated to either "Active" (By pressing an update button), or "Inactive" (By pressing a remove button). I don't want the user to be able to edit any of the duties that have the dutyStatus of "Inactive". Any assistance or help is greatly appreciated. Thanks!
The below code is what happens when the user selects a row in the JTable and presses the "Update" and "Delete" button. Also, I'm trying to use a 3 tier architecture to run my codes, my controller class is RetrieveDutyControl and my entity is Duty.
public void actionPerformed(ActionEvent e) {
int rowSelected = tblDutyList.getSelectedRow();
if (rowSelected >= 0) {
String idDuty = tblDutyList.getValueAt(rowSelected, 0)
.toString();
String name = tblDutyList.getValueAt(rowSelected, 1)
.toString();
String desc = tblDutyList.getValueAt(rowSelected, 2)
.toString();
String sector = tblDutyList.getValueAt(rowSelected, 3)
.toString();
String status = tblDutyList.getValueAt(rowSelected, 4)
.toString();
Duty duty = new Duty(Integer.parseInt(idDuty), name, desc,
sector, status);
RetrieveDutyControl rdc = new RetrieveDutyControl();
ArrayList<Duty> dutyList = rdc.processRetrieveDuties(duty);
JPanel contentPane = new RemoveDutyForm(myFrame, duty);
myFrame.getContentPane().removeAll();
myFrame.setContentPane(contentPane);
myFrame.setVisible(true);
} else {
JOptionPane.showMessageDialog(null, "No Record Selected",
"Alert", JOptionPane.ERROR_MESSAGE);
}
Try with overridden prepareRenderer() method to gray out the row based on data
Sample code: (use first column's value to validate)
Object[] columnNames = { "A", "B", "C", "D" };
Object[][] data = {
{ "abc", new Double(850.503), 53, true },
{ "lmn", new Double(36.23254), 6, false },
{ "pqr", new Double(8.3), 7, false },
{ "xyz", new Double(246.0943), 23, true } };
JTable table = new JTable(data, columnNames) {
#Override
public java.awt.Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
java.awt.Component comp = super.prepareRenderer(renderer, row, col);
Object value = getModel().getValueAt(row, 0);
if (value.equals("lmn")) {
comp.setBackground(Color.lightGray);
} else {
comp.setBackground(Color.white);
}
return comp;
}
};
For buttons check for value and do nothing.
How to get the value of the selected row?
if(table.getSelectedRow()!=-1){
int rowIndex=table.getSelectedRow();
Object value=table.getModel().getValueAt(rowIndex, 0);
if(value.equals("lmn")){
//do nothing
}else{
// perform desired operation
}
}
How can I calculate sum of price column in jTable and put sum of them at the end of the jTable. Can you give me a sample code?
public class IncomeReport extends JFrame {
private AccountFacade service = new AccountFacade();
void init() {
String[] columnNames = {"مبلغ", "محل درآمد ", "منبع"};
List list = service.incomeReportFacade();
Object[][] model = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
model[i] = (Object[]) list.get(i);
}
JTable table = new JTable(model, columnNames) {
DefaultTableCellRenderer renderRight = new DefaultTableCellRenderer();
{
// initializer block
renderRight.setHorizontalAlignment(SwingConstants.RIGHT);
}
#Override
public TableCellRenderer getCellRenderer(int arg0, int arg1) {
return renderRight;
}
};
Try something like this. Get the model, and use the DefaultTableModel#getValueAt() method.
Jtable table = new Jtable();
DefaultTableModel model = (DefaultTableModel)table.getModel();
double total = 0;
int column = 2; // example
for (int i = 0; i < model.getRowCount(); i++){
total += model.getValueAt(i, column); // getValueAt(row, column)
}
Object[] row = {"", "", total};
model.addRow(row);
If you need a total that is dynamically kept up to date then you will need to either override your TableModel to provide the sum for the final row, or will need to listener for changes to the model and update the last row with the sum.
Customizing your own TableModel would also allow you the ability to make your summary row uneditable so while this might be more work, it provides much more flexibility.
I have a table and and I use the DefaultTableModel. I implemenmted a TableListener to make sure that there are no empty values in the first column and remove duplicates. Additionally I add an empty row as the last line in the table, so when a user enters a non-existing value there it will be added to the row.
Now I wanted to keep the columns sorted and added a TableRowSorter to my model. But now the problem is that the empty row gets sorted as well. I implemented a Comparator because I thought I could override this by checking for the empty column, but that doesn't work, because I don't know in which direction the sorter currently orders.
Is there a way to do this (Have an empty row as last line always)? Can I get the sorting order somehow? Or do I have to implement a complete model just for this?
I found a solution. Here is the complete class for reference.
public class EnvironmentPanel
extends JPanel
implements Comparator<String>
{
private static final long serialVersionUID = 1L;
private static final String[] mHeader =
{
"Name",
"Value",
};
private JTable mEnvironmentTable = null;
private DefaultTableModel mTableModel = null;
private int mSortOrder = 1;
public EnvironmentPanel()
{
initialize();
}
private void initialize()
{
GridBagLayout gridBagLayout = new GridBagLayout();
setLayout(gridBagLayout);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
gbc_scrollPane.insets = new Insets(3, 3, 3, 3);
gbc_scrollPane.weighty = 1.0;
gbc_scrollPane.weightx = 1.0;
gbc_scrollPane.fill = GridBagConstraints.BOTH;
gbc_scrollPane.anchor = GridBagConstraints.NORTHWEST;
gbc_scrollPane.gridx = 0;
gbc_scrollPane.gridy = 0;
add(scrollPane, gbc_scrollPane);
scrollPane.setViewportView(getMEnvironmentTable());
}
private JTable getMEnvironmentTable()
{
if(mEnvironmentTable == null)
{
mEnvironmentTable = new JTable();
mEnvironmentTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
mTableModel = new DefaultTableModel();
mEnvironmentTable.setModel(mTableModel);
for(int i = 0; i < mHeader.length; i++)
mTableModel.addColumn(mHeader[i]);
Object[] row = new Object[mHeader.length];
row[0] = "";
mTableModel.addRow(row);
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>();
mEnvironmentTable.setRowSorter(sorter);
sorter.setModel(mTableModel);
sorter.setComparator(0, this);
sorter.setSortsOnUpdates(true);
sorter.addRowSorterListener(new RowSorterListener()
{
#Override
public void sorterChanged(RowSorterEvent oEvent)
{
if(oEvent.getType().equals(Type.SORT_ORDER_CHANGED))
mSortOrder *= (-1);
}
});
mTableModel.addTableModelListener(new TableModelListener()
{
public void tableChanged(TableModelEvent oEvent)
{
onTableChanged(oEvent);
}
});
}
return mEnvironmentTable;
}
/**
* The table will always have an empty line at the end. If a new name is entered
* the value is taken and a new line will be added.
* Entries with an empty name column will be removed.
*
* The name must be unique.
*
* #param oEvent
*/
private void onTableChanged(TableModelEvent oEvent)
{
String s = null;
Map<String, Integer>nmap = new HashMap<String, Integer>();
for(int i = mTableModel.getRowCount()-2; i >= 0; i--)
{
s = (String)mTableModel.getValueAt(i, 0);
if(s == null || s.equals(""))
{
mTableModel.removeRow(i);
continue;
}
// If we found an entry with the same name, we remove the one
// that is later in the list.
if(nmap.containsKey(s))
{
int pos = nmap.get(s);
mTableModel.removeRow(pos);
}
// Add the latest row to the map.
nmap.put(s, i);
}
int n = mTableModel.getRowCount();
if(n > 0)
{
s = (String)mTableModel.getValueAt(n-1, 0);
if(s != null && s.equals("") == false)
{
Object[] row = new Object[mHeader.length];
row[0] = "";
mTableModel.addRow(row);
}
else
{
s = (String)mTableModel.getValueAt(n-1, 1);
if(s != null && s.equals("") == false)
mTableModel.setValueAt(null, n-1, 1);
}
}
}
#Override
public int compare(String oLeft, String oRight)
{
if(oLeft.equals(""))
return -1*mSortOrder;
if(oRight.equals(""))
return 1*mSortOrder;
return oLeft.compareTo(oRight);
}
}