GUI事件触发不会持续 [英] GUI event not triggering consistently

查看:121
本文介绍了GUI事件触发不会持续的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小程序来记录和播放.wav文件。
在GUI类,我有以下code为停止按钮:

I have a little program to record and playback .wav files. In the GUI class I have the following code for the "stop" button:

private AudioCapture audCap = new AudioCapture();

stopBtn.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            captureBtn.setEnabled(true);
            stopBtn.setEnabled(false);
            playBtn.setEnabled(true);
            audCap.stopCapture = true; // this doesn't work
            audCap.stopPlayback = true; // this does
        }
    }

在AudioCapture()类我有这样的code播放,停靠正确点击停止按钮时:

In the AudioCapture() class I have this code for playback, which stops correctly when stop button is clicked:

class PlayThread extends Thread {
    byte tempBuffer[] = new byte[10000];

    public void run() {

        stopPlayback = false;

        try {
            sourceDataLine.open(audioFormat);
            sourceDataLine.start();

            int cnt;
            while ((cnt = audioInputStream.read(tempBuffer, 0,
                    tempBuffer.length)) != -1 && stopPlayback == false) {
                if (cnt > 0) {
                    sourceDataLine.write(tempBuffer, 0, cnt);
                }
            }
            sourceDataLine.drain();
            sourceDataLine.close();

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }
    }
}

我也有这个code录制/捕获,点击停止按钮时不停止:

I also have this code for recording/capturing, which doesn't stop when the stop button is clicked:

class CaptureThread extends Thread {
    // An arbitrary-size temporary holding buffer
    byte tempBuffer[] = new byte[10000];

    public void run() {

        stopCapture = false;
        // record as wave
        AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
        // takes user input file name and appends filetype
        audioFile = new File(wavName + ".wav");

        try {
            while (!stopCapture) {

                int cnt = targetDataLine.read(tempBuffer, 0,
                        tempBuffer.length);
                if (cnt > 0) {
                    AudioSystem.write(new AudioInputStream(targetDataLine),
                            fileType, audioFile);
                }
            }
            targetDataLine.stop();
            targetDataLine.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

&stopCature放大器; stopPlayback都在AudioCapture()类的实例变量。

stopCature & stopPlayback are instance variables in the AudioCapture() class.

我使用Eclipse和在尝试设置一个破发点,而(!stopCapture),它似乎从来就没不止于此。
有谁知道是否有在code上面的东西会导致第一种方法能够按预期工作,但第二个不?

I'm using Eclipse and tried setting a break point at "while (!stopCapture)" and it never seems to get beyond this. Does anyone know if there is anything in the code above that would cause the first method to function as expected but the second not to?

-EDIT-
我试图把该计划的削减版本到SSCE,但它仍然运行到几百行:

-EDIT- I've tried to put a cut down version of the program into an SSCE but it still runs to a couple of hundred lines:

import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class audioTest extends JFrame {

private static final long serialVersionUID = 1L;
AudioCapture audCap = new AudioCapture();

public static void main(String[] args) {
    new audioTest();
}

public audioTest() {

    layoutTransporButtons();
    getContentPane().setLayout(new FlowLayout());
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(350, 100);
    setVisible(true);
}

public void layoutTransporButtons() {

    final JPanel guiButtonPanel = new JPanel();
    final JButton captureBtn = new JButton("Record");
    final JButton stopBtn = new JButton("Stop");
    final JButton playBtn = new JButton("Playback");
    guiButtonPanel.setLayout(new GridLayout());
    this.add(guiButtonPanel);
    captureBtn.setEnabled(true);
    stopBtn.setEnabled(false);
    playBtn.setEnabled(true);

    // Register anonymous listeners
    captureBtn.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            captureBtn.setEnabled(false);
            stopBtn.setEnabled(true);
            playBtn.setEnabled(false);
            // Capture input data from the microphone
            audCap.captureAudio();
        }
    });
    guiButtonPanel.add(captureBtn);

    stopBtn.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            captureBtn.setEnabled(true);
            stopBtn.setEnabled(false);
            playBtn.setEnabled(true);
            audCap.stopRecordAndPlayback = true;
        }
    });
    guiButtonPanel.add(stopBtn);

    playBtn.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            stopBtn.setEnabled(true);
            audCap.playAudio();
        }
    });
    guiButtonPanel.add(playBtn);
}

class AudioCapture {

