JFrame,错误无法对非静态字段进行静态引用 [英] JFrame, Error Cannot make a static reference of the non-static field

查看:114
本文介绍了JFrame,错误无法对非静态字段进行静态引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从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 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