JFrame,错误无法对非静态字段进行静态引用 [英] JFrame, Error Cannot make a static reference of the non-static field
问题描述
我正在尝试从SerialRead方法设置数据变量,但是得到了无法对非静态字段Etiqueta2进行静态引用,Eclipse表示我应该使Etiqueta2静态,但它不会在Jlabel中显示数据。
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();
}
}
}
我该怎么办setText在Etiqueta2标签上显示数据变量?
What can I do to setText on the Etiqueta2 Label to show the data variable?
谢谢
EDIT3:我使用swingworker更新了代码,执行并执行println以查看控制台中的数据
I updated the code with the swingworker, execute and println to watch the data in the console
推荐答案
SerialReader
被声明为 static
,因此它无法访问外部 Final
的实例字段类,因为可以先创建 SerialReader
的实例,而不必先创建 Final
的实例。
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.
相反,您应该传递要更新为 SerialReader $ c的
JLabel
的引用$ c> class
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
另一个您遇到的问题是Swing不是线程安全的,因此实际上不建议在内部从 JLabel
实例调用 setText
run
方法。
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.
通常,我建议使用 SwingWorker
,因为它具有允许您发布
来自后台线程的结果并处理
的方法。事件调度线程的上下文,允许您安全地修改UI的状态,但是在这种情况下,可以使用 SwingUtilities.invokeLater
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();
}
}
但是您可能需要使数据
最终
,这可能会导致更多问题,在这种情况下,我只使用 SwingWorker
But you may need to make data
final
, which could cause more issues, which in that case, I'd just use a SwingWorker
instead.
仔细查看工作线程和SwingWorker 了解详情
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;
}
}
可运行 SwingWorker
示例...
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
示例...
"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
}
}
}
这篇关于JFrame,错误无法对非静态字段进行静态引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!