How to prevent duplicate entries in JTable?
I want to stop enter duplicate data in table. I tried given below cord. But it is not working. My first column name is item id. So I used jtable.getValueAt(i, 1). It that wrong.
public void lordTable(JTable jtable, JTextField txtItemID, JTextField txtName, JTextField txtQty, JTextField txtUp) {
String s = "";
boolean exists = false;
for (int i = 0; i < jtable.getRowCount(); i++) {
s = jtable.getValueAt(i, 1).toString().trim();
if (txtItemID.getText().equals("")) {
JOptionPane.showMessageDialog(null, "Enter Invoice Details First");
} else {
if (txtItemID.getText().equals(s)) {
exists = true;
break;
}
}
}
if (!exists) {
DefaultTableModel dd = (DefaultTableModel) jtable.getModel();
Vector v = new Vector();
v.add(txtItemID.getText());
v.add(txtName.getText());
v.add(txtQty.getText());
v.add(txtUp.getText());
Double val = (Double.parseDouble(txtUp.getText())) * (Double.parseDouble(txtQty.getText()));
v.add(val);
dd.addRow(v);
} else {
JOptionPane.showMessageDialog(null, "data already exist.");
}
}
Access first column in a table with zero, that is: getValueAt(row, 0).
Related
I use:
Java 10 SE
Java Swing
Eclipse IDE
I have JTable, the contents gets loaded at runtime dynamically. It has some JComboBoxes. If I select the JComboBox, and then attempt to reload the table, the JComboBox appears visible at the time when the table loading is in progress.
Besides that, if the JComboBox's contents gets updated (elsewhere in different table, when the combo supposed to reflect that new contents), that new contents does not get visible staright away after loading the JTable dynamically.
The snap-shot sample of the app:
That's, the table being loaded at runtime up, and in the middle you have vsisble JComboBox persistent from the previous selection.
How to:
Get rid off that persistent JComboBox
Make the data visible instantly, upon update under the combo, once you load the table dynamically
I have the public final class TableColumnEditor extends DefaultCellEditor{
which returns the JComboBox on a specific column:
else if(row == ROW_2_DEVS_WORK_WEEKEND) {
ProjectMetrics metrics = new ProjectMetrics();
JComboBox<String> combo = new JComboBox<>();
combo.setBackground(Color.WHITE);
for(String devs : metrics.identifyDevsThatWorkAtWeekend()) {
combo.addItem(devs);
}
return combo;
}
I have the public final class TableColumnRenderer extends DefaultTableCellRenderer{
which makes sure that the view displays the JComboBox under that specific column:
else if(row == ROW_2_DEVS_WORK_WEEKEND) {
ProjectMetrics metrics = new ProjectMetrics();
JComboBox<String> combo = new JComboBox<>();
combo.setBackground(Color.WHITE);
for(String devs : metrics.identifyDevsThatWorkAtWeekend()) {
combo.addItem(devs);
break;
}
return combo;
}
The table gets loaded dynamically right here (non-essential things removed):
public static void reloadTableDynamically(JTable metricsTable){
DefaultTableModel model = (DefaultTableModel)metricsTable.getModel();
if(projectData.isEmpty()) {
metricsTable.clearSelection();
int rowCount = model.getRowCount();
for(int item = (rowCount - 1); item >= 0; item--) {
model.removeRow(item);//clears previous rows
}
metricsTable.repaint();
return;
}
model.getDataVector().clear();
int rowCount = constantRows + ((devsTask.size() == 0) ? 1 : devsTask.size());
try {
new Thread(()-> {
int lastRowID = 0;
int devsTaskID = 0;
for(int item = 0; item < rowCount; item++) {
Object[] input = null;
if(item == 0) {
input = new Object[] {"", metrics.getProjectDateRange(), "" };
}//similar branches removed
else {
devsTaskID++;
input = new Object[] {"", devsTask.get(devsTaskID).getDeveloper(), ""};
}
model.addRow(input);
metricsTable.scrollRectToVisible(new java.awt.Rectangle(metricsTable.getCellRect(lastRowID++, 0, true)));
metricsTable.repaint();
try {
Thread.sleep(Config.getInstance().getReloadInOutTable());
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
metricsTable.scrollRectToVisible(new java.awt.Rectangle(metricsTable.getCellRect(projectData.size() - 1, 0, true)));
metricsTable.repaint();//so that to reach the last row
}).start();
}
catch(Exception e) {
}
}
What do you think?
Well, I figured out how to overcome this problem.
Firstly, the JComboBox gets updated on EDT(Event Despatch Thread).
/**
* #param combo The JComboBox ref.
* #param toDisplay The value to add to it
*/
public static void updateComboBoxOnEventDespatchThread(JComboBox<String> combo, String toDisplay) {
Runnable doComboUpdate = new Runnable() {
public void run() {
combo.addItem(toDisplay);
}
};
SwingUtilities.invokeLater(doComboUpdate);
}
Under the JTable column editor:
else if(row == ROW_2_DEVS_WORK_WEEKEND) {
ProjectMetrics metrics = new ProjectMetrics();
JComboBox<String> combo = new JComboBox<>();
combo.setBackground(Color.WHITE);
Runnable doComboInsert = new Runnable() {
public void run() {
int id = 0;
for(String devs : metrics.identifyDevsThatWorkAtWeekend()) {
UIutils.updateComboBoxOnEventDespatchThread(combo, "("+ ++id +") " + devs);
}
}
};
SwingUtilities.invokeLater(doComboInsert);
return combo;
}
But the main fix, without which both issues do not go away, is following.
That is, I noticed that in order for data to appear under the table instantly, firstly, you need to select any other unrelated table's cell.
That is, the Java thread, which loads the JTable at runtime, does need to have this:
if(model.getRowCount() > 0) {
metricsTable.selectAll();
}
That's probably a hack, but it works for me!
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
String dishName = "";
ArrayList<Integer> st = new ArrayList<Integer>();
int rowCount = table.getRowCount();
int fPrice;
int rowIndex = 0;
int colIndex = 4;
boolean emptyFlag = false;
do {
String price = (String) table.getValueAt(rowIndex, 4);
fPrice = Integer.parseInt(price);
if (price != null && price.length() != 0) {
st.add(fPrice);
rowIndex++;
} else {
emptyFlag = true;
}
} while (rowIndex < rowCount && !emptyFlag);
Collections.sort(st);
int key = Integer.parseInt(searchPrice.getText());
int low = 0;
int high = st.size() - 1;
int searchResult = MenuInfo.priceSearch(st, low, high, key);
if(searchResult==-1){
JOptionPane.showMessageDialog(this, "Could not find the dish of your price!");}
else{
dishName = (String) table.getValueAt(searchResult,1);
JOptionPane.showMessageDialog(this, "The price you have searched can afford " + dishName);
}
} //ends here
The above code is the code I have tried in my program. But it can display the corresponding dishName only if the data are sorted previously. If I add dish of lower price, then it displays the dishname of first row. Please do appreciate my request :)
Here is the image of my jtable
I wrote some code that may help. It looks like you're using Swing, so I used Swing. My code will find the corresponding value, but not sort the rows. I'll share it, but if you really need it to be sorted, let me know.
public static void main(String[] args) {
String[] headers = {"Name","Number"};
String[][] rowData = {{"foo","500"},{"bar","700"}};
JFrame frame = new JFrame();
JPanel panel = new JPanel();
//frame.add(panel);
//A table is controlled by its model, so we need a variable to access the model
DefaultTableModel model = new DefaultTableModel(rowData,headers);
JTable table = new JTable(model);
JScrollPane scroll = new JScrollPane(table);
//To allow sorting, we us a TableRowSorter object
TableRowSorter<TableModel> sorter = new TableRowSorter<>(table.getModel());
table.setRowSorter(sorter);
//We have to set the 2nd column to be sortable
ArrayList<RowSorter.SortKey> sortKeys = new ArrayList<>();
//sorting on 2nd column (with index of 1), which is Number
sortKeys.add(new RowSorter.SortKey(1, SortOrder.ASCENDING));
sorter.setSortKeys(sortKeys);
sorter.sort();
//add new value, then sort
Object[] newRow = {"baz", "600"};
model.addRow(newRow);
sorter.sort();
panel.add(scroll);
frame.add(panel);
frame.setSize(800, 400);
//show is deprecrated.. I shouldn't be using it!
frame.show();
int minIndex = findMin(table, 1);
//use the row index of the min item in column 1 to get the corresponding value in column 0
System.out.println("Minimum String: " + table.getValueAt(minIndex, 0));
}
//find min value in the column with index tableColumnIndex and return the row index of that item
public static int findMin(JTable table, int tableColumnIndex) {
int minIndex = 0;
String min = table.getValueAt(0, tableColumnIndex).toString();
for (int i = 1; i < table.getRowCount(); i++) {
if (table.getValueAt(i, tableColumnIndex).toString().compareTo(min) < 0) {
min = table.getValueAt(i, tableColumnIndex).toString();
minIndex = i;
}
}
return minIndex;
}
So I have a function that populates JTable from my database.
I have here
public static TableModel resultSetToTableModel(ResultSet rs) {
try {
ResultSetMetaData metaData = rs.getMetaData();
int numberOfColumns = metaData.getColumnCount();
Vector<String> columnNames = new Vector<String>();
// Get the column names
for (int column = 0; column < numberOfColumns; column++) {
columnNames.addElement(metaData.getColumnLabel(column + 1));
}
// Get all rows.
Vector<Vector<Object>> rows = new Vector<Vector<Object>>();
while (rs.next()) {
Vector<Object> newRow = new Vector<Object>();
for (int i = 1; i <= numberOfColumns; i++) {
if(isObjectInteger(rs.getObject(i)) && i>1) //checks if the value is Integer else not and is past the first column
{
System.out.println(i+"="+rs.getObject(i));
String label = columnNames.get(i); //THE ERROR IS ON THIS PART
newRow.addElement(getValue((Integer) rs.getObject(i),label)); //gets the value of specific foreign key id from another table
}
else
{
System.out.println(i+"="+rs.getObject(i));
newRow.addElement(rs.getObject(i));
} //inside row (new Rows)
}
rows.addElement(newRow); //outside row
}
return new DefaultTableModel(rows, columnNames)
{
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
I have total 8 columns in my database the output of that System.out.println is:
The one's that get's inside the else:
1=1
2=test
3=A.
4=test
5=test
6=test
The one's that get's inside the if
7=1
8=23
As you can see the output is right but it always throws Array index out of range: 8 error on the String label = columnNames.get(i);
While ResultSet.getObject() requires an argument based on one, columnNames is a vector, with its indexes based on zero.
Hence valid values for it would be 0..7, not 1..8. In other words, the first part of your if statement should be:
System.out.println(i + "=" + rs.getObject(i));
String label = columnNames.get(i-1); // NOT "i".
I've been struggling for hours with this method which has a strange behavior.
Scenario: two jlists, menuList and productList filled with data from a mysql db, the first contains the "categories" and the second the products of that category. Both of them are populated with a Vector of objects. The problem is when I perform a search of a products it works fine in all circumstances except immediately after I save a new menu (category). In this case, the index of the menuList is successfully moved to the right category in which the products I was searching is in, but productList remains blank.
This is the code of the method which makes the search.
private void bFindProductActionPerformed(java.awt.event.ActionEvent evt) {
Product product = new Product();
product.setProductName(searchedProduct.getText());
bNewProduct.setEnabled(false);
Vector<Product> productVoices = DBConnection.searchProduct(product);
if (!productVoices.isEmpty()) {
modelProductList.clear();
disableProductButtons();
menuName.setText("");
productName.setText("");
int idMenu = 0;
for (int i = 0; i < productVoices.size(); i++) {
Product current = (Product) productVoices.get(i);
modelProductList.addElement(current);
idMenu = current.getMenuId();
}
productList.setModel(modelProductList);
for (int i = 0; i < modelMenuList.getSize(); i++) {
Menu current = (Menu) modelMenuList.getElementAt(i);
if (idMenu == current.getMenuId()) {
int currentId = modelMenuList.indexOf(current);
menuList.setSelectedIndex(currentId);
menuList.requestFocus();
}
}
} else {
JOptionPane.showMessageDialog(null, "No product found", "", JOptionPane.WARNING_MESSAGE);
searchedProduct.setText("Search...");
}
}
And this is the code of the methos which saves a new menu (or updates an existing one):
private void bSaveMenuActionPerformed(java.awt.event.ActionEvent evt) {
//If there's a selected menu updates
if (!menuList.isSelectionEmpty()) {
Menu selectedMenu = (Menu) menuList.getSelectedValue();
listIndex = menuList.getSelectedIndex();
selectedMenu.setMenuName(menuName.getText());
int result = DBConnection.updateMenu(selectedMenu);
if (result == 1) {
reloadMenuList(); //this re-fill the menuList
menuList.setSelectedIndex(listIndex);
menuList.setEnabled(true);
bFindProduct.setEnabled(true);
bNewMenu.setEnabled(true);
bNewProduct.setEnabled(false);
}
} else { //If there isn't a selected menu, creates a new menu
Menu newMenu = new Menu();
newMenu.setMenuName(menuName.getText());
int result = DBConnection.insertMenu(newMenu);
if (result == 1) {
reloadMenuList();
newMenuIsSaved = true;
menuList.setEnabled(true);
bFindProduct.setEnabled(true);
}
}
}
Thank you.
I using detaful table model
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
and I row count
int Row = model.getRowCount();
Here is which I add row and wish to diplay error when adding same items.
if (Row > 0) {
for(i=0;i<Row; i++){
if(jTable1.getValueAt(i,0).equals(name.getText())){
JOptionPane.showMessageDialog(null, "Can't add same item");
}
}
}else if (Row <99) {
model.addRow(new Object[] {name.getText(),address.getText(),Integer.parseInt(age.getText())});
}
I guess wrong at if else statement?
Because I can add the 1st row and I can't add for 2nd row.
Thanks for help
Not sure what you have in your other variables, but I guess you have a discrepancy between product_id and name, perhaps?
Wouldn't it be more like
if(jTable1.getValueAt(i,0).equals(name.getText())){
UPDATE:
Try rewriting it like this:
int Row = model.getRowCount();
int boolean exists = false;
for(i=0;i<Row; i++){
if(jTable1.getValueAt(i,0).equals(name.getText())){
JOptionPane.showMessageDialog(null, "Can't add same item");
exists = true;
break;
}
}
if (!exists && Row < 99) {
model.addRow(new Object[] {name.getText(),address.getText(),Integer.parseInt(age.getText())});
}