JFrame,错误无法对非静态字段进行静态引用

JFrame, Error Cannot make a static reference of the non-static field

我正在尝试通过 SerialRead 方法设置数据变量,但我得到了 "Cannot make a static reference of the non-static field Etiqueta2",Eclipse 说我应该将 Etiqueta2 设为静态,但它没有在 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();
        }
    }
}

如何设置 Etiqueta2 标签上的文本以显示数据变量?

谢谢

EDIT3:我用swingworker更新了代码,执行和println在控制台看数据

SerialReaderFinal 的静态内部 class,因此无法访问 Final 中的任何非静态字段。由于您显然不在 Final 之外使用 SerialReader,只需将其设为非静态即可(甚至可以是私有内部 class)。同样适用于 SerialWriter.

SerialReader 声明为 static,因此它无法访问外部 Final class 的实例字段,因为可以创建 SerialReader 不需要先 Final 的实例。

相反,您应该将要更新的 JLabel 的引用传递给 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;
         //...

然后您将使用它从您的 运行 方法中进行更新。

您可以简单地使 class 成为非静态的,但这取决于您的需要

您遇到的另一个问题是 Swing 不是线程安全的,因此实际上不建议从 run 方法中对 JLabel 的实例调用 setText

通常,我建议使用 SwingWorker,因为它具有允许您从后台线程 publish 结果和事件上下文中 process 结果的方法调度线程,允许您安全地修改 UI 的状态,但在这种情况下,您可以使用 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();
        }            
    }

但您可能需要制作 data final,这可能会导致更多问题,在这种情况下,我会改用 SwingWorker

仔细查看 Worker Threads and SwingWorker 了解更多详情

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示例...

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 示例...

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
        }

    }
}