JFrame中,错误无法使非静态字段的静态参考(JFrame, Error Cannot make

2019-10-22 18:30发布

我想设置从SerialRead方法的数据变量,但我得到了“不能让非静态场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();
        }
    }
}

我能做些什么来的setText在Etiqueta2标签来显示数据变量?

谢谢

EDIT3:我更新了SwingWorker类的代码,执行和println看在控制台中的数据

Answer 1:

SerialReader被声明为static ,因此它不能访问外部的实例字段Final类,因为它可以创建的实例SerialReader无需实例Final第一。

相反,你应该通过一个参考JLabel要更新到SerialReader

public static class SerialReader implements Runnable 
{   //Final frame = new Final();

    InputStream in;
    private JLabel label;

    public SerialReader ( InputStream in, JLabel label ) {
         this.label = label;
         //...

那么你可以使用这个从你的run方法中进行更新。

你可以简单地使类非静态的,但归结到您的需要

你有另一个问题是Swing不是线程安全的,所以它实际上是不妥当的呼叫setText对实例JLabel从内run方法。

通常情况下,我建议你使用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代替。

就拿仔细看看工作线程和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;
    }
}

Runnable接口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);
            }
        }

    }

}

“伪造” 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
        }

    }
}


Answer 2:

SerialReader是一个静态内部类的Final ,并且由于这不能访问任何非静态字段Final 。 既然你显然不使用SerialReader之外的Final只是让非静态的(甚至可以是一个私有内部类)。 这同样适用于SerialWriter



文章来源: JFrame, Error Cannot make a static reference of the non-static field