I have a project set up with with an embedded derby jdbc and a jtable, however when I try to append data from my database to my jtable through resultset and adding the results from the resultset to a string[] and adding it to my tablemodel the result display is blank.
This is my database resultset:
ResultSet res = statement.executeQuery("SELECT * FROM VAULT");
while (res.next()) {
String [] row = {res.getString("Expenses"), res.getString("ExpensesType"), res.getString("PaymentType"), res.getString("Amount"), res.getString("Date")};
System.out.print(res.getString("Expenses"));
System.out.print(res.getString("ExpensesType"));
System.out.print(res.getString("PaymentType"));
System.out.print(res.getString("Amount"));
System.out.print(res.getString("Date"));
GUI.tableModel.addRow(row);
GUI.tableModel.fireTableDataChanged();
}
res.close();
This is my table code:
table = new JTable(tableModel);
table.setBackground(Color.GRAY);
table.setFillsViewportHeight(true);
JTableHeader header = table.getTableHeader();
header.setBackground(Color.DARK_GRAY);
header.setForeground(Color.LIGHT_GRAY);
scrollPane.setViewportView(table);
tableModel.addColumn("Expenses");
tableModel.addColumn("Expense Type");
tableModel.addColumn("Payment Type");
tableModel.addColumn("Amount");
tableModel.addColumn("Date");
Since the code, basically, works, I have to assume the problem is with some other part of the application which I cannot replicate, like the database management for example...
However...
Your resource management is non-existent...A database Statement has context and has a direct relationship to the query that made it, once you have completed working with it you should make sure you close it, for example...
public static Connection createDatabaseConnection() throws SQLException, ClassNotFoundException {
//...
System.out.println("Database Connected...");
try (Statement statement = c.createStatement()) {
count = statement.executeUpdate("CREATE TABLE VAULT (Expenses VARCHAR(5000), ExpensesType VARCHAR(5000), PaymentType VARCHAR(5000), Amount VARCHAR(10), Date VARCHAR(5000))");
System.out.println("Table Created...");
}
try (Statement statement = c.createStatement()) {
ResultSet res = statement.executeQuery("SELECT * FROM VAULT");
while (res.next()) {
String[] row = {res.getString("Expenses"), res.getString("ExpensesType"), res.getString("PaymentType"), res.getString("Amount"), res.getString("Date")};
System.out.print(res.getString("Expenses"));
System.out.print(res.getString("ExpensesType"));
System.out.print(res.getString("PaymentType"));
System.out.print(res.getString("Amount"));
System.out.print(res.getString("Date"));
GUI.tableModel.addRow(row);
}
}
and...
String updateStatement = "INSERT INTO VAULT"
+ " (Expenses, ExpensesType, PaymentType, Amount, Date)"
+ " VALUES (\'" + expenses + "\',\'" + expensesType + "\',\'" + paymentType + "\',\'" + amount + "\',\'" + date + "\')";
try (Statement statement = c.createStatement()) {
System.out.print(updateStatement);
int c = statement.executeUpdate(updateStatement);
count = count + c;
System.out.println("Data Inserted in to Database...");
} catch (Exception ex) {
ex.printStackTrace();
}
This will ensure that once you leave the try section, the resource will automatically be closed.
You should also consider making use of PreparedStatements, see Using Prepared Statements for more details.
In your actionPerformed method, this...
table.setModel(tableModel);
is worrying. The model has already been set when you setup the UI, you shouldn't need to set it again unless you've create a new model or table, which you've done neither of...
And...
tableModel.fireTableDataChanged();
table.updateUI();
Should never be done. You should never call any of the notification methods of a model externally, these should all be taken care of by the model it self (and in the case of the DefaultTableModel are).
updateUI has nothing to do with "updating the state of the UI" and has is probably the most efficient method you could use. The simple fact that you've fireTableDataChanged should have already triggered an update (although fireTableDataChanged is also one of the most efficient methods you could use as well).
Simply call tableModel.addRow and let the model and table do the rest.
Your work flow is a little off. You shouldn't add the row to the table until AFTER you've made sure it's been added to the database, what happens if the insert fails for some reason?
You really, really, REALLY should learn to make use of dialogs, see How to Make Dialogs for more details, instead of throwing, yet, another frame at the user...
static is not your friend, sure it might "seem" to make life easier and "it's just a quick {what ever}", but bad is bad any of the time...
You should never make UI components static it is way to easy to lose context and not know if you're updating what's actually on the screen or not.
"But how does class X reference component Y?" - in most cases, it shouldn't. I should either return a value/values that container class can deal with or should communicate through the use of some kind of model or observer pattern...
If you're going to strip away the window frame, you had better implement functionality that allows me to drag it and, because it's a personal grip of mine, resize it, otherwise your users will not like you
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
See Why is it frowned upon to use a null layout in Swing? and Laying Out Components Within a Container for more details...
Related
am developing a java application and I want to populate a ComboBox with First name and Last name from a table in database. how can I concatenate the two columns to display as one Full Name
this is my code. I will greatly appreciate for any assistance.
private void fillcombo(){
try{
conn = DriverManager.getConnection(url, user, password);
String sql = "select * From Member_Reg" ;
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
while(rs.next()){
String name = rs.getString("First_name+""+Last_name");
jComboBoxMembername.addItem(name);
}
}catch(Exception ex){
JOptionPane.showMessageDialog(null,ex);
}
}
Get two Strings out of the ResultSet and concatenate them in your Java code.
String name = rs.getString("First_name") + " " + rs.getString("Last_name");
It'd also be a really good idea to break that method up into multiple different ones - database access should be done in a different place to UI generation.
At a minimum this should be a method constructing your jComboBoxMembername variable (which seems to be global in your code at the moment, and it almost certainly shouldn't be), and that method should call a different method that retrieves the name from the database. So one method responsible for constructing the UI, and one method responsible for accessing the database. As your application gets bigger you'll want to separate them into different classes as well - a presentation class (or classes) and a database access class (or classes).
Replace the first line inside the while loop with the following line:
String name = rs.getString("First_name") + " " + rs.getString("Last_name");
This is my first question here and I hope I am not repeating someone else's question. I will try and explain the problem as much as I can in the next few lines. Pardon my English if its really bad .
So I have here a JTable in which I would like to retrieve values from a database. So far I can add 1 value and I know why this is. The question is . How do I add multiple values to this table ?
This is the method I use in my operations to find a gun in a specific shop with its quantity
public ResultSet gunSearch(String id, int qty, int storeId) {
try {
String s = "SELECT gunID, gunName AS \"Gun Name\", gunPrice AS \"Price\", SellCost AS \"Cost\", availableQty AS \"Amount Available\", "+qty+" AS \"Quantity\" FROM Guns WHERE gunId = '" + id + "'AND storeId='"+storeId+"'";
pstmt = conn.prepareStatement(s);
rset = pstmt.executeQuery(s);
} catch (Exception ex) {
System.out.println("Error here at searchByProdId Operation "+ex);
}
return rset;
}
For my GUI I use the following code to display the information entered by the user
public void actionPerformed(ActionEvent e){
if(e.getSource().equals(enterBtn)){
String gunID = gunIdText.getText();
int qty = Integer.parseInt(quantityText.getText());
table.setModel(DbUtils.resultSetToTableModel(op.gunSearch(gunID, qty, storeId)));
Whenever I click the Enter button the column of data is retrieved from the database. However if I re-enter another gunId and quantity , the previous column disappears and the new column of data is retrieved from the database.
How could I possibly , enter couple of different gunId's and quantitie's into the JTable ?
Your gunSearch method only returns one result. You then completely recreate the TableModel from this one result, erasing whatever you had in the old model.
You'll need to concoct a new method that can take a Collection<String> (a collection of gun ids) and return a row for each id provided.
Alternatively, you can create a method that adds a gun to an existing TableModel rather than recreating the whole model from scratch every time. It depends on how you want the application to work, which option is better.
I'm trying to create a Java GUI dynamically by taking values from a result set and using it to generate a checklist. I've created a small demo program to demonstrate what I've done:
SQL Commands
CREATE USER 'test'#'localhost' IDENTIFIED BY 'testpw';
CREATE DATABASE combotest;
USE combotest;
CREATE TABLE combotable (
id INT(5) NOT NULL PRIMARY KEY auto_increment,
type VARCHAR(50) NOT NULL);
INSERT INTO combotable (id, type) VALUES
(default, 'Label'),
(default, 'Textfield'),
(default, 'Combo'),
(default, 'Label'),
(default, 'Textfield'),
(default, 'Combo'),
(default, 'Combo');
GRANT SELECT ON combotest.* TO 'test'#'localhost';
For your convenience if you'd like to test it yourself I've put all the SQL commands above.
Now, for my Java code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.*;
import javax.swing.*;
public class resToComboDemo implements ActionListener {
//JDBC Variables
static Connection connect = null;
static Statement statement = null;
static ResultSet res = null;
#SuppressWarnings("rawtypes")
//Other Variables
JComboBox comboBox;
JButton submit;
JFrame frame;
JLabel label;
JTextField textField;
Container pane;
public static void main(String[] args) throws SQLException {
new resToComboDemo();
}
public resToComboDemo() throws SQLException {
try {
Class.forName("com.mysql.jdbc.Driver");
// Setup the connection with the DB
connect = DriverManager
.getConnection("jdbc:mysql://localhost/combotest?"
+ "user=test&password=testpw");
statement = connect.createStatement();
//Note: in this specific case I do realize that "order by id" is not necessary. I want it there, though.
res = statement.executeQuery("SELECT * FROM combotable ORDER BY id");
createStuff(res);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Error 1: "+e, "Error!", JOptionPane.ERROR_MESSAGE);
} finally {
connect.close();
}
}
#SuppressWarnings({"rawtypes", "unchecked" })
public void createStuff (ResultSet res) throws SQLException {
frame = new JFrame("Testing dynamic gui");
Dimension sD = Toolkit.getDefaultToolkit().getScreenSize();
int width = sD.width;
int height = sD.height - 45;
frame.setSize(width,height);
pane = frame.getContentPane();
pane.setLayout(new GridLayout(0, 2));
while (res.next()) {
Object[] options = { "Pass", "Fail"};
String type = res.getString("type");
JLabel label = new JLabel("<html><small>"+type+"</small></html>");
JLabel blank = new JLabel(" ");
blank.setBackground(Color.black);
blank.setOpaque(true);
if (type.equals("Label")) {
label.setBackground(Color.black);
label.setForeground(Color.white);
label.setOpaque(true);
pane.add(label);
pane.add(blank);
} else if (type.equals("Combo")) {
pane.add(label);
comboBox = new JComboBox(options);
pane.add(comboBox);
} else if (type.equals("Textfield")) {
pane.add(label);
textField = new JTextField(20);
pane.add(textField);
}
}
JLabel blank2 = new JLabel(" ");
pane.add(blank2);
submit = new JButton("Submit");
submit.addActionListener(this);
pane.add(submit);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
Now, everything works great with creating the GUI here. However, I need to be able to treat the Combobox and Textfield components as their own separate entities. Meaning, I want to be able to get user input from each different component. Right now, if I were to request information from textfield, it just gives me the information from the last textfield. This makes perfect since, because that's how java reads it. I have no problem with that.
I just can't for the life of me figure out how to get each component's input separately. Perhaps by taking the result set and adding the results to some type of array? I've attempted this multiple times in different flavors and I can't get it to come out the way I need it to. Some of you are going to request that I show you what I've tried... but honestly, it's not worth it.
And, before anybody asks: No, I will not use FlowLayout. :)
Any help is greatly appreciated!
There are probably a few ways to achieve this based on what you want to do...
If you are only performing a batch update, you could use a Map keyed to the id of the row and mapping to the Component.
This way, when you want to save the values back to the database, you would simply iterate the Maps key values, extract the Component associated with each key and then extract the value of the Component...
I might consider making a wrapper interface which has a simple getText method and wrap the component within it, making the implementation of the wrapper responsible for extracting the text, but that's just me ;)
If you want to perform updates when a individual component is updated, you would need to swap the mapping, so that the Component would the key and the id would be mapped to it.
This would mean that when some kind of event occurred that would trigger and update (ie a ActionEvent), you could extract the source from the event and look up the id in the Map based on the Component that caused the event...
Now...frankly, I would simply use a JTable and create a custom TableModel which could model all this.
This would require you to create POJO of the table, maintaining the id, type and value within a single object. This would define a basic row in the table.
The only problem is you would need to create a (reasonably) complex TableCellEditor that could take the type and return an appropriate editor for the table. Not impossible, it's just an additional complexity beyond the normal usage of a table.
This would all the information you need is available in a single object of a single row in the table.
Take a look at How to use tables for more details
Equally, you could use a similarly idea with the Map ideas above...
You could also simply create a self contained "editor" (extending from something like JPanel), which maintain information about the id and type and from which you could extract the value and simply keep a list of these....for example...
what about interrogating the Container ( pane) which contains the components
getComponents() method and loop through the sub component and check for JComobox and JTextField do the required cast and retrieve the value
Just an idea in case you are against adding the sub-components into a kind of list
You only have a reference to the last text field or combo box that you create, since you are reusing the variables that hold them. I would put them in an ArrayList, store each new text field and combbox as you create them, then you can go back and get input from all of them after you're done.
---------- (after the OP's response to the above paragraph)
No, there is no "place to refer you" -- it's your set of requirements, it would be pretty remarkable to find code that already existed that did this exact thing. Java and Swing give you the tools, you need to put things together yourself.
You don't show your "actionPerformed" routine, but let's hypothesize about it for a minute. It is called by the framework when an action is done, and it is passed an "ActionEvent" object. Looking through its methods, we find that it has "getSource()", so it will give you a reference to the component which generated the event.
Let's further think about what we have -- a set of components in the UI, and ones which can generate events are interesting to us. We want to, in this case, retrieve something from the component that generated the event.
If we have the component (from actionEvent.getSource()) and we want to do something with it, then we can, at worst do something like the following in the actionPerformed() method:
Component sourceComponent = actionEvent.getSource();
if (sourceComponent instanceof JComboBox)
{ JComboBox sourceBox = (JComboBox) sourceComponent;
// get the value from the combo box here
}
else if (sourceComponent instanceof JTextField)
{ JTextField sourceTextField = (JTextField) sourceComponent;
// get the value from the text field here
}
// or else do nothing -- our action was not one of these.
Done this way, you don't even need to keep a list of the components -- the UI is keeping a reference to all of them, and you just use that reference when the actionEvent occurs.
Now, this is not the only or even the best or the simplest way of doing this. If you wanted to extend JComboBox and JTextField with your own classes, you could have those classes both implement an interface that defined something like getValue() or getText; then you would not need the ugly instance of operator, which can usually be done away with by better design and planning.
I have 3 jlists. I have a button that is used to delete a selected item from the Patient Jlist but I also need it to delete from my history Jlist and Invoices Jlist. I have it deleting from one but I dont know how to implement the code to delete from the history jlist and invoices jlist.
Here is my code to delete from 1 JList which works!:
JButton btnDeleteDB = new JButton("Delete From DB");
btnDeleteDB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
int selectedIndex = patientList1.getSelectedIndex();
if (selectedIndex != -1) {
int x = patientList.get(selectedIndex).getID();
String query =
"DELETE FROM `patienttable` WHERE `patientid` ='"+x+"' LIMIT 1";
try {
Connection con =
DriverManager.getConnection(
"jdbc:mysql://localhost:3306/denistassignment","root","");
Statement s = (Statement) con.createStatement();
s.execute(query);
} catch (Exception ex) {
ex.printStackTrace();
}
patientListModel.remove(selectedIndex);
patientList1.remove(selectedIndex);
}
}});
btnDeleteDB.setBounds(320, 500, 125, 23);
contentPane.add(btnDeleteDB);
Your code shows quite a few design flaws I'm afraid, I will list some before answering your question:
Remove the code which removes the item from the DB and the list from the ActionListener and place it in a private method so you have easy access to it from other listeners if needed, to enhance readability and to avoid code duplication.
You are not closing neither the DB connection nor the statement. Do so.
Don't catch general Exceptions, and don't just call e.printStackTrace() unless for explicit debug code which is removed before production.
patientList1.remove(selectedIndex); has nothing to do with removing an item from the JList, consult the JavaDoc of this method for details. In short, remove that line.
I suppose all your JLists are in the same class and you have member variables pointing to each. If so, then just locate the corresponding objects which should also be removed in your other JLists at the same time you are locating the index of the currently selected one. I don't know the details of your system, so maybe iterate over the other list items, compare IDs with the ID of the one you want to delete and then just call listXY.getModel().remove(indexOfItem) for each one you want to delete.
I am using jTable in netbeans. After selection of combobox if i select employee id 1 it show all data of emp 1 in jTable. But next time when i choose emmployee id 2 jTable shows single value of emp id 1's and all another values of empid 2.
My code is given below
Connect c = new Connect();//connection to database
con = (Connection) c.getConnection();
st = (Statement)con.createStatement();
String ddate = (String)text.getSelectedItem();
System.out.println("id " +ddate);
rs = st.executeQuery("select e.employee_id,e.`first_name`, i.outtime, i.outtime_date from tbl_employee e,tbl_outtime i where e.employee_id=i.outtime_emp_id and i.`outtime_date` LIKE '%/"+month2+"/"+year1+"'and outtime_emp_id="+ddate);
while(rs.next())
{
String dat1=rs.getString("outtime_date");
String e1=rs.getString("employee_id");
System.out.println(e1);
st33=(Statement) con.createStatement();
rs33=st33.executeQuery("select i.intime, i.intime_date from tbl_employee e,tbl_intime
i where e.employee_id=i.intime_emp_id and i.`intime_date`='"+dat1+"' and
i.intime_emp_id="+e1);
if(rs33.next())
{
int emp=rs.getInt("employee_id");
System.out.println(emp);
String name=rs.getString("first_name");
String dept=rs33.getString("intime");
String desig=rs.getString("outtime");
String join=rs33.getString("intime_date");
jTable1.setValueAt(emp, cnt, 0);
jTable1.setValueAt(name, cnt, 1);
jTable1.setValueAt(dept, cnt, 2);
jTable1.setValueAt(desig, cnt, 3);
jTable1.setValueAt(join, cnt, 4);
cnt=cnt+1;
}
}
Tell me solution if anyone knows.
read tutorial about JTable
all data for JTables view are stored into XxxTableModel
have to clear XxxTableModel, and add new row(s) from JDBC to the XxxTableModel
Use TableModel for adding row.
Read
http://docs.oracle.com/javase/tutorial/uiswing/components/table.html
for samples.
Like all other Swing components, a table consists of two parts: a view part (the JTable) and a model part (the TableModel). The view is updated when the model indicates it has been changed by throwing events. See the table tutorial for more information.
So for your use-case, you can either adjust the existing TableModel or create a new one. I would personally opt to create a new one since you are working with a database.
Note that Swing components should only be accessed and modified on the Event Dispatch Thread, and that long running tasks (as querying a database) should not happen on this thread (see the Swing concurrency tutorial). That is why I would recommend to create a new TableModel. You can create this model on the worker thread you use for querying the database, and the replace the model in one go on the Event Dispatch Thread. The SwingWorker class is most suited for this.