TableModel, causing duplicate Database Info in a Java JFrame - java

I have this method setup in a JFrame to be called when the user presses a button to "Load File"; however, when the user presses the button a second time . . . they get another table underneath the first table so all the information gets duplicated and it expands beyond my "non-resizable" frame.
How can I get it to only load the one table no matter how many times the user presses the button?
JButton btnLoad = new JButton("Load File")
private void GetAction()
{
ActionHandler handler = new ActionHandler();
btnLoad.addActionListener(handler);
}
private class ActionHandler implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
String incmd = evt.getActionCommand();
if (incmd.equals("Load File")) // If Load File button is pressed
DatabaseLoad();
else if (incmd.equals("Exit")) // If Exit button is pressed
System.exit(0);
}
}
private void DatabaseLoad()
{
try
{
// The driver allows you to query the database with Java
// forName dynamically loads the class for you
Class.forName("com.mysql.jdbc.Driver");
// DriverManager is used to handle a set of JDBC drivers
// getConnection establishes a connection to the database
// You must also pass the userid and password for the database
String url = "jdbc:mysql://localhost:3306/charity";
conn = DriverManager.getConnection (url,"root","password");
// Statement objects executes a SQL query
// createStatement returns a Statement object
Statement sqlState = conn.createStatement();
// This is the query I'm sending to the database
String selectStuff = "SELECT `name`, `charity`, `amount` FROM `charity`.`donations` ";
// A ResultSet contains a table of data representing the
// results of the query. It can not be changed and can
// only be read in one direction
rows = sqlState.executeQuery(selectStuff);
// Temporarily holds the row results
Object[] tempRow;
// next is used to iterate through the results of a query
while(rows.next()){
// Gets the column values based on class type expected
tempRow = new Object[]{rows.getString(1), rows.getString(2), rows.getDouble(3) };
// Adds the row of data to the end of the model
dTableModel.addRow(tempRow);
}
// Successfully loaded, message the user
message1.setText("<html><font color='red'>Database Info Loaded</font>");
message2.setText("");
}
catch (SQLException ex)
{
// String describing the error
System.out.println("SQLException: " + ex.getMessage());
// Vendor specific error code
System.out.println("VendorError: " + ex.getErrorCode());
}
catch (ClassNotFoundException e)
{
// Executes if the driver can't be found
System.out.println("Driver Cannot be found");
e.printStackTrace();
}
// Create a JTable using the custom DefaultTableModel
JTable table = new JTable(dTableModel);
// Increase the font size for the cells in the table
table.setFont(new Font("Serif", Font.PLAIN, 16));
// Increase the size of the cells to allow for bigger fonts
table.setRowHeight(table.getRowHeight()+5);
// Allows the user to sort the data
table.setAutoCreateRowSorter(true);
// right justify amount column
TableColumn tc = table.getColumn("amount");
RightTableCellRenderer rightRenderer = new RightTableCellRenderer();
tc.setCellRenderer(rightRenderer);
// Disable auto resizing
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// Set the width for the columns
TableColumn col1 = table.getColumnModel().getColumn(0);
col1.setPreferredWidth(200);
TableColumn col2 = table.getColumnModel().getColumn(1);
col2.setPreferredWidth(275);
TableColumn col3 = table.getColumnModel().getColumn(2);
col3.setPreferredWidth(75);
// Put the table in a scrollpane and add scrollpane to the frame
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setPreferredSize(new Dimension(552, 400));
this.add(scrollPane, BorderLayout.CENTER);
}
// To change justification to the right
class RightTableCellRenderer extends DefaultTableCellRenderer {
public RightTableCellRenderer() {
setHorizontalAlignment(JLabel.RIGHT);
}
}

How can I get it to only load the one table no matter how many times the user presses the button?
The table and scrollpane should only be created once when you build the GUI components. Then when you want to change the data you just change the model of the existing table:
table.setModel( updatedModel );

Related

Items in combobox reduced after adding actionPerformed