    volatile boolean stopRecordAndPlayback = false;
    AudioFormat audioFormat;
    TargetDataLine targetDataLine;
    AudioInputStream audioInputStream;
    SourceDataLine sourceDataLine;
    private String wavName;
    private File audioFile;
    /**
     *  capture audio input from microphone and save as .wav file
     */
    public void captureAudio() {

        wavName = JOptionPane.showInputDialog(null,
                "enter name of file to be recorded:");
        try {
            Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
            // Select an available mixer
            Mixer mixer = AudioSystem.getMixer(mixerInfo[1]);
            // Get everything set up for capture
            audioFormat = getAudioFormat();
            DataLine.Info dataLineInfo = new DataLine.Info(
                    TargetDataLine.class, audioFormat);
            // Get a TargetDataLine on the selected mixer.
            targetDataLine = (TargetDataLine) mixer.getLine(dataLineInfo);
            // Prepare the line for use.
            targetDataLine.open(audioFormat);
            targetDataLine.start();
            // Create a thread to capture the microphone
            Thread captureThread = new CaptureThread();
            captureThread.start();
        } catch (Exception e) {
            System.out.println(e);
            System.exit(0);
        }
    }

    /**
     *  This method plays back the audio data that has
     *  been chosen by the user
     */
    public void playAudio() {
        // add file chooser
        JFileChooser chooser = new JFileChooser();
        chooser.setCurrentDirectory(audioFile);
        int returnVal = chooser.showOpenDialog(chooser);
        // retrieve chosen file
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            // create the file
            audioFile = chooser.getSelectedFile();
        }
        // play chosen file
        try {
            audioInputStream = AudioSystem.getAudioInputStream(audioFile);
            audioFormat = audioInputStream.getFormat();
            DataLine.Info dataLineInfo = new DataLine.Info(
                    SourceDataLine.class, audioFormat);
            sourceDataLine = (SourceDataLine) AudioSystem
                    .getLine(dataLineInfo);
            // Create a thread to play back the data
            new PlayThread().start();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }
    }
    /**
     *  This method creates and returns an AudioFormat object
     */
    private AudioFormat getAudioFormat() {
        float sampleRate = 44100.0F;
        // 8000,11025,16000,22050,44100
        int sampleSizeInBits = 16;
        // 8,16
        int channels = 1;
        // 1,2
        boolean signed = true;
        // true,false
        boolean bigEndian = false;
        // true,false
        return new AudioFormat(sampleRate, sampleSizeInBits, channels,
                signed, bigEndian);
    }

    /**
     *  Inner class to capture data from microphone
     */
    class CaptureThread extends Thread {
        // An arbitrary-size temporary holding buffer
        byte tempBuffer[] = new byte[10000];

        public void run() {
            // reset stopCapture to false
            stopRecordAndPlayback = false;
            // record as wave
            AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
            // take user input file name and append file type
            audioFile = new File(wavName + ".wav");

            try {
                targetDataLine.open(audioFormat);
                targetDataLine.start();
                while (!stopRecordAndPlayback) {
                    AudioSystem.write(new AudioInputStream(targetDataLine),
                            fileType, audioFile);
                }
                targetDataLine.stop();
                targetDataLine.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /**
     *  Inner class to play back the data
     */
    class PlayThread extends Thread {
        byte tempBuffer[] = new byte[10000];

        public void run() {
            // reset stop button
            stopRecordAndPlayback = false;

            try {
                sourceDataLine.open(audioFormat);
                sourceDataLine.start();
                int cnt;
                while ((cnt = audioInputStream.read(tempBuffer, 0,
                        tempBuffer.length)) != -1
                        && stopRecordAndPlayback == false) {
                    if (cnt > 0) {
                        sourceDataLine.write(tempBuffer, 0, cnt);
                    }
                }
                sourceDataLine.drain();
                sourceDataLine.close();
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(0);
            }
        }
    }
}

}

推荐答案

您不给所有需要的信息,但一个很可能的原因是程序中的数据争。

You don't give all the needed information but a very likely reason is a data race in your program.

由于要在不同的线程运行的东西,你需要使用某种形式的同步跨线程,以确保你在一个线程中进行更改在其他都是可见的。

Since you are running things in different threads, you need to use some form of synchronization across threads to make sure the changes you make in one thread are visible in the other.

通常情况下,你的情况,声明布尔变量波动应该足够了。

Typically, in your case, declaring the boolean variables volatile should be sufficient.

修改

一种可能性是,在while循环的条件没有得到经常你认为评估(如果有的话) - 你可以添加一些记录,看看到底是怎么回事:

One possibility is that the condition in your while loop does not get evaluated as often as you think (if at all) - you could add some logging to see what is going on:

stopBtn.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        //your code here
        System.out.println("in actionPerformed: " + stopCatpure);
    }
}

class CaptureThread extends Thread {
    //same code
            while (!stopCapture) {
                System.out.println("in while: " + stopCapture);
                //rest of your code
            }
}

这篇关于GUI事件触发不会持续的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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