如何在 Java 中更新使用 NetBeans 图形 GUI 设计器创建的文本字段

How to update Text Field created with NetBeans graphical GUI designer in Java

几十年来我一直在编写嵌入式 C 代码,我希望通过学习 Java 来更新我的技能。

我还需要一个项目的图形测试工具(读取串口、处理数据、根据 GUI 按钮选择将结果写入串口等)

我正在尝试使用 NetBeans 图形 GUI 设计器来创建 GUI,然后添加 Java 代码来实现逻辑,但我仍在学习 Java 所以我不确定如何从 Java 代码访问我的 GUI 中的文本字段。具体来说,我想要一个屏幕上的文本框,它每秒更新一次当前时间(这最终将成为一个健康检查路由,寻找错过的命令超时等)。

我遇到的问题是如何从我的 healthCheck() 例程访问名为 timeDisplayField 的文本字段对象。 healthCheck() 例程每秒都会被调用一次,但是当我取消注释任何试图访问 timeDisplayField 对象的尝试时,我要么得到一个编译错误,要么得到一个 NullPointer 运行 时间错误。

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package myPackage;

import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Date;

/**
 *
 * @author SGrunza
 */


public class mainWindow extends javax.swing.JFrame {

    /**
     * Creates new form mainWindow
     */



        public void healthCheck()
{
    Calendar    now = Calendar.getInstance();
    int         hour = now.get( Calendar.HOUR_OF_DAY );
    int         minute = now.get( Calendar.MINUTE );
    int         second = now.get( Calendar.SECOND );

    String      timeString = new String();

    //System.out.printf("%02d:%02d:%02d\r\n", hour, minute, second );

    timeString = timeString.format( "%02d:%02d:%02d\r\n", hour, minute, second );
    timeDisplayField.setText( timeString );
}