I want to update my table right after clicking on a diffrent item in combobox. After adding actionPerformed combobox shows only the first item and the arrow doesn't work. I'm updating my table after selecting a diffrent item and clicking a button. Action perform in a button does work. Am I using the actionPerformed incorrectly?
Here is a code how I add items to a combobox.
private void fillComboBox() {
try {
DatabaseMetaData meta = (DatabaseMetaData) conn.getMetaData();
rs = meta.getTables("db", null, null, new String[] {
"TABLE"
});
while (rs.next()) {
ComboBox.addItem(rs.getString("TABLE_NAME"));
}
} catch(Exception e) {
JOptionPane.showMessageDialog(null,e);
}
}
Here is how I fill the table.
private void fillTable()
{
String selectedValue = ComboBox.getSelectedItem().toString();
String sql = "Select * from "+selectedValue;
Statement stmt;
try {
stmt = conn.createStatement(rs.TYPE_SCROLL_INSENSITIVE,rs.CONCUR_UPDATABLE);
rs = stmt.executeQuery(sql);
Table.setModel(DbUtils.resultSetToTableModel(rs));
} catch (SQLException ex) {
Logger.getLogger(Welcome.class.getName()).log(Level.SEVERE, null, ex);
}
}
And after clicking a button, I update the table
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
fillTable();
}
Works fine, but I would like to update the table right after clicking on a new item in combobox.
Edit: I fixed it by adding fillComboBox() after fillTable(). But now I have two first items in combobox even after removeAll(). How do I fix it?
public Welcome() {
initComponents();
conn = MySqlConnect.ConnectDB();
fillComboBox();
fillTable();
ComboBox.removeAll();
fillComboBox();
repaint();
}
I always change contents of a ComboBox dynamically by using the underlying Model, not through the actual ComboBox. After your GUI is already shown, I think this matters ... using the model, not the JComboBox itself.
...
final var model = new DefaultComboBoxModel<String>();
while (rs.next()) {
model.addElement(rs.getString("TABLE_NAME"));
}
...
ComboBox.setModel(model);

Garbage value in jtable after adding row dynamically

I have JTable which has few columns.In that I have JComboBox. At program start I want them to be empty.I have one JButton on click action of button i have the code to add row dynamically in table.
But after adding the row i get garbage value in the cell having JComboBox. As shown in below figure :
And here is the code :
Code to add JComboBox in table
// Create columns names
String columnNames[] = { "Item", "Sun Item", "Required Quantity","Price","Gross Amount" };
// Create some data
final String dataValues[][] =
{
{ "", "", "","","", },
};
tableModel = new DefaultTableModel(dataValues, columnNames);
// Create a new table instance
table = new JTable( tableModel );
updateItemCombo();
TableColumn itemColumn = table.getColumnModel().getColumn(0);
itemColumn.setCellEditor(new DefaultCellEditor(comboItem));
public void updateItemCombo(){
Vector<String> s = new Vector<String>();
try{
setConnectin();
String str = "select * from ItemTable";
stmt = conn.createStatement();
rs = stmt.executeQuery(str);
while(rs.next())
{
String nm = rs.getString("Item_Name");
s.add(nm);
}
conn.close();
}catch(Exception e2){
e2.printStackTrace();
}
DefaultComboBoxModel<String> modelData = new DefaultComboBoxModel<String>(s);
comboItem.setModel(modelData);
}
Code to add row dynamically on button click :
btnAddOrder.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
tableModel.addRow(dataValues);
tableModel.fireTableDataChanged();
}
});
What should i do to remove this garbage value from table? Please help
The addRow(...) method takes a 1-Dimensional array as a parameter. You are attempting to add a 2-Dimensional array.
Also, do not use:
tableModel.fireTableDataChanged();
it is the job of the TableModel to invoke the appropriate fireXXX() method, which by the way in this case would be fireTableRowsInserted(...).

add new row to JTable from a Different class

