I create Jtable that store data from the database that I can delete/add contents' the Jtable with Jbutton. When I t try to run the code, I got this result:
When I add data into Jtable twice,there is data in it with an extra blank row
When I delete data into Jtable twice,data in a specific row is deleted but it add a transparent blank row too.
Why does this happen?
Here the code that I think there is a problem:
//add,delete button
final JToggleButton tglbtnAdd = new JToggleButton("Add");
final JToggleButton tglbtnDelete = new JToggleButton("Delete");
JButton button = new JButton("1");
button.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent arg0) {
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection dbconbt1 = DriverManager.getConnection("" +"jdbc:sqlserver://localhost;databaseName=Store;user=sa;password=");
Statement sqlstatement = dbconbt1.createStatement();
ResultSet dbresultset1 = sqlstatement.executeQuery("select * from Store.dbo.Product where ProductID = 'P-1'");
ResultSetMetaData rsmetadata = dbresultset1.getMetaData(); // Get metadata on them
int numcols = rsmetadata.getColumnCount(); // How many columns?
// Get column names
for (int i = 1; i <= numcols; i++) {
defaultmodel2.addColumn( rsmetadata.getColumnName(i));
}
if(tglbtnAdd.isSelected() == true) {
while (dbresultset1.next()) {
Vector<Object> row = new Vector<Object>(numcols);
for (int i = 1; i <= numcols; i++) {
row.addElement( dbresultset1.getObject(i) );
}
defaultmodel2.addRow(row );
}
}
if(tglbtnDelete.isSelected() == true) {
/**while (dbresultset1.next())
{
Vector<Object> row = new Vector<Object>(numcols);
row.removeElement( dbresultset1.getObject(0) );
}
*/
defaultmodel2.removeRow(0);
}
// Get row
dbresultset1.close();
sqlstatement.close();
dbconbt1.close();
Make your table structure on form load only, and just take your data from JTextField's (or from whatever you use) into Object array. Finally, add the object array to your model. For delete, just call model.removeRow() method.
Related
The method I've provided here is supposed to create a new table, perform the recall, and then update the table with the message that is received by the person contacted. It all works fine, except for the received message. I can even click the button again that initiates the recall and it then updates the table to include the message that was received, but nothing I add to the code seems to update the table automatically. As you can see here I've even tried completely redrawing the table and that doesn't work either. The only thing that actually makes the message show up is by re initiating the recall.
I've tried re validate and repaint but those don't seem to work.
public void doRecall() throws Exception {
newFrame = new JFrame("Recall Initiated Awaiting Replies");
newFrame.setSize(600, 300);
newFrame.setIconImage(img);
Member con = new Member();
String columnNames[] = { "First Name", "Last Name", "Phone No.",
"Response" };
Object[][] data = new Object[v.size()][4];
for (int j = 0; j < v.size(); j++) {
con = (Member) v.elementAt(k);
data[j][0] = con.getFName();
data[j][1] = con.getLName();
data[j][2] = con.getPhoneNo();
data[j][3] = con.getResponse();
k++;
}
k = 0;
abtable = new JTable(data, columnNames);
JScrollPane scrollPane = new JScrollPane(abtable);
abtable.setPreferredScrollableViewportSize(new Dimension(500, 370));
JPanel pane = new JPanel();
JLabel label = new JLabel("Members Currently In The Recall Roster");
pane.add(label);
newFrame.getContentPane().add(pane, BorderLayout.SOUTH);
newFrame.getContentPane().add(scrollPane, BorderLayout.CENTER);
newFrame.setLocation(screenWidth / 4, screenHeight / 4);
newFrame.setVisible(true);
String customMessage = getMessage();
k = 0;
for (int j = 0; j < v.size(); j++) {
con = (Member) v.elementAt(k);
try {
String toPhoneNumber = con.getPhoneNo();
customMessage = customMessage.replaceAll("\\s+", "+");
System.out.println(customMessage);
String requestUrl = ("http://cloud.fowiz.com/api/message_http_api.php?username=&phonenumber=+"
+ toPhoneNumber + "&message=" + customMessage + "&passcode=");
URL url = new URL(requestUrl);
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
System.out.println(uc.getResponseMessage());
String reply = uc.getResponseMessage();
if (reply.equalsIgnoreCase("ok")) {
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
k++;
}
k = 0;
for (int j = 0; j < v.size(); j++) {
con = (Member) v.elementAt(k);
boolean phoneCheck = false;
while (phoneCheck != true) {
for (int j1 = 0; j1 < v.size(); j1++) {
con = (Member) v.elementAt(k);
mR2 = new MailReader();
String host = "pop.gmail.com";// change accordingly
String mailStoreType = "pop3";
String username = "";// change
// accordingly
String password = "";// change accordingly
MailReader.check(host, mailStoreType, username, password);
if (MailReader.searchForPhone(con.getPhoneNo()) == true) {
con.setResponse(MailReader.getReply(con.getPhoneNo()));
newFrame.addNotify();
System.out.println("IT WORKED");
newFrame.remove(scrollPane);
JTable abctable = new JTable(data, columnNames);
JScrollPane scrollPane2 = new JScrollPane(abctable);
newFrame.getContentPane().add(scrollPane2,
BorderLayout.CENTER);
abtable.repaint();
newFrame.repaint();
newFrame.revalidate();
phoneCheck = true;
}
}
}
}
}
When interacting with the data of the table, we want to use the TableModel of the table. The TableModel is what actually holds the data, and allows us to easily manipulate the data in the table.
You can either implement your own AbstractTableModel or use the DefaultTableModel, which already provides an implementation, that comes equipped with method for adding row and other goodies.
With DefaultTableModel, you can simply call the method addRow(Object[]) or addRow(Vector) to add a row dynamically at runtime. For example:
String columnNames[] = {
"First Name", "Last Name", "Phone No.", "Response" };
DefaultTableModel model = new DefaultTableModel(columnNames, 0):
JTable table = new JTable(model);
...
// dynamically add a row
Object[] row = { data1, data2, data2, data4 };
model.addRow(row);
The DefaultTableModel implementation will fire the necessary updates to call for a repainting of the table.
See the DefaultTableModel API for other useful methods and constructors. Add see How to Use Tables for general information on using tables.
How i refresh the JTable ?
Here is my Code.
public void itemStateChanged(ItemEvent evt)
{
String text=(String)to_Cmb2.getSelectedItem();
try
{
// Connect to an Access Database
Connection con=DriverManager.getConnection("jdbc:odbc:flightdsn");
Statement s=con.createStatement();
// Read data from a table
ResultSet rs = s.executeQuery("SELECT FlightNo,City,To,Arrives,Departs FROM I_Flights_Routes WHERE To ='"+text+"' ");
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
// Get column names
for (int i = 1; i <= columns; i++)
{
columnNames.addElement(md.getColumnName(i));
}
// Get row data
while (rs.next())
{
Vector<Object> row = new Vector<>(columns);
for (int i = 1; i <= columns; i++)
{
row.addElement(rs.getObject(i));
}
data.addElement(row);
}
rs.close();
s.close();
con.close();
}
catch (Exception e)
{
System.out.println(e);
}
// Create table with database data
JTable table = new JTable(data, columnNames)
{
public Class getColumnClass(int column)
{
for (int row = 0; row < getRowCount(); row++)
{
Object o = getValueAt(row, column);
if (o != null)
{
return o.getClass();
}
}
return Object.class;
}
};
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setBounds(50,10,400,200);
td.add(scrollPane);
// td is Jpanel object
td.setVisible(true);
}
You're creating an entirely new JTable -- don't do that. Use the same JTable but
modify the JTable's model if you want to add new data to existing data
or if you want to totally replace the data in the table, create a new DefaultTableModel (or other TableModel) and set your JTable's model with it via `setModel(...).
Also, as an aside you will want to avoid using null layouts and setBounds(...) as this creates very inflexible GUI's that look terrible on other platforms or other resolutions and are very difficult to upgrade and manage.
As mentioned in the header I cannot get my JTable to update with a new row unless I restart the program. When I restart, the new row is there and everything is as it should be. I have tried revalidating/repainting the panel and frame, I have tried the fire methods. I'm at a loss. Thanks in advance
ActionListener (in adminGUI class) for 'Add' button:
if(source.equals(add2)){
String c = itb.getText();
int a = main.getResults();
boolean matches = Pattern.matches("[A-Z][a-z]+", c);
if(matches == true){
main.addGenre(a, c);
}
String Method(in main class) to add a row to the database table:
public static void addGenre(int a, String b){
int rowsAdded;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection connect =DriverManager.getConnection("jdbc:odbc:MovieDB");
Statement stmt = connect.createStatement();
String query = "INSERT INTO Genres (genre_id, genre_name)" + "VALUES(" + a + ", '" + b + "')";
rowsAdded = stmt.executeUpdate(query);
}catch(Exception exc){}
}
Method(also in main class) to increment the auto-increment-key column:
public static int getResults(){
int a = 0;
ResultSet ints = main.getResults("Select genre_id from Genres");
try {
while(ints.next()){
int d = ints.getInt("genre_id");
if(d>a){
a = d;
}
a++;
}
} catch (SQLException ex) {
Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
}
return a;
}
JTable details:
ResultSet rs1 = main.getResults("Select * from Genres");
JTable tab1 = new JTable(DbUtils.resultSetToTableModel(rs1));
DbUtils.resultSetToTableModel details :
public class DbUtils {
public static TableModel resultSetToTableModel(ResultSet rs) {
try {
ResultSetMetaData metaData = rs.getMetaData();
int numberOfColumns = metaData.getColumnCount();
Vector columnNames = new Vector();
// Get the column names
for (int column = 0; column < numberOfColumns; column++) {
columnNames.addElement(metaData.getColumnLabel(column + 1));
}
// Get all rows.
Vector rows = new Vector();
while (rs.next()) {
Vector newRow = new Vector();
for (int i = 1; i <= numberOfColumns; i++) {
newRow.addElement(rs.getObject(i));
}
rows.addElement(newRow);
}
return new DefaultTableModel(rows, columnNames);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
"I cannot get my JTable to update with a new row unless I restart the program."
I think what you're expecting is that when the database table update, so should your JTable. It doesn't really work like that. You need to update the TableModel, and the JTable will be automatically updated
Since resultSetToTableModel returns a DefuaultTableModel, you can use either of the two methods from DefaultTableModel:
public void addRow(Object[] rowData) - Adds a row to the end of the model. The new row will contain null values unless rowData is specified. Notification of the row being added will be generated.
public void addRow(Vector rowData) - Adds a row to the end of the model. The new row will contain null values unless rowData is specified. Notification of the row being added will be generated.
So when your are adding the data to the database, you also want to update the DefaultTableModel like this
public static void addGenre(Integer a, String b){
...
rowsAdded = stmt.executeUpdate(query);
if (rowsAdded > 0) {
DefaultTableModel model = (DefaultTableModel)tab1.getModel();
model.addRow( new Object[] { a, b });
}
}
Also noticed I changed the method signature to Integer instead of int so it will fit with the Object[] passed to addRow. The int you pass to it will get autoboxed to Integer
SIDE NOTES
Don't swallow you exception by putting nothing in the catch block. Put something meaningful that will notify you of any exceptions that may occur, like
catch(Exception ex) {
ex.printStackTrace();
}
You should also close your Connections, Statements, and ResultSets
You should use PreparedStatement instead of Statement, to avoid SQL injection.
private void resetListData() throws ClassNotFoundException, SQLException
{
Connection cne = null;
try {
Class.forName("org.sqlite.JDBC");
cne = DriverManager.getConnection("jdbc:sqlite:table.sqlite");
cne.setAutoCommit(false);
PreparedStatement psd = (PreparedStatement) cne.prepareStatement("Select * from Genres");
psd.execute();
ResultSet r = psd.getResultSet();
ResultSetMetaData rsmd = r.getMetaData();
int count = rsmd.getColumnCount();
String[] meta = new String[count];
for (int i = 0; i < count; i++)
{
String name = rsmd.getColumnName(i + 1);
meta[i] = name;
//System.out.println(name);
}
model = new DefaultTableModel(new Object[][]{}, new String[]{"name", "address"});
jTable1.setModel(model);
while (r.next())
{
Object[] row = new Object[count];
for (int i = 1; i <= count; ++i)
{
row[i - 1] = r.getString(i); // Or even rs.getObject()
}
model.addRow(row);
}
cne.close();
} catch (ClassNotFoundException | SQLException e) {
}
}
Use this code. so you can insert one row at the end of Jtable without restarting application.,
Thanks..
I want to put an action whenever someone clicks a cell. open another gui for example. But how do i make a cell clickable BUT not editable? These are results for an sql query. I can't manage to make the table uneditable though. Do I need a listener or something? and if yes where should I put it?
Here is my code:
public class AllResultsFromDB extends JFrame
{
GUI ins = new GUI();
public AllResultsFromDB(GUI x)
{
Vector columnNames = new Vector();
Vector data = new Vector();
this.ins = x;
try
{
// Initializing GUI class in order to call getSelectedTable() method.
// GUI ins = new GUI();
//System.out.println(ins.getSelectedTable());
Login sgui = new Login();
String dburl = "jdbc:oracle:thin:#localhost:1521:ORCL";
Connection connection = DriverManager.getConnection( dburl, sgui.getUsername(), sgui.getPassword() );
// Fetch data from table specified by user
String query = "SELECT * FROM " + ins.getSelectedTable() + " ORDER BY id";
System.out.println(query);
Statement stmt = connection.createStatement();
ResultSet rset = stmt.executeQuery(query);
ResultSetMetaData metad = rset.getMetaData();
int columns = metad.getColumnCount();
// This loop gets the names of the columns
for (int i = 1; i <= columns; i++)
{
columnNames.addElement( metad.getColumnName(i) );
//columnNames.addElement("PROFILES");
}
// This loop gets the data inside the rows
while (rset.next())
{
Vector row = new Vector(columns);
//Vector b = new Vector((Collection)button);
for (int i = 1; i <= columns; i++)
{
row.addElement( rset.getObject(i) );
}
data.addElement( row );
//data.addElement(b);
}
rset.close();
stmt.close();
connection.close();
// Create table with results
JTable table = new JTable(data, columnNames)
{
public Class getColumnClass(int column)
{
for (int row = 0; row < getRowCount(); row++)
{
Object obj = getValueAt(row, column);
if (obj != null)
{
return obj.getClass();
}
}
return Object.class;
}
};
JScrollPane scroll = new JScrollPane( table );
getContentPane().add( scroll );
//table.addMouseListener(l);
//table.setEnabled(false);
//table.setDragEnabled(true);
JPanel panel = new JPanel();
getContentPane().add( panel, BorderLayout.SOUTH );
} catch (SQLException e) {
}
}
}
Start by taking a look at How to use tables
The isCellEditable method the TableModel determines of a cell is editable or not. This method should return false
When you supply column/data information to the JTable directly, the JTable creates a DefaultTableModel internally. This class's isCellEditiable method will return true by default.
By using something like DefaultTableModel, you can override this method without with to much trouble and set the model to the table directly.
Next, you need to attach a MouseListener to the table
Take a look at How to write a Mouse Listener
You can then use getSelectedColumn, getSelectedRow to get the selected cell.
You'll also need to use convertRowIndexToModel and convertColumnIndexToModel to convert between the view and model indices
How to display ResultSet in JTable. i am using this code
String [] record= new
String[ColCount];
for (i=0; i<ColCount; i++)
{
record[i]=rset1.getString(i+1);
}
cell[i] = rset1.getString("loginname");
cell[i] = rset1.getString( "role");
System.out.println(cell[i][0]);
//ItemGroup = rset1.getString( "Status");
}
System.out.println(ItemCode);
JTable jt = new JTable(
cell[i], headers);
but I get only one row which is lastly inserted to database.
You need to put a while loop around your code to iterate over the result set. eg,
while(rset1.next())
{
//do something
}
The code that you have listed is incomplete/incomprehensible, but the code below shows how to take a ResultSet with an arbitrary number of columns and display its contents in a JTable.
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
private void viewTable(){
//Perform database query here, which will open a Connection to the database
//Assume we use the above query to populate a ResultSet results
//Get information about the ResultSet
ResultSetMetaData metaData = results.getMetaData();
//Gets the number of columns in results
int columnCount = metaData.getColumnCount();
//Gets the name of each column in results
String[] columnNames = new String[columnCount];
for(int i = 0; i < columnNames.length; i++){
columnNames[i] = metaData.getColumnLabel(i+1);
}
//You can use a String[] to keep track of the rows if you know the #
//# of rows in the ResultSet, this implementation assumes that we don't
//This ArrayList will keep track of each row in results (each row is
//represented by a String[]
ArrayList<String[]> rows = new ArrayList<>();
while(results.next()){
//Fetch each row from the ResultSet, and add to ArrayList of rows
String[] currentRow = new String[columnCount];
for(int i = 0; i < columnCount; i++){
//Again, note that ResultSet column indecies start at 1
currentRow[i] = results.getString(i+1);
}
rows.add(currentRow);
}
//Close Connection to the database here
String[][] rowsArray = new String[rows.size()][columnCount];
rowsArray = rows.toArray(rowsArray);
table = new JTable(rowsArray, columnNames);
}