问题
I am trying to set the data variable from SerialRead method but I got "Cannot make a static reference of the non-static field Etiqueta2", Eclipse said that I should make Etiqueta2 static but it doesnt show the data in the Jlabel.
public class Final extends JFrame
{
//Crea Elementos de la interfaz
JLabel Etiqueta=new JLabel();
JTextField Texto=new JTextField();
JButton Boton=new JButton();
JLabel Etiqueta1=new JLabel();
JLabel Etiqueta2=new JLabel();
JButton Boton1=new JButton();
public Final()
{
super();
// Crea la interfaz
setVisible(true);
setLayout(null);
setTitle("Lectura y escritura de datos");
setSize(380,200);
//Propiedades de los elementos del Frame
// Etiqueta
Etiqueta.setBounds(20,50, 100, 20);
Etiqueta.setText("Enviar un digito");
add(Etiqueta);
// Caja de texto
Texto.setBounds(120,50,100, 20);
add(Texto);
// Boton
Boton.setBounds(250,50,100, 20);
Boton.setText("Enviar");
add(Boton);
// Etiqueta 1
Etiqueta1.setBounds(20,80, 100, 20);
Etiqueta1.setText("Leer un digito");
add(Etiqueta1);
// Etiqueta2
Etiqueta2.setBounds(120,80,100, 20);
add(Etiqueta2);
// Boton 1
Boton1.setBounds(250,80,100, 20);
Boton1.setText("Leer");
add(Boton1);
// Boton de cierre
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
void connect ( String portName ) throws Exception
{
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if ( portIdentifier.isCurrentlyOwned() )
{
System.out.println("Error: Port is currently in use");
}
else
{
CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);
if ( commPort instanceof SerialPort )
{
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
InputStream in = serialPort.getInputStream();
OutputStream out = serialPort.getOutputStream();
new SerialReader(in, Etiqueta2).execute();
(new Thread(new SerialWriter(out))).start();
}
else
{
System.out.println("Error: Only serial ports are handled by this example.");
}
}
}
/** */
public static class SerialReader extends SwingWorker<Void, String> { //Final frame = new Final();
private InputStream in;
private JLabel label;
public SerialReader(InputStream in, JLabel label) {
this.in = in;
this.label = label;
}
@Override
protected void process(List<String> chunks) {
String data = chunks.get(chunks.size() - 1);
label.setText(data);
}
@Override
protected Void doInBackground() throws Exception {
byte[] buffer = new byte[1024];
int len = -1;
while ((len = this.in.read(buffer)) > -1) {
String data = new String(buffer, 0, len);
System.out.println(data);
publish(data);
}
return null;
}
}
/** */
public static class SerialWriter implements Runnable
{
**** output code ****
}
public static void main ( String[] args )
{
try
{
(new Final()).connect("COM7");
}
catch ( Exception e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
What can I do to setText on the Etiqueta2 Label to show the data variable?
Thanks
EDIT3: I updated the code with the swingworker, execute and println to watch the data in the console
回答1:
SerialReader is declared as static, therefore it can not access the instance fields of the outer Final class, as it's possible to create an instance of SerialReader without needing an instance of Final first.
Instead, you should pass a reference of the JLabel you want to update to the SerialReader class
public static class SerialReader implements Runnable
{ //Final frame = new Final();
InputStream in;
private JLabel label;
public SerialReader ( InputStream in, JLabel label ) {
this.label = label;
//...
Then you would use this to update from within your run method.
You could simply make the class non-static, but that comes down to your needs
The other problem you have is Swing is not thread safe, so it's actually unadvisable to call setText on the instance of JLabel from within the run method.
Typically, I'd recommend using a SwingWorker, as it has methods that allow you to publish results from the background thread and process them within the context of the Event Dispatching Thread, allowing you to safely modify the state of the UI, but in this case, you could use SwingUtilities.invokeLater
public void run ()
{
//...
try
{
while ( ( len = this.in.read(buffer)) > -1 )
{
//...
SwingUtiltiies.invokeLater(new Runnable() {
public void run() {
Etiqueta2.setText(data);
}
});
}
}
catch ( IOException e )
{
e.printStackTrace();
}
}
But you may need to make data final, which could cause more issues, which in that case, I'd just use a SwingWorker instead.
Take a closer look at Worker Threads and SwingWorker for more details
SwingWorker Example...
public static class SerialReader extends SwingWorker<Void, String> { //Final frame = new Final();
private InputStream in;
private JLabel label;
public SerialReader(InputStream in, JLabel label) {
this.in = in;
this.label = label;
}
@Override
protected void process(List<String> chunks) {
String data = chunks.get(chunks.size() - 1);
label.setText(data);
}
@Override
protected Void doInBackground() throws Exception {
byte[] buffer = new byte[1024];
int len = -1;
while ((len = this.in.read(buffer)) > -1) {
String data = new String(buffer, 0, len);
publish(data);
}
return null;
}
}
Runnable SwingWorker example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JLabel label;
public TestPane() {
setLayout(new GridBagLayout());
label = new JLabel("...");
add(label);
new ClockWorker(label).execute();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public static class ClockWorker extends SwingWorker<Void, String> {
protected static final DateFormat DF = new SimpleDateFormat("hh:mm.ss SSS a");
private JLabel label;
public ClockWorker(JLabel label) {
this.label = label;
}
@Override
protected void process(List<String> chunks) {
label.setText(chunks.get(chunks.size() - 1));
}
@Override
protected Void doInBackground() throws Exception {
while (true) {
publish(DF.format(new Date()));
Thread.sleep(1);
}
}
}
}
"Faked" InputStream example...
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
public class Final extends JFrame {
//Crea Elementos de la interfaz
JLabel Etiqueta = new JLabel();
JTextField Texto = new JTextField();
JButton Boton = new JButton();
JLabel Etiqueta1 = new JLabel();
JLabel Etiqueta2 = new JLabel("Banana");
JButton Boton1 = new JButton();
public Final() {
super();
// Crea la interfaz
setVisible(true);
setLayout(null);
setTitle("Lectura y escritura de datos");
setSize(380, 200);
//Propiedades de los elementos del Frame
// Etiqueta
Etiqueta.setBounds(20, 50, 100, 20);
Etiqueta.setText("Enviar un digito");
add(Etiqueta);
// Caja de texto
Texto.setBounds(120, 50, 100, 20);
add(Texto);
// Boton
Boton.setBounds(250, 50, 100, 20);
Boton.setText("Enviar");
add(Boton);
// Etiqueta 1
Etiqueta1.setBounds(20, 80, 100, 20);
Etiqueta1.setText("Leer un digito");
add(Etiqueta1);
// Etiqueta2
Etiqueta2.setBounds(120, 80, 100, 20);
add(Etiqueta2);
// Boton 1
Boton1.setBounds(250, 80, 100, 20);
Boton1.setText("Leer");
add(Boton1);
// Boton de cierre
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
void connect(String portName) throws Exception {
System.out.println("...");
new SerialReader(new FakeInputStream(), Etiqueta2).execute();
// CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
// if (portIdentifier.isCurrentlyOwned()) {
// System.out.println("Error: Port is currently in use");
// } else {
// CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
//
// if (commPort instanceof SerialPort) {
// SerialPort serialPort = (SerialPort) commPort;
// serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
//
// InputStream in = serialPort.getInputStream();
// OutputStream out = serialPort.getOutputStream();
//
// new SerialReader(in, Etiqueta2).execute();
// (new Thread(new SerialWriter(out))).start();
//
// } else {
// System.out.println("Error: Only serial ports are handled by this example.");
// }
// }
}
/**
*
*/
public static class SerialReader extends SwingWorker<Void, String> {
private InputStream in;
private JLabel label;
public SerialReader(InputStream in, JLabel label) {
this.in = in;
this.label = label;
}
@Override
protected void process(List<String> chunks) {
String data = chunks.get(chunks.size() - 1);
label.setText(data);
}
@Override
protected Void doInBackground() throws Exception {
byte[] buffer = new byte[1024];
int len = -1;
while ((len = this.in.read(buffer)) > -1) {
String data = new String(buffer, 0, len);
System.out.println(data);
publish(data);
}
return null;
}
@Override
protected void done() {
try {
get();
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
(new Final()).connect("COM7");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static class FakeInputStream extends InputStream {
private Random rnd = new Random();
@Override
public int read() throws IOException {
return 33 + rnd.nextInt(125-33); // Ascii characters
}
}
}
回答2:
SerialReader is a static inner class of Final and due to this can't access any non-static fields in Final. Since you apparently don't use SerialReader outside of Final just make it non-static (could even be a private inner class). Same applies for SerialWriter.
来源:https://stackoverflow.com/questions/29761883/jframe-error-cannot-make-a-static-reference-of-the-non-static-field