I want to add data to a JTable which is situated on a JTabbedpane. Data which I want to insert in JTable is a user input data(TextField) from a different class named (addcontact). cntctus is the tab in which Jtable is situated. it contains a method to insert a new row to JTable.
when I am giving values to tname textfield(user Input) a nullpointerexception occurs on the line :-
//contctus.addData(new Object[]{,,,}
my problem is similar to this, Applied all the solutions mentioned. but still getting nullpointerexception
Data from JTextField to JTable
but in my case, the class for input data is different.
I am providing image for contctus tab. ![.][1]
this is the cntctus class:-
public class cntctus extends JPanel{
JPanel p,tablepanel;
JLabel labelpic;
static JTable table;
int j,i,k=0;
String column[];
Object [][]row;
private static DefaultTableModel model;
public cntctus()
{
String column[]= { "Name","Position","Phone"};
Object [][]row = {{"Prof. g", "Director", "+123456"},
{"Mr. Suir singh", "Assistant Professor", "+9123568989"},
{"Ms. sa", "BI teacher","9468645"},
{"bhbnjk ","nj","k780"},
{"nb","hbj","9798679"}
};
model=new DefaultTableModel(row,column);
labelpic =new JLabel(new ImageIcon("D:\\Workspace\\nikhil\\bin\\Resources\\cont.png"));
table = new JTable(row,column);
TableColumn colum = null;
table.setFont(new Font("Comic Sans MS",15,13));
TableModel tm = table.getModel();
.
.
.
}
//and here is the method for adding new row
public static void addData(Object[] data) {
//String nextrow=Integer.toString(model.getRowCount());
model.addRow(data);
}
I am invoking this method from addcontact class. JTable contains three columns.
now dynamically i want to add more contacts in my JTable with the help of addcontact class.
when i'll be clicking on submit button i wish to put all the three details in Jtable.
a part of Code for addcontact class is :-
public void actionPerformed(ActionEvent aes) {
Object src=aes.getSource();
if(src==submit){
if(tname.getText().equals("")){
JOptionPane.showMessageDialog(null, "Please fill contact name!!");
}
else
{
cntctus.addData( new Object[]{tname.getText(), tpos.getText(), tnum.getText()});
//validate();
}
if(tpos.getText().equals("")){
JOptionPane.showMessageDialog(null, "Please fill contact details!!");
}
if(tnum.getText().equals("")){
JOptionPane.showMessageDialog(null, "Please fill contact number!!");
}
}

Remove JTable row that read file records

I am New in java, I have a JTable that can read records from a txt file and show they perfectly.
I want to add a new book to my JFrame that when user select a row on table and clicked the "delete" button, that row should delete and that deleted row records must delete from txt file,too.
my code is this, but it has errors and not seen JTable! :
public class CopyOfAllUserTable extends AbstractTableModel {
Vector data;
Vector column;
public static void main(String[] args){
new CopyOfAllUserTable();
}
public CopyOfAllUserTable() {
String line;
data = new Vector();
column = new Vector();
try {
FileInputStream fis = new FileInputStream("D:\\AllUserRecords.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
StringTokenizer st1 = new StringTokenizer(br.readLine(), " ");
while (st1.hasMoreTokens())
column.addElement(st1.nextToken());
while ((line = br.readLine()) != null) {
StringTokenizer st2 = new StringTokenizer(line, " ");
while (st2.hasMoreTokens())
data.addElement(st2.nextToken());
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
final JFrame frame1=new JFrame();
JTable table=new JTable(data,column);
JButton button1=new JButton("Delete");
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTableModel model=new DefaultTableModel(data, column);
JTable table=new JTable(model);
}
});
JPanel panel=new JPanel();
panel.add(table);
panel.add(button1);
frame1.add(panel);
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setBounds(200, 80, 600, 500);
frame1.setVisible(true);
frame1.setEnabled(true);
}
public int getRowCount() {
return data.size() / getColumnCount();
}
public int getColumnCount() {
return column.size();
}
public Object getValueAt(int rowIndex, int columnIndex) {
return (String) data.elementAt((rowIndex * getColumnCount())
+ columnIndex);
}
}
My problem is in delete row, and read records from file to jtable are perfectly successful.
Firstly you're not adding your JTable to the content of the frame.
For containers like: frame.getContentPane() and JPanel you should add the child components by using their #add(...) method.
For example:
final JPanel panel=new JPanel(new BorderLayout());
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTableModel model=new DefaultTableModel(data, column);
JTable table=new JTable(model);
panel.add(new JScrollPane(table));
panel.revalidate();
}
});
Note that JPanel default layout is FlowLayout. Second thing - if you want to have headers and scrolling in your JTable you need to wrap it with JScrollPane.
Next - you should revalidate the panel after adding/removing/etc.
The second issue is removing rows from JTable. I usually write a method to handle it:
protected void removeRows(final int[] rows) {
int modelRows[] = new int[rows.length];
for(int i = 0; i < rows.length; ++i) {
modelRows[i] = table.convertRowIndexToModel(rows[i]);
}
Arrays.sort(modelRows);
for(int i = modelRows.length - 1; i >= 0; --i) {
int row = modelRows[i];
model.removeRow(row);
}
model.fireTableDataChanged();
}
The convertRowIndexToModel method converts index returned by JTable#getSelectedRows() or JTable#getSelectedRow() (which are the visible indices) to the model indices. If you set RowSorter for your JTable or you leave it to standard implementation:
table.setAutoCreateRowSorter(true);
You are adding table directly to the panel with out using the JScrollPane. Your table header will not be visible if you do like this,
So instead of this,
JPanel panel=new JPanel();
panel.add(table);
Do this,
JPanel panel=new JPanel();
panel.add(new JScrollPane(table));
Why to use JScrollPane? Read this.
When user selects a row and clicks on delete, then get the selected row and remove it from the table list. As you are using AbstractTableModel then you have to write your custom removeRow(..) method to perform this.
Example:
private boolean removeSelectedRow(int row) {
// Remove the row from the list that the table is using.
dataList.remove(row);
// You need to call fireXXX method to refresh the table model.
fireTableDataChanged();
return true;
// If fail return false;
}
If delete is the action then first get the selected row and then call removeSelectedRow(int) like the following,
private void deleteRow() {
int selectedRow = table.getSelectedRow();
boolean deleteStatus = removeSelectedRow(selectedRow);
// Only if the deletion is success then delete from the file.
if(deleteStatus) {
// Delete it from the file too.
}
}
first you have to make sure that something has been selected: when there is something selected than enable the delete button. please look up the JTable java source code #
http://developer.classpath.org/doc/javax/swing/JTable-source.html
and the following code:
1331: /**
1332: * Receives notification when the row selection changes and fires
1333: * appropriate property change events.
1334: *
1335: * #param event the list selection event
1336: */
1337: public void valueChanged(ListSelectionEvent event)
1338: {
1339: firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
1340: Boolean.FALSE, Boolean.TRUE);
1341: int r = getSelectedRow();
1342: int c = getSelectedColumn();
1343: if (r != lastSelectedRow || c != lastSelectedColumn)
1344: {
1345: Accessible o = getAccessibleAt(lastSelectedRow,lastSelectedColumn);
1347: Accessible n = getAccessibleAt(r, c);
1348: firePropertyChange(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY, o, n);
1350: lastSelectedRow = r;
1351: lastSelectedColumn = c;
1352: }
1353: }
You need to register for the last event to be notified when the selected rows have been changed. Add your own listener to enable the deletebutton based on whether or not a row has been selected which is as you can see in the event itself.
Please use to start with the DefaultTableModel because it will work in 90% of the cases.
And any change is applied to the tabledatamodel which will automatically propogate to the JTable View: normally you never change the view because all selection and scroll information is lost which is something you don't want.
When the delete button is fired the approach is straight forward: there is a row selected, otherwise it is impossible to click it: remove that selected row number from the defaultTableModel, and last but not least I would write simply the entire contents of the datamodel model to the designated file because the table's model hold the actual rows that are indeed displayed in the View.
So please think in terms of models models and models: Views are instantiated only once, packed scrolled etc and than you leave them as is. Models are normally also never changed: you change the contents of the models by adding and or deleting rows. One other tip: use always renderers: those that don't don't, in my humble opinion, don't understand how to work with JTables.
And yes you can leave out the first part to listen for selection changes: sure and pop up a warning to indicate the problem. And in a later stage add the functionality that listens for selection changes to enable and or disable the JButton delete row.
Hope this helps.

show data from jTable in jFrame

I have jFrame2 which contains jTable with 4 columns (the jTable taking data from table in database which contain 20 columns)
Also I have jFrame1 which I have used it to fill database.
What I want to do that when I select row in jTable and click jButton, it must open jframe1 showing all data for that row.
i will clear what i want in points
*i want open jframe1 from jframe2 via jbutton(this task is done and this is the code)
public void actionPerformed(ActionEvent e) {
if(e.getSource()==jButton2){
jframe2 regFace =new jframe2();
regFace.setVisible(true);
}}
*once jframe1 opened by jbutton in jframe2 it must show in it fields all data of selected row in jframe2>>this point mean
........-sql query executed once jfram1 opened by Jbutton in jframe2
.........-showing data in jtextfield taking from database by query i mentioned in line above (this task is done and this is the code but not completed)
try {
dbconnect = new myDbConnection();
ResultSet resultSet =null;
resultSet = dbconnect.excuteQuery("SELECT id, area,location, status1 FROM pledges where id='17'");
while (resultSet.next()){
id.setText(resultSet.getString(1));
area.setText(resultSet.getString(2));
location.setText(resultSet.getString(3));
status.setText(resultSet.getString(4));
// i = Long.parseLong(rs1.getString(1));
}
*in brief i want understand jframe1 that please if you opened by jframe2 execute a query and fill text fields by that query
*this is picture would clear better
here
It sounds like the part you are having trouble with is how to get the selected data from the table into the fields in jframe1.
A lot of this depends on the TableModel that is used in your JTable. Assuming you just used a DefaultTableModel, you can get the selected row data like this:
#Override
public void actionPerformed(ActionEvent e) {
int viewRow = myJTable.getSelectedRow();
int modelRow = myJTable.convertRowIndexToModel(viewRow);
DefaultTableModel model = (DefaultTableModel) myJTable.getModel();
// You will get a compiler warning on the following line, but there's not much you can do about it beside suppress it
Vector<Object> rowVector = (Vector<Object>) model.getDataVector().get(modelRow);
jframe2 regFace =new jframe2();
regFace.setSelectedRow(rowVector);
regFace.setVisible(true);
}
And you would have the following method in your jframe2 class:
public void setSelectedRow(Vector<Object> row ) {
id.setText(row.get(0).toString());
area.setText(row.get(1).toString());
location.setText(row.get(2).toString());
status.setText(row.get(3).toString());
// continue for all columns
}
before i put the answer i would thank #wolfcastle such a nice person.He almost answer the question and i'm just modify it to adapt it with sql query and database.
this is the code for jfrme2
public void actionPerformed(ActionEvent e) {
if(e.getSource()==jButton2){
int viewRow = jTable1.getSelectedRow();
int modelRow = jTable1.convertRowIndexToModel(viewRow);
Object oc= jTable1.getModel().getValueAt(modelRow, 0);
String vv=oc.toString();
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
jframe1 regFace =new jframe1();
try {
regFace.setSelectedRow(vv);
} catch (SQLException ex) {
Logger.getLogger(showp1.class.getName()).log(Level.SEVERE, null, ex);
}
regFace.setVisible(true);
}
}
and the the code for jframe1
public void setSelectedRow(String row ) throws SQLException {
dbconnect = new myDbConnection();
ResultSet resultSet =null;
System.out.print(row);
resultSet = dbconnect.excuteQuery("SELECT id, area,location, status1 ,date1,insname,oname,bname,street,junction,INSPSITION,recname1 FROM pledges where id='"+row+"'");
while (resultSet.next()){
id.setText(resultSet.getString(1));
area.setText(resultSet.getString(2));
location.setText(resultSet.getString(3));
status.setText(resultSet.getString(4));
date.setText(resultSet.getString(5));
insname.setText(resultSet.getString(6));
oname.setText(resultSet.getString(7));
bname.setText(resultSet.getString(8));
street.setText(resultSet.getString(9));
junction.setText(resultSet.getString(10));
insposition.setText(resultSet.getString(11));
recname.setText(resultSet.getString(12));
}
}

Categories