I have below SwingWorker;
public class WorkerTrying extends SwingWorker<Void, Void> {
Statement stmt;
Connection con;
ResultSet rs;
String connectionUrl = "jdbc:sqlserver://192.168.131.10;" + "databaseName=SomeDB;" + "user=" + "SomeUser" + ";" + "password=" + "SomeUserPassword" + ";";
public void closeConnection() throws SQLException{
stmt.close();
System.out.println("Closed!!!");
}
protected Void doInBackground() throws Exception {
String query = "Select column1,column2 from Table1"
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
con = DriverManager.getConnection(connectionUrl);
stmt = con.createStatement();
rs = stmt.executeQuery(query);
while (rs.next()){
//Doing something...
}
return null;
}
public void done() {
}
}
As you can see some DB connection and data fetchinbg via While loop in this worker. My problem is DB Queries takes very long time sometimes. I want add STOP button for closing Statements and Connections in SwingWorker and cancel immediatelly itself.
I am trying below stop button but no help;
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
WorkerTrying workerTrying = new WorkerTrying();
workerTrying.cancel(true);
}
Also i have 3-4 SwingWorkers. So i must detect which one is currently running first.
Regards.
==== UPDATE ====
New Stop button like this;
jButtonStop.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
for(SwingWorker workerTrying : _workers){
if(!workerTrying.isDone()){
try {
((WorkerTrying)workerTrying).closeConnection();
} catch (SQLException ex) {
Logger.getLogger(MainGui.class.getName()).log(Level.SEVERE, null, ex);
}
workerTrying.cancel(true);
}
}
}
}
});
==== SECOND ISSUE UPDATE ====
Start button Action Listener just like this;
startButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
if(jTextField1.getText().equals("")){
final SwingWorker workerTrying = new WorkerTrying();
_workers.add(workerTrying);
workerTrying.execute();
}
else{
final SwingWorker workerTrying2 = new WorkerTrying2();
_workers.add(workerTrying2);
workerTrying2.execute();
}
}
});
As you can see some condition for which SwingWorker can be execute.
Than Stop button just like this;
stopButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
for (SwingWorker workerTrying : _workers) {
if(!workerTrying.isDone()){
try {
((WorkerTrying)workerTrying).closeConnection();
} catch (SQLException ex) {
Logger.getLogger(MainGui.class.getName()).log(Level.SEVERE, null, ex);
}
workerTrying.cancel(true);
}
}
for (SwingWorker workerTrying2 : _workers) {
if(!workerTrying2.isDone()){
try {
((WorkerTrying2)workerTrying2).closeConnection();
} catch (SQLException ex) {
Logger.getLogger(MainGui.class.getName()).log(Level.SEVERE, null, ex);
}
workerTrying2.cancel(true);
}
}
}
});
If First SwingWorker (workerTrying) executed and try stopping, everythings looks ok. Statement closed and SwingWorker canceled succesfully.
But when second SwingWorker (workerTrying2) executed and wanted to Stop, below exception throwed;
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: testproject.MainGui$WorkerTrying2 cannot be cast to testproject.MainGui$WorkerTrying
I used List to track all the Workers. And stopped it all. You can try this.
public class SwingT {
private List<SwingWorker> _workers = new ArrayList<>();
public SwingT(){
JFrame frame = new JFrame("Test Worker");
frame.setSize(320, 160);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
JButton btn = new JButton("Add Work");
btn.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
SwingWorker workerTrying = new WorkerTrying();
_workers.add(workerTrying);
workerTrying.execute();
}
});
JButton btn2 = new JButton("Stop All");
btn2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
for(SwingWorker workerTrying : _workers){
if(!workerTrying.isDone()){
//Close DB Connections
((WorkerTrying)workerTrying).closeConnection();
workerTrying.cancel(true);
}
}
}
});
frame.add(btn);
frame.add(btn2);
frame.setVisible(true);
}
/**
* #param args
*/
public static void main(String[] args) {
new SwingT();
}
}
UPDATE
public class WorkerTrying extends SwingWorker<Void, Void> {
public void closeConnection(){
//Close the connection
System.out.println("closed");
}
..........
}
Related
I developed a program to learn how log-in works. I've got a window(jFrame) where you can login with a button on it "create new account". If you click this butten, the login window closes and the create acc. window(another file) opens up. I want it to reopen the login window after you've created your acc.
My Problem:
I don't know how to reopen the login window. Be it by restarting the mainmethod or somethingelse, which you guys can tell me hopefully .
First window
public class password extends javax.swing.JFrame {
public password() {
initComponents();
}
private void initComponents() {
jButton1 = new javax.swing.JButton();
[some more Elements...]
jButton1.setText("Create an account");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
[more layoutstuff...]
}
//event where it opens the new window and closes the login window
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
register reg = new register();
reg.register();
dispose();
}
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(password.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(password.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(password.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(password.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new password().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
[more elements...]
}
second window
public class register extends javax.swing.JFrame {
public register() {
initComponents();
}
private void initComponents() {
jTextField1 = new javax.swing.JTextField();
[again more elements and layoutstuff...]
}
public static void register() {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new register().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
[more elements]
}
Please excuse me for my question but I am very new to programming.
You could just hide and then show the login window later or you could roll up a new login window.
i have written a java application with tables and functions like add,delete or update.
My problem is, that I delete a row in the table and it is deleted in the database, but when I click on a free space of my JTable the deleted row appears again?
here my code:
DAO CLASS
#Override
public void delete(int id) throws SQLException {
handle = new DatabaseHandler();
con = handle.buildConnectionToServer();
query = "DELETE FROM Team WHERE TID="+id;
std = con.createStatement();
std.execute(query);
con.commit();
handle.closeConnection();
}
CONTROLLER
//ActionListener "Delete" Button in "DeleteEquipment"
public void controllActionListenerDeleteEquipmentSubmit(){
main.setActionListenerDeleteEquipmentSubmit(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
if(arg0.getSource()==main.getDeleteEquipment()){
EquipmentDAO equipment = new EquipmentDAO ();
int a = (int)main.getDeleteEquipmentPanel().getDeleteValues().getValueAt(main.getDeleteValues().getSelectedRow(),0);
try {
equipment.delete(a);
JOptionPane.showMessageDialog(null, "Successfully Deleted");
equipmentArr = equipment.show();
main.getDeleteEquipmentPanel().showAllDelete(equipmentArr);
equipmentArr=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
});
}
MAINFRAME
//Back Button of "DeleteEquipment" to "ManageEquipment"
public void setActionListenerBackDeleteEquipment(ActionListener actionListener) {
deleteEquipment.getDeleteEquipmentBack().addActionListener(actionListener);
}
public JButton getDeleteEquipmentBack(){
return deleteEquipment.getDeleteEquipmentBack();
}
//Delete Button in DeleteEquipment
public void setActionListenerDeleteEquipmentSubmit(ActionListener actionListener) {
deleteEquipment.getDeleteEquipment().addActionListener(actionListener);
}
public JButton getDeleteEquipment(){
return deleteEquipment.getDeleteEquipment();
}
I'm having a problem with GUI. When I click on JButton b1, when the text is empty in the JTextField text it does not catch the exception.
The query is executing only once when the button is clicked,if clicked again it throws exception and query is not executing
Code:
public class A extends JFrame{
private JTextField text;
private JButton b1;
private JLabel l1;
private Connection conn;
private Statement state;
private ResultSet set;
String server = "jdbc:mysql://localhost";
String user="tim";
String pass="u";
//query enter in textfield | select * from universty.student where rollno=2
public A() throws ClassNotFoundException, SQLException{
super("Frame");
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(server,user,pass);
state = conn.createStatement();
getContentPane().setLayout(null);
text = new JTextField();
text.setBounds(35, 132, 346, 35);
getContentPane().add(text);
l1= new JLabel();
l1.setFont(new Font("Tahoma", Font.PLAIN, 22));
l1.setBounds(35, 305, 384, 27);
getContentPane().add(l1);
b1 = new JButton("Submit");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try{
String query = text.getText();
set = state.executeQuery(query);
set.next();
String answer = set.getString(2);
l1.setText(answer);
}
catch (Exception e){
JOptionPane.showMessageDialog( null,
e.getMessage(), "Database error",
JOptionPane.ERROR_MESSAGE );
return;
}
finally{
try{
set.close();
state.close();
conn.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}});
b1.setBounds(132, 178, 129, 35);
getContentPane().add(b1);
setSize(450,450);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
}
}
Main Method:
public class Main {
public static void main(String args[]) throws ClassNotFoundException, SQLException{
A obj = new A();
}
}
You should open and close the database connection within your:
actionPerformed()
Since when you call your constructor it opens the db connection and closes it again. When you click the db connection is already closed again
public void actionPerformed(ActionEvent arg0) {
conn = DriverManager.getConnection(server,user,pass);
state = conn.createStatement();
//do query here
set.close();
state.close()
conn.close();
}
At the end of the first click, you close everything with following statement.
finally{
try{
set.close();
state.close();
conn.close();
That's why.
__UPDATE__
I am asked to provide a solution. Actually I have given half of the solution by pin-pointing the problem. But let me elaborate more, since I am asked.
Simple solution is not to close connection or statement or whatever. But this would be a bad solution, as unnecessary resources could be hold active. No need for that.
I do not know your application. So I can not give you a precise answer but rather, I can give you some guide lines and help you find the right answer by yourself.
Hold on to the resources, as long as you need them. And get rid of them as soon as you are done with them. For this case, If it is required user to click on that button and make a change in the database, then do not close connection etc but reuse them. If it is a multi-page application, you can close these resource when user moves to another page. (or activity if it a mobile app).
I hope it makes sense =]
I'm not sure of the purpose of your code but you should try and separate your view logic from your business logic. Also allowing a user to run SQL from a text box and submit button sounds dangerous, but if that's really what you want to do, here is one implementation you could use. Note the DAO here is not a true DAO because of the way you want to execute a query
public class A extends JFrame {
private final JTextField text;
private final JButton b1;
private final JLabel l1;
private AService service;
public A() {
super("Frame");
service = new AServiceImpl(new ADAOJDBCImpl());
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
text = new JTextField();
text.setBounds(35, 132, 346, 35);
getContentPane().add(text);
l1= new JLabel();
l1.setFont(new Font("Tahoma", Font.PLAIN, 22));
l1.setBounds(35, 305, 384, 27);
getContentPane().add(l1);
b1 = new JButton("Submit");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String query = text.getText();
try {
String answer = service.executeQuery(query);
l1.setText(answer);
} catch (SQLException e){
JOptionPane.showMessageDialog( null,
e.getMessage(), "Database error",
JOptionPane.ERROR_MESSAGE );
return;
}
}});
b1.setBounds(132, 178, 129, 35);
getContentPane().add(b1);
setSize(450,450);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
pack();
setVisible(true);
}
}
public interface AService {
public String executeQuery(String query) throws SQLException;
}
public class AServiceImpl implements AService {
private ADAO dao;
public AServiceImpl(ADAO dao) {
this.dao = doa;
}
#Override
public String executeQuery(String query) throws SQLException {
return dao.executeQuery();
}
}
/**
* Note usually a DAO is specfically for accessing data, NOT
* for executing User defined queries from a GUI text box
* so it would usually have methods such as add, find, delete, update etc.
*/
public interface ADAO {
public String executeQuery(String query) throws SQLException;
}
public class ADAOJDBCImpl implements ADAO {
#Override
public String executeQuery(String query) throws SQLException {
String server = "jdbc:mysql://localhost";
String user="tim";
String pass="u";
String answer = "":
try (Connection conn = DriverManager.getConnection(server,user,pass);
Statement state = conn.createStatement();
ResultSet set = state.executeQuery(query);) {
if(set.next()) {
answer = set.getString(2);
}
}
return answer;
}
}
I'm trying to figure out why the text field isn't updating. I'm aware that using SwingWorker will probably fix this problem, but I can't understand why it doesn't work in the first place.
public class waitExample {
private JFrame frame;
private JTextField txtLeadingText;
private String one = "update string 1";
private String two = "update string 2";
private String three = "update string 3";
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
waitExample window = new waitExample();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public waitExample() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
txtLeadingText = new JTextField();
txtLeadingText.setHorizontalAlignment(SwingConstants.CENTER);
txtLeadingText.setText("leading text");
frame.getContentPane().add(txtLeadingText, BorderLayout.SOUTH);
txtLeadingText.setColumns(10);
JButton btnClickMeTo = new JButton("CLICK ME TO UPDATE TEXT");
btnClickMeTo.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
try {
updateOne();
Thread.sleep(1000);
updateTwo();
Thread.sleep(1000);
updateThree();
Thread.sleep(1000);
updateLast();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
frame.getContentPane().add(btnClickMeTo, BorderLayout.CENTER);
}
private void updateOne() {
txtLeadingText.setText(one);
}
private void updateTwo() {
txtLeadingText.setText(two);
}
private void updateThree() {
txtLeadingText.setText(three);
}
private void updateLast() {
txtLeadingText.setText("default text");
}
}
From what I understand, the default Thread will prevent any GUI updates. That shouldn't matter because I am setting the textField BEFORE the Thread.sleep.
Why doesn't the text field update? Shouldn't the text be set, then the Thread wait?
EDIT: As per the answers, the above code has been updated.
You are invoking Thread.sleep(1000); on EDT. This means that when your method will end - only then the repaint() will fire (at some point in time later).
Until then your GUI is freezed.
Consider that this is going on one thread (so processing is straightforward):
txtLeadingText.setText(one);
Thread.sleep(1000);
txtLeadingText.setText(two);
Thread.sleep(1000);
txtLeadingText.setText(three);
Thread.sleep(1000);
...
<returning from updateText()>
<processing other events on button click>
...
// some time later
<Swing finds out that GUI needs repaint: calls rapaint()>
This is what you should do (I didn't compile or test it):
public class MyRunnable implements Runnable {
private List<String> strsToSet;
public MyRunnable(List<String> strsToSet) {
this.strsToSet = strsToSet;
}
#Override
public void run() {
try {
if(strsToSet.size() > 0) {
final String str = strsToSet.get(0);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
txtLeadingText.setText(str);
}
});
Thread.sleep(1000);
List<String> newList = new LinkedList<String>(strsToSet);
newList.remove(0);
new Thread(new MyRunnable(newList)).start();
}
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
new Thread(new MyRunnable(Arrays.asList(one, two, three))).start();
It is hard to do in Swing but in contrast in dynamically languages (like Groovy) it would go as simple as that (you'll get a better grasp of what is going on):
edt {
textField.setText(one)
doOutside {
Thread.sleep(1000);
edt {
textField.setText(two)
doOutside {
Thread.sleep(1000);
edt {
textField.setText(three)
}
}
}
}
}
The GUI event loop updates the screen, but it can't update the screen until you return.
I suggest you avoid doing any blocking operations in the GUI event thread.
How can I pass a SQL connection to a Action Listener. I want to have an infinite loop, that sleeps for 100ms. Every iteration the loop is suppose to query a database. Is swing timer the best way to do this? If so how can I pass the connection to the Action Listener. If not, can someone please advise on how this can be done. Much thanks.
Code:
public static void main(String[] args) throws InterruptedException {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
AdminManager frame = new AdminManager();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
BoneCP connectionPool = null;
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e) {
e.printStackTrace();
return;
}
try {
// setup the connection pool
BoneCPConfig config = new BoneCPConfig();
config.setJdbcUrl("jdbc:mysql://192.162.0.0");
config.setUsername("root");
config.setPassword("");
connectionPool = new BoneCP(config); // setup the connection pool
connection = connectionPool.getConnection(); // fetch a connection
if (connection != null){
System.out.println("Connection successful!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// Define listner
ActionListener taskPerformer = new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
String sql = "SELECT * table;";
Statement st = connection.createStatement();
ResultSet rs = st.executeQuery(sql);
while(rs.next()) {
String symbol = rs.getString("name");
System.out.println(symbol);
}
}
};
Timer timer = new Timer( 100 , taskPerformer);
timer.setRepeats(true);
timer.start();
Thread.sleep(1000);
//connectionPool.shutdown(); // shutdown connection pool.
}
Do not the javax.swing.Timer class to periodically execute a non-Swing task. Instead, use a ScheduleExecutorService,
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.schedule(new Runnable(){
#Override
public void run(){
// query database
}
}, 0, 100, TimeUnit.MILLISECONDS);
If the background task must continually update a Swing component, use SwingWorker to process() periodic updates to the component's model. In this example, a JTextArea is updated with data obtained from an H2 database.