简体   繁体   中英

Swing GUI not updating

I'm writing an application that reads in audio, analyses this data and then displays the results in realtime. Currently I am using a SwingWorker to run the loop that initiates the background analysis and calling the SwingUtilities.invokeLater method inside the loop to update the GUI components each time analysis has completed. At the moment, the GUI seems to be updating randomly, and occasionally not at all.

The following code shows how I'm trying to accomplish this. The TunerListener is an inner class of a JPanel subclass. PrevNote, nextNote, frequency, and the light variables are all components in the JPanel subclass that I want to update:

private class TunerListener implements ActionListener {
    private boolean firstUpdate = true;
    private boolean executing = false;
    private TunerWorker tunerWorker = null;

    private final class TunerWorker extends SwingWorker<Void, Void> {

        @Override
        protected Void doInBackground() {
            while (!this.isCancelled()) {

                // Audio analysis in worker thread
                model.update(firstUpdate);

                // Update components in EDT
                if (!this.isCancelled()) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            prevNote.setText(model.getPrev());
                            currentNote.setText(model.getNote());
                            nextNote.setText(model.getNext());
                            frequency.setText("Frequency: "
                                    + model.getFrequency());
                            switch (model.getOffset()) {
                                case -2:
                                    light_2.setIcon(onRed);
                                    light_1.setIcon(off);
                                    light0.setIcon(offBig);
                                    light1.setIcon(off);
                                    light2.setIcon(off);
                                    break;
                                case -1:
                                    light_2.setIcon(off);
                                    light_1.setIcon(onRed);
                                    light0.setIcon(offBig);
                                    light1.setIcon(off);
                                    light2.setIcon(off);
                                    break;
                                case 0:
                                    light_2.setIcon(off);
                                    light_1.setIcon(off);
                                    light0.setIcon(onGreen);
                                    light1.setIcon(off);
                                    light2.setIcon(off);
                                    break;
                                case 1:
                                    light_2.setIcon(off);
                                    light_1.setIcon(off);
                                    light0.setIcon(offBig);
                                    light1.setIcon(onRed);
                                    light2.setIcon(off);
                                    break;
                                case 2:
                                    light_2.setIcon(off);
                                    light_1.setIcon(off);
                                    light0.setIcon(offBig);
                                    light1.setIcon(off);
                                    light2.setIcon(onRed);
                                    break;
                            }
                            firstUpdate = false;
                        }
                    });
                }

            }

            return null;
        }

        @Override
        protected void done() {
        }

    };

    @Override
    public void actionPerformed(ActionEvent ae) {

        if (ae.getActionCommand().equals("tune")) {
            if (!executing) {
                executing = true;
                firstUpdate = true;
                tune.setText("Stop Tuning");
                tunerWorker = new TunerWorker();
                tunerWorker.execute();
            } else {
                tune.setText("Start Tuning");
                executing = false;
                tunerWorker.cancel(true);
            }
        }

    }
}

Edit I notice when I use the debugger that I sometimes get to a point where it tells me the source could not be found and in the debugging window it says something about a FutureTask$Sync.innerRun. Does this narrow it down at all?

As an alternative, use an instance of javax.swing.Timer , illustrated here , to Start and Stop the playing of a selected Note , shown here . The play() method feeds a SourceDataLine , which operates asynchronously, and the enum Note makes constructing a JComboBox particularly easy.

注意

final JComboBox combo = new JComboBox();
for (Note note : Note.values()) {
    combo.addItem(note);
}
combo.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println(combo.getSelectedItem());
    }
});
this.add(combo);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM