Hello I I´m a very newbie in Java and I´m trying to write a very simple excercise to practice, I created a Jclass to read the parameter from a DB and save it in a variable called "estado" and a JFrame to show the value of this variable who is changing randomly in DB.
The program read a MySql DB and store the data needed in a Java variable like these class:
package Paquete_domotica;
import java.io.*;
import java.sql.*;
public class domotica {
public static int estado;
boolean loop = true;
public domotica() throws IOException
{
while(loop)
{
try
{
DriverManager.registerDriver(new org.gjt.mm.mysql.Driver());
Connection conexion = DriverManager.getConnection (
"jdbc:mysql://localhost/XXX","XXXX", "XXXX");
Statement s = conexion.createStatement();
ResultSet rs = s.executeQuery ("select id, nombre, valor from data");
while (rs.next())
{
if (rs.getInt ("id") == 20)
{
estado = rs.getInt ("valor");
}
}
rs.close();
conexion.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
}
The variable stored is called "estado", these variable is 1 or 0 and I´m trying that every change of these variable make a change of the value of jTextField1 in the following Jframe:
package Paquete_domotica;
import java.awt.event.ActionListener;
import java.io.IOException;
public class JFramedomotica extends javax.swing.JFrame {
int numeroRecibido;
public JFramedomotica() {
initComponents();
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jTextField1 = new javax.swing.JTextField();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jTextField1.setHorizontalAlignment(javax.swing.JTextField.CENTER);
jTextField1.setText("SIN DATOS");
jTextField1.setCursor(new java.awt.Cursor(java.awt.Cursor.TEXT_CURSOR));
jTextField1.setEnabled(false);
jTextField1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jTextField1MouseClicked(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(110, 110, 110)
.addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 136, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(154, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(138, 138, 138)
.addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(142, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
private void jTextField1MouseClicked(java.awt.event.MouseEvent evt) {
jTextField1.setText(String.valueOf(domotica.estado));
}
public static void main(String args[]) throws IOException {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
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(JFramedomotica.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(JFramedomotica.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(JFramedomotica.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(JFramedomotica.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new JFramedomotica().setVisible(true);
}
});
new domotica();
}
// Variables declaration - do not modify
private javax.swing.JTextField jTextField1;
// End of variables declaration
}
As you can see now I can update the jTextField1 with
private void jTextField1MouseClicked(java.awt.event.MouseEvent evt) {
jTextField1.setText(String.valueOf(domotica.estado));
}
But with this code I have to click mouse to refresh the jTextField1, I don´t know how to update jTextField1 at every change of "estado".
There's a great deal wrong with your code, so much so that it's easier so give you a clean example of how this can be done.
The key to solving this problem is to seperate the polling and UI then introduce an event mechanism to notify the UI of changes detected by the poller.
You've got the first concept correct, however you really don't want the calling thread to loop forever as is the case with your
domotica
class. You want the class to hide the polling from you and fire events when the data changes like this:Notice the
PollerThread
and how it's handling the JDBC resources. Firstly it's got a sleep to avoid hogging the CPU. Secondly, repeatidly openning and closing connections as in your example is likely to upset your DBA. It's far better to use ajavax.sql.DataSource
and obtain the resources outside of the loop.The Poller class can then be instantiated and passed to the applications main frame as follows, using the window closing to stop the polling:
That's almost it.
The final piece is for the
MainFrame
to listen for events from thePoller
and updated the UI. The important thing here is that the update should be performed on the Event Dispatch Thread like this:And that's about it. This example should give you the gist, it's missing the necessary exception handling,
null
checks, etc but that should be easy enough to add in.You have a lot painful code that is hard where to begin, you are using a
public static estado
variable, that is a very bad design in OOP. Swing is an event based system. So let's see some tipswhile(true)
blocks your gui make it irresponsive. If you want repetition you can use Swing Timer. Note that the Swing timer's task is performed in the event dispatch thread. This means that the task can safely manipulate components, but it also means that the task should execute quickly. If the task might take a while to execute, then consider using a SwingWorker instead of or in addition to the timer.Observer Pattern
for example usingPropertyChangeListener
andPropertyChangeSupport
to update your JTextField.Example using
SwingWorker
.Then in your
JFrame
you can do this.