Here is a Controller Class of MVC:
public class EventController extends MouseAdapter implements ActionListener {
private EventModel model;
private EventView view;
/** Constructor */
public EventController(EventModel myModel, EventView myView){
model = myModel;
view = myView;
}
public void setUpListeners() {
this.view.addEventButton.addActionListener(this);
this.view.addEventMenuItem.addActionListener(this);
this.view.editEventMenuItem.addActionListener(this);
this.view.tableEvent.addMouseListener(this);
}
#Override
public void actionPerformed(ActionEvent e){
Object button = e.getSource();
if(button==this.view.addEventButton) {
setEventDetails();
}
else if (button==this.view.addEventMenuItem) {
this.view.addDialog.setVisible(true);
}
else if(button==this.view.editEventMenuItem) {
this.view.editDialog.setVisible(true);
}
}
/*to change the display of label text of the VIEW according to the selected row of the table tableEvent*/
#Override
public void mouseClicked(java.awt.event.MouseEvent event) {
int rowSelected = view.tableEvent.getSelectedRow();
String tableClick = view.tableEvent.getModel().getValueAt(view.tableEvent.convertRowIndexToModel(rowSelected), 0).toString();
Events e = model.getEvent(tableClick); //tell model to change its state based on user input on views
view.changeDisplay(e);
}
Here is View Class and its changeDisplay() method to change label text appropriately:
public class EventView extends javax.swing.JFrame {
private EventModel model;
public void changeDisplay(Events e) {
evTitle.setText(""+e.getEventName());
evWhen.setText("When: "+ e.getEventDate());
evWhere.setText("Where: "+ e.getEventVenue());
evDescription.setText("Description: "+ e.getEventDetail());
evOpportunity.setText("Opporunity: "+ e.getEventOpportunity());
evMoreDet.setText("More Details: "+ e.getEventMoreDetails());
}
}
Here is Model Class:
public class EventModel {
Connection conn = JavaConnect.ConnectDB();
PreparedStatement pst = null;
ResultSet rs = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Events e = new Events();
public void addEvent(String name, Date date,String start, String venue, String details,
String opportunity, String more, String end) throws SQLException {
try {
String qry = "INSERT INTO EVENT(eventName,date,time,venue,details,opportunity,moreDetails,endTime) VALUES (?,?,?,?,?,?,?,?)";
pst = conn.prepareStatement(qry);
pst.setString(1, name);
pst.setString(2, sdf.format(date));
pst.setString(3, start);
pst.setString(4, venue);
pst.setString(5, details);
pst.setString(6, opportunity);
pst.setString(7, more);
pst.setString(8, end);
pst.executeUpdate();
}
finally{
try{ pst.close(); }
catch (SQLException se) {}
}
}
public Events getEvent(String tableClick) {
try {
pst = conn.prepareStatement("SELECT * FROM Event WHERE eventID='"+tableClick+"' ");
rs = pst.executeQuery();
while(rs.next()){
e.setEventName(rs.getString(2));
System.out.println(rs.getString(2));
e.setEventDate(rs.getString(3));
e.setEventTime(rs.getString(4));
e.setEventVenue(rs.getString(5));
e.setEventDetail(rs.getString(6));
e.setEventOpportunity(rs.getString(7));
e.setEventMoreDetails(rs.getString(8));
e.setEndTime(rs.getString(9));
rs.close();
pst.close();
}
}
catch(SQLException ex){
ex.printStackTrace();
}
return e;
} //end getEvent
}
My program is having a little error which I cant seem to fix for ages. Basically, whenever I click the row of the table (tableEvent) it should display the appropriate text in the labels next to the table as shown in the screenshot with the event "Software development careers event". This works fine on the first execution, but the mouseClicked event method in the controller does not change the display of the text after I've added an event through the addEvent method of the model. I am not sure what it is, whether I did something wrong with instantiation of an object of class Events, my addEvent method is wrong, or the actual mouseClicked overridden method in controller is wrong. What could it be?
I'm not sure that my answer helps you, but selection changes should be detected using ListSelectionListener. It's better because it provides reaction not only for the mouse clicks, but also for key events.
To add listener to your table simply use the selection model of the table:
myTable.getSelectionModel().addListSelectionListener(myListener)
Probably this change helps you to solve your problem
Related
I am designing a simple database application that features 2 jComboBoxes in the GUI. The first jComboBox is populated with the results of an SQL query. I would like the second jComboBox to populate with the results of a second query that incorporates the user selected value in the first box, but I can't quite get it to work.
I have created 2 classes, one that draws the GUI and contains the main method, and a second class that queries my Oracle database.
My GUI class:
public class TestUI extends javax.swing.JFrame {
// Create new form TestUI
public TestUI() {
initComponents();
}
#SuppressWarnings("unchecked")
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jComboBox1 = new javax.swing.JComboBox<>();
jTextField1 = new javax.swing.JTextField();
jComboBox2 = new javax.swing.JComboBox<>();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
// Combo box 1 population
jComboBox1.removeAllItems();
createConnection c1 = new createConnection();
c1.getEmployee().forEach((employee) -> {
jComboBox1.addItem(employee);
});
jComboBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jComboBox1ActionPerformed(evt);
}
});
// ComboBox 2 population
jComboBox2.removeAllItems();
}
private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add handling code here:
}
public static void main(String args[]) {
DRAW GUI
}
}
And my database class:
import java.util.List;
import java.util.ArrayList;
import java.sql.*;
public class createConnection {
String empName;
public Connection createConnection() {
try {
Class.forName(driver);
java.sql.Connection conn = DriverManager.getConnection(DB_URL, DB_username, DB_password);
return conn;
} catch (ClassNotFoundException | SQLException e) {
return null;
}
}
// ComboBox 1
public List<String> getEmployee() {
List<String> list = new ArrayList();
Connection conn = createConnection();
try {
Statement stmt = conn.createStatement();
String query = "SELECT * FROM hr.employees ORDER BY last_name";
ResultSet results = stmt.executeQuery(query);
while (results.next()) {
list.add(results.getString("last_name"));
}
} catch (Exception e) {
System.out.println("Exception = " + e);
}
return list;
}
// Combo Box 2
public List<String> getEmpLocation() {
List<String> list = new ArrayList();
Connection conn = createConnection();
try {
Statement stmt = conn.createStatement();
String query = "SELECT country_id FROM hr.location WHERE hr.location.emp_name = " + empName;
ResultSet results = stmt.executeQuery(query);
while (results.next()) {
list.add(results.getString("last_name"));
}
} catch (Exception e) {
System.out.println("Exception = " + e);
}
return list;
}
}
I have left out irrelevant code like db connection variables and GUI coordinates etc.
I am wondering how to properly get the getEmpLocation() method in the database class to populate the 2nd ComboBox. This will involve adding code to both classes and passing the variable value but I can't figure it out! Any help would be greatly appreciated here.
I'm assuming that you'd like select a value from your first JComboBox then click on a button to process your selected data and load new data to your second JComboBox.
In this case you need an ActionListener to your JButton instead of your JComboBox:
jButton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
selectedName = (String) jComboBox1.getSelectedItem();
}
});
You also need to store your selected value in a variable. The getSelectedItem() method returns an Object so it needs to be cast to a String in your case.
Since we added an ActionListener to a button you dont need this one:
jComboBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jComboBox1ActionPerformed(evt);
}
});
In your createConnection class (by naming convention class names should start with a capital letter):
If you are not using try-with-resources statement you should close your connections after the catch block.
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
You need to pass your selectedName variable to getEmpLocation() method:
public List<String> getEmpLocation(String name) {
You should use a PreparedStatement instead of Statement:
String query = "SELECT first_name FROM employees WHERE last_name = ?";
PreparedStatement ps = conn.prepareStatement(query);
ps.setString(1, name);
ResultSet results = ps.executeQuery();
To be honest I don't know what you'd like to achieve with your select queries. First, this select query won't work. Table name is LOCATIONS instead of location, and it doesnt have a column called emp_name.
"SELECT country_id FROM hr.location WHERE hr.location.emp_name = ?"
If you'd like to get locations you should use a query like this:
"SELECT dep.department_name, loc.city, cou.country_name
FROM employees emp, departments dep, locations loc, countries cou
WHERE emp.last_name = ?
AND emp.department_id = dep.department_id
AND dep.location_id = loc.location_id
AND loc.country_id = cou.country_id"
You can choose which location you'd like to use department, city or country name. But my main problem is that if you select last names first and put them in a JComboBox it is most likely you will get only one row of data, so there is no point in using the second JComboBox. Let's approach this problem from the other side. What if you select location first and then select your employee. That could solve this issue.
Quick Example:
You select all first names from database, then you can select proper last name.
Selecting all first name from database:
public List<String> getEmpFirstName() {
List<String> list = new ArrayList();
Connection conn = createConnection();
try {
Statement stmt = conn.createStatement();
String query = "SELECT DISTINCT first_name "
+ "FROM hr.employees "
+ "ORDER BY first_name";
ResultSet results = stmt.executeQuery(query);
while (results.next()) {
list.add(results.getString("first_name"));
}
} catch (Exception e) {
System.out.println("Exception = " + e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
return list;
}
Selecting last name(s) based on first name using PreparedStatement:
public List<String> getEmpLastName(String name) {
List<String> list = new ArrayList();
Connection conn = createConnection();
try {
String query = "SELECT last_name "
+ "FROM employees "
+ "WHERE first_name = ?";
PreparedStatement ps = conn.prepareStatement(query);
ps.setString(1, name);
ResultSet results = ps.executeQuery();
while (results.next()) {
list.add(results.getString("last_name"));
}
} catch (Exception e) {
System.out.println("Exception = " + e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
return list;
}
Update your ActionListener:
jButton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Store selected value
selectedName = (String) jComboBox1.getSelectedItem();
// Create Connection and pass selected value to getEmpLastName
createConnection c1 = new createConnection();
names = c1.getEmpLastName(selectedName);
// Clear your second comboBox and fill with data
jComboBox2.removeAllItems();
for (String lastName : names) {
jComboBox2.addItem(lastName);
}
}
});
Try to select common names like Alexander, David, James, John, Julia and so on.
I have a JComboBox that displays Name From database Patients_Details
public void ComboItem() {
chooser.removeAllItems();
chooser.addItem("Please Select...");
try {
String sql="select * from Patients_Details";
pst = conn.prepareStatement(sql);
rs=pst.executeQuery();
while (rs.next()) {
String id = rs.getString("Patient_ID"); // Get the Id
String name = rs.getString("Name"); // Get the Name
ComboItem comboItem = new ComboItem(id, name); // Create a new ComboItem
chooser.addItem(comboItem); // Put it into the ComboBox
String tmp=comboItem.getid();
}
} catch (SQLException sqle) {
System.out.println(sqle);
}
}
This is from comboitem class that only returns the name and not the id
public String toString() {
return this.name ;
}
My question is how do I get the selecteditem so that this action can be performed I have no clue how to do this I have been trying all bunch of code for almost 2 hours
any help will be much appreciated
NB I am Java beginner
private void chooserPopupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
try{
String sql="select * from Patients_Details where Patient_ID=? ";
pst=conn.prepareStatement(sql);
rs=pst.executeQuery();
if(rs.next()){
String add1=rs.getString("Patient_ID");
txtpatientid.setText(add1);
String add2=rs.getString("Name");
txtname.setText(add2);
String add3=rs.getString("Age");
txtage.setText(add3);
String add4=rs.getString("Gender");
txtgender.setText(add4);
String add5=rs.getString("Date");
txtdate.setText(add5);
}
}
catch(Exception e) {
JOptionPane.showMessageDialog(null,e );
}
}
Simply add an ActionListener to the combo box. When actionPerformed is called, you can look up the selected value and call what ever methods you need to.
For example:
chooser.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Object selectedValue = chooser.getSelectedValue();
// carry on with what ever you need
}
});
Have a look at ...
How to write action listeners
How to use combo boxes
For more details
I confused with this if-else because I'm new in Java & MySQL and I tried to make it by myself.
public Menu() {
initComponents();
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/restaurant", "root", "");
System.out.println("ODBC Connection Successful");
showCategory();
} catch (ClassNotFoundException | SQLException e) {
System.out.println("ODBC Connection Failed" + e);
}
}
if - else
private void showCategory() {
try {
Statement stmt;
stmt = con.createStatement();
if (rbMFood.isSelected()) {
ResultSet rs = stmt.executeQuery("SELECT * FROM menu_cat WHERE type_id = 'TY02'");
while (rs.next()) {
cmbMCat.addItem(rs.getString("menu_cat"));
}
} else {
ResultSet rs = stmt.executeQuery("SELECT * FROM menu_cat WHERE type_id = 'TY01'");
while (rs.next()) {
cmbMCat.addItem(rs.getString("menu_cat"));
}
}
} catch (Exception e) {
}
}
Radio Button
private void rbMFoodActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
type = "Food";
}
private void rbMDrinkActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
type = "Drink";
}
And I declare the function in the end of the program
private String type;
When I click drink / food, the category still drink's category.
The database
Any help would be greatly appreciated!
You are using rs.getString("menu_cat") But the format is rs.getString(<Column Name>) But you are using rs.getString(<Table Name>) As "menu_cat" is name of the table and not the name of the column.
AFTER POSTING CONSTRUCTOR
What I see from the code you have posted, is that You have called showCategory() in the constructor. This method is responsible for populating the JComboBox cmbMCat. Now the cmbMCat is being populated when you are creating the new Menu. After that the items list of the cmbMCat does not change.
So, What I suggest is that you call the showCategory() from the rbMFoodActionPerformed and rbMDrinkActionPerformed methods. I hope this will solve your problem.
Also add cmbMCat.removeAllItems() before Statement stmt; to remove all the items that are there in the cmbMCat and reset it with a fresh list of items.
After comment regarding the if-else
Change the showCatagory() as below:
private void showCategory() {
cmbMCat.removeAllItems();
try {
PreparedStatement stmt; //Used Prepared statement
String sql = "SELECT * FROM menu_cat WHERE type_id = ?";
stmt = con.prepareStatement(sql);
if (type.equals("Drink")) {
stmt.setString("TY01");
} else {
stmt.setString("TY02");
}
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
cmbMCat.addItem(rs.getString("menu_cat"));
}
}
} catch (Exception e) {
}
}
Also note that you eventListener code should be:
private void rbMFoodActionPerformed(java.awt.event.ActionEvent evt){
type = "Food";
showCategory();
}
private void rbMDrinkActionPerformed(java.awt.event.ActionEvent evt){
type = "Drink";
showCategory();
}
I have a JComboBox that displays Name From database Patients_Details
public void ComboItem() {
chooser.removeAllItems();
chooser.addItem("Please Select...");
try {
String sql="select * from Patients_Details";
pst = conn.prepareStatement(sql);
rs=pst.executeQuery();
while (rs.next()) {
String id = rs.getString("Patient_ID"); // Get the Id
String name = rs.getString("Name"); // Get the Name
ComboItem comboItem = new ComboItem(id, name); // Create a new ComboItem
chooser.addItem(comboItem); // Put it into the ComboBox
String tmp=comboItem.getid();
}
} catch (SQLException sqle) {
System.out.println(sqle);
}
}
This is from comboitem class that only returns the name and not the id
public String toString() {
return this.name ;
}
My question is how do I get the selecteditem so that this action can be performed I have no clue how to do this I have been trying all bunch of code for almost 2 hours
any help will be much appreciated
NB I am Java beginner
private void chooserPopupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
try{
String sql="select * from Patients_Details where Patient_ID=? ";
pst=conn.prepareStatement(sql);
rs=pst.executeQuery();
if(rs.next()){
String add1=rs.getString("Patient_ID");
txtpatientid.setText(add1);
String add2=rs.getString("Name");
txtname.setText(add2);
String add3=rs.getString("Age");
txtage.setText(add3);
String add4=rs.getString("Gender");
txtgender.setText(add4);
String add5=rs.getString("Date");
txtdate.setText(add5);
}
}
catch(Exception e) {
JOptionPane.showMessageDialog(null,e );
}
}
Simply add an ActionListener to the combo box. When actionPerformed is called, you can look up the selected value and call what ever methods you need to.
For example:
chooser.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Object selectedValue = chooser.getSelectedValue();
// carry on with what ever you need
}
});
Have a look at ...
How to write action listeners
How to use combo boxes
For more details
I want to post a question about something I wish to do particularly but have no idea how to approach this as I am new with JTables.
This is what I have atm:
But I would like to arrange the table like this:
So that under a particular date, all events that correspond to that date are shown rather than individually like have above.
Here are the related classed in question, I am not sure where and how to make the alternations to allow me to achieve the above.
public class DbUtils {
public static TableModel resultSetToTableModel(ResultSet rs) {
try {
ResultSetMetaData metaData = rs.getMetaData();
int numberOfColumns = metaData.getColumnCount();
Vector columnNames = new Vector();
for (int column=0; column < numberOfColumns; column++) {
columnNames.addElement(metaData.getColumnLabel(column + 1));
}
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;
}
}
}
public class EventModel {
public TableModel getTableData() {
TableModel model=null;
try {
String sql = "SELECT eventID as 'Event ID', date as 'Date',eventName as 'Name', time as 'Start Time' FROM Event";
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
model = (DbUtils.resultSetToTableModel(rs));
}
catch(SQLException e){
e.printStackTrace();
}
finally {
try {rs.close(); pst.close();}
catch(SQLException e){} }
return model;
}
public Events getEvent(String tableClick) {
try {
pst = conn.prepareStatement("SELECT * FROM Event WHERE eventID='"+tableClick+"' ");
rs = pst.executeQuery();
while(rs.next()){
e.setEventName(rs.getString(2));
e.setEventDate(rs.getString(3));
e.setEventTime(rs.getString(4));
e.setEventVenue(rs.getString(5));
e.setEventDetail(rs.getString(6));
e.setEventOpportunity(rs.getString(7));
e.setEventMoreDetails(rs.getString(8));
e.setEndTime(rs.getString(9));
}
}
catch(SQLException ex){
ex.printStackTrace();
} finally {
try {
rs.close();
pst.close();
} catch (Exception e) {
}
}
return e;
} //end getEvent
}
public class EventController {
private KeyAdapter keyAdapter = new KeyAdapter() {
#Override
public void keyReleased(java.awt.event.KeyEvent e) {
if((e.getKeyCode()==KeyEvent.VK_UP) || (e.getKeyCode()==KeyEvent.VK_DOWN)) {
changeEvent();
}
}
};
public void changeEvent() {
int rowSelected = view.tableEvent.getSelectedRow();
tableClick = view.tableEvent.getModel().getValueAt(view.tableEvent.convertRowIndexToModel(rowSelected), 0).toString();
events = model.getEvent(tableClick); //tell model to change its state based on user input on views
view.changeDisplay(events);
}
}
public class EventView {
public void changeDisplay(Events e) {
evTitle.setText(""+e.getEventName());
evWhen.setText("When: "+ e.getEventDate());
evWhere.setText("Where: "+ e.getEventVenue());
evDescription.setText(""+ e.getEventDetail());
evOpportunity.setText(""+ e.getEventOpportunity());
evMoreDet.setText(""+ e.getEventMoreDetails());
endTime.setText("End Time: "+e.getEndTime());
}
}
e is the object of the class Events which is just a bean.
You may be able to simply setAutoCreateRowSorter(true). Addendum: Because Date implements Comaprable, ensure that your TableModel returns type Date.class for the date column, as shown here. See also How to Use Tables: Sorting and Filtering.
A more elaborate approach would be to use a tree-table such as Outline, shown here. The top level(s) would be dates, and the leaves would be events.