    public mainWindow() 
    {
        Timer       healthTimer = new Timer();

        healthTimer.scheduleAtFixedRate( new TimerTask()
                {
                    @Override 
                    public void run()
                {
                    //System.out.println( "healthTask " + new Date() +
                    //        "Thread name: " + Thread.currentThread().getName() );
                    healthCheck();
                }
                },
                0,  // delay until first run
                1000 ); // delay for each subsequent run


        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        interfaceTypeGroup = new javax.swing.ButtonGroup();
        jPanel1 = new javax.swing.JPanel();
        nfcButton = new javax.swing.JRadioButton();
        smipButton = new javax.swing.JRadioButton();
        serialButton = new javax.swing.JRadioButton();
        appStatusField = new javax.swing.JTextField();
        msgField = new javax.swing.JTextField();
        cardReaderStatusField = new javax.swing.JTextField();
        timeDisplayField = new javax.swing.JTextField();
        activateButton = new javax.swing.JButton();
        readButton = new javax.swing.JButton();
        deactivateButton = new javax.swing.JButton();
        checkSleepButton = new javax.swing.JButton();
        getInfoButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        interfaceTypeGroup.add(nfcButton);
        nfcButton.setSelected(true);
        nfcButton.setText("NFC");

        interfaceTypeGroup.add(smipButton);
        smipButton.setForeground(new java.awt.Color(153, 153, 153));
        smipButton.setText("SMIP");

        interfaceTypeGroup.add(serialButton);
        serialButton.setForeground(new java.awt.Color(153, 153, 153));
        serialButton.setText("Serial");

        appStatusField.setText("appStatus");

        msgField.setText("msgWindow");

        cardReaderStatusField.setText("cardReader_status");

        timeDisplayField.setText("timeDisplay");

        activateButton.setLabel("Activate");

        readButton.setText("Read Sensor");

        deactivateButton.setText("Deactivate");

        checkSleepButton.setText("Check Sleep");

        getInfoButton.setText("Get Info");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(msgField)
                    .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addComponent(activateButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(deactivateButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(readButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(getInfoButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addContainerGap())
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(checkSleepButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGap(12, 12, 12))))
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGap(12, 12, 12)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(nfcButton)
                            .addComponent(smipButton)
                            .addComponent(serialButton))
                        .addGap(18, 18, 18)
                        .addComponent(cardReaderStatusField))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGap(12, 12, 12)
                        .addComponent(appStatusField, javax.swing.GroupLayout.PREFERRED_SIZE, 203, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 564, Short.MAX_VALUE)
                        .addComponent(timeDisplayField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addGap(12, 12, 12))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(nfcButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(smipButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(serialButton))
                    .addComponent(cardReaderStatusField))
                .addGap(18, 18, 18)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(timeDisplayField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(appStatusField, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(activateButton)
                    .addComponent(getInfoButton))
                .addGap(18, 18, 18)
                .addComponent(readButton)
                .addGap(18, 18, 18)
                .addComponent(deactivateButton)
                .addGap(37, 37, 37)
                .addComponent(checkSleepButton)
                .addGap(18, 18, 18)
                .addComponent(msgField, javax.swing.GroupLayout.DEFAULT_SIZE, 217, Short.MAX_VALUE)
                .addContainerGap())
        );

        timeDisplayField.getAccessibleContext().setAccessibleName("timeDisplayField");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(mainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(mainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(mainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(mainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new mainWindow().setVisible(true);
            }
        });
    }


    // Variables declaration - do not modify//GEN-BEGIN:variables
    public javax.swing.JButton activateButton;
    public javax.swing.JTextField appStatusField;
    public javax.swing.JTextField cardReaderStatusField;
    public javax.swing.JButton checkSleepButton;
    public javax.swing.JButton deactivateButton;
    public javax.swing.JButton getInfoButton;
    public javax.swing.ButtonGroup interfaceTypeGroup;
    public javax.swing.JPanel jPanel1;
    public javax.swing.JTextField msgField;
    public javax.swing.JRadioButton nfcButton;
    public javax.swing.JButton readButton;
    public javax.swing.JRadioButton serialButton;
    public javax.swing.JRadioButton smipButton;
    public javax.swing.JTextField timeDisplayField;
    // End of variables declaration//GEN-END:variables
}

我是 Java 的新手,所以我不确定到哪里寻求帮助。我怀疑部分问题在于使用 NetBeans GUI 构建器,但我真的不想手动构建所有 GUI。

将其归结为一个简单的问题:如何更改 healthCheck() 以便它更新屏幕上的文本字段?

答案在What is a NullPointerException and how do i fix it. 你可以在stacktrace中看到它(错误):

Exception in thread "Timer-0" java.lang.NullPointerException
    at rae.mainWindow.healthCheck(mainWindow.java:24)
    at rae.mainWindow.run(mainWindow.java:35)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)

在第 24 行,你有这一行:

timeDisplayField.setText(timeString);

timeString 不是 null 这意味着 timeDisplayFieldnull。那是因为您首先启动计时器,然后调用创建文本字段的 initComponents 方法:

public mainWindow() {
    Timer healthTimer = new Timer();

    healthTimer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            // System.out.println( "healthTask " + new Date() +
            // "Thread name: " + Thread.currentThread().getName() );
            healthCheck();
        }
    }, 0, // delay until first run
            1000); // delay for each subsequent run

    initComponents(); //here
}

您可以通过在时间初始化之前调用 initComponents 来修复它:

public mainWindow() {
    Timer healthTimer = new Timer();

    initComponents(); //Before timer

    healthTimer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            // System.out.println( "healthTask " + new Date() +
            // "Thread name: " + Thread.currentThread().getName() );
            healthCheck();
        }
    }, 0, // delay until first run
            1000); // delay for each subsequent run

}

但是,不建议在 Swing 环境中使用 java.util.Timer。考虑将其更改为 Swing Timer which is created for such cases. A good example of its usage can be found in