首页 > 解决方案 > Eclipse 在将项目导出为可执行 jar 期间找不到主类

问题描述

我觉得这将是一个微不足道的问题,但它让我把头撞到墙上。

我需要一个能够尽可能快地录制音频的 Java 程序。我搜索了一些预先存在的代码,我发现了这一点,并对代码进行了修改:我确保在创建 GUI 之后的第一件事就是让 Java 本身按下记录按钮。

在修改后的 main 方法下方,在类中找到SwingSoundRecorder

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                SwingSoundRecorder GUI = null;
                GUI = new SwingSoundRecorder();
                GUI.setVisible(true);
                
                // This line ensures the GUI will start recording immediately
                GUI.buttonPlay.doClick();
            }
        });
    }

完成此操作后,我尝试将其导出为 Java 可执行文件。由于我使用 Eclipse,我认为这会很容易:只需指定 .jar 文件的位置以及主类是什么。

好吧,显然 Java 不承认SwingSoundRecorder有一个 main 方法可以使用。我真的不明白为什么。

任何想法?有什么帮助吗?


编辑:所涉及的所有四个类的完整代码,正如@anish sharma 正确想要的那样:

public class SwingSoundRecorder extends JFrame implements ActionListener {

    /**
     * 
     */
    private static final long serialVersionUID = 2747541100831140840L;
    private JButton buttonRecord = new JButton("Record");
    private JButton buttonPlay = new JButton("Play");
    private JLabel labelRecordTime = new JLabel("Record Time: 00:00:00");

    private SoundRecordingUtil recorder = new SoundRecordingUtil();
    private AudioPlayer player = new AudioPlayer();
    private Thread playbackThread;
    private RecordTimer timer;

    private boolean isRecording = false;
    private boolean isPlaying = false;

    private String saveFilePath;

    // Icons used for buttons
    private ImageIcon iconRecord = new ImageIcon(getClass().getResource(
            "/net/codejava/sound/images/Record.gif"));
    private ImageIcon iconStop = new ImageIcon(getClass().getResource(
            "/net/codejava/sound/images/Stop.gif"));
    private ImageIcon iconPlay = new ImageIcon(getClass().getResource(
            "/net/codejava/sound/images/Play.gif"));
    

    /**
     * launch the program
     * 
     */
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                SwingSoundRecorder GUI = null;
                GUI = new SwingSoundRecorder();
                GUI.setVisible(true);
                
                // This line ensures the GUI will start recording immediately
                GUI.buttonPlay.doClick();
            }
        });
    }

    
    
    
    
    
    
    
    
    
    
    
    

    public SwingSoundRecorder() {
        super("Swing Sound Recorder");
        setLayout(new FlowLayout());

        buttonRecord.setFont(new Font("Sans", Font.BOLD, 14));
        buttonRecord.setIcon(iconRecord);
        buttonPlay.setFont(new Font("Sans", Font.BOLD, 14));
        buttonPlay.setIcon(iconPlay);
        buttonPlay.setEnabled(false);
        labelRecordTime.setFont(new Font("Sans", Font.BOLD, 12));

        add(buttonRecord);
        add(labelRecordTime);
        add(buttonPlay);

        buttonRecord.addActionListener(this);
        buttonPlay.addActionListener(this);

        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    /**
     * Handle click events on the buttons.
     */
    @Override
    public void actionPerformed(ActionEvent event) {
        JButton button = (JButton) event.getSource();
        if (button == buttonRecord) {
            if (!isRecording) {
                startRecording();
            } else {
                stopRecording();
            }

        } else if (button == buttonPlay) {
            if (!isPlaying) {
                playBack();
            } else {
                stopPlaying();
            }
        }
    }

    /**
     * Start recording sound, the time will count up.
     */
    private void startRecording() {
        Thread recordThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    isRecording = true;
                    buttonRecord.setText("Stop");
                    buttonRecord.setIcon(iconStop);
                    buttonPlay.setEnabled(false);

                    recorder.start();

                } catch (LineUnavailableException ex) {
                    JOptionPane.showMessageDialog(SwingSoundRecorder.this,
                            "Error", "Could not start recording sound!",
                            JOptionPane.ERROR_MESSAGE);
                    ex.printStackTrace();
                }
            }
        });
        recordThread.start();
        timer = new RecordTimer(labelRecordTime);
        timer.start();
    }

    /**
     * Stop recording and save the sound into a WAV file
     */
    private void stopRecording() {
        isRecording = false;
        try {
            timer.cancel();
            buttonRecord.setText("Record");
            buttonRecord.setIcon(iconRecord);
            
            setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

            recorder.stop();

            setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));

            saveFile();

        } catch (IOException ex) {
            JOptionPane.showMessageDialog(SwingSoundRecorder.this, "Error",
                    "Error stopping sound recording!",
                    JOptionPane.ERROR_MESSAGE);
            ex.printStackTrace();
        }
    }

    /**
     * Start playing back the sound.
     */
    private void playBack() {
        timer = new RecordTimer(labelRecordTime);
        timer.start();
        isPlaying = true;
        playbackThread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {

                    buttonPlay.setText("Stop");
                    buttonPlay.setIcon(iconStop);
                    buttonRecord.setEnabled(false);

                    player.play(saveFilePath);
                    timer.reset();

                    buttonPlay.setText("Play");
                    buttonRecord.setEnabled(true);
                    buttonPlay.setIcon(iconPlay);
                    isPlaying = false;

                } catch (UnsupportedAudioFileException ex) {
                    ex.printStackTrace();
                } catch (LineUnavailableException ex) {
                    ex.printStackTrace();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }

            }
        });

        playbackThread.start();
    }

    /**
     * Stop playing back.
     */
    private void stopPlaying() {
        timer.reset();
        timer.interrupt();
        player.stop();
        playbackThread.interrupt();
    }

    /**
     * Save the recorded sound into a WAV file.
     * 
     * @author Nam Ha Minh, source is <a href="https://www.codejava.net/coding/capture-and-record-sound-into-wav-file-with-java-sound-api">here</a>
     */
    private void saveFile() {
        JFileChooser fileChooser = new JFileChooser();
        FileFilter wavFilter = new FileFilter() {
            @Override
            public String getDescription() {
                return "Sound file (*.WAV)";
            }

            @Override
            public boolean accept(File file) {
                if (file.isDirectory()) {
                    return true;
                } else {
                    return file.getName().toLowerCase().endsWith(".wav");
                }
            }
        };

        fileChooser.setFileFilter(wavFilter);
        fileChooser.setAcceptAllFileFilterUsed(false);

        int userChoice = fileChooser.showSaveDialog(this);
        if (userChoice == JFileChooser.APPROVE_OPTION) {
            saveFilePath = fileChooser.getSelectedFile().getAbsolutePath();
            if (!saveFilePath.toLowerCase().endsWith(".wav")) {
                saveFilePath += ".wav";
            }

            File wavFile = new File(saveFilePath);

            try {
                recorder.save(wavFile);

                JOptionPane.showMessageDialog(SwingSoundRecorder.this,
                        "Saved recorded sound to:\n" + saveFilePath);

                buttonPlay.setEnabled(true);

            } catch (IOException ex) {
                JOptionPane.showMessageDialog(SwingSoundRecorder.this, "Error",
                        "Error saving to sound file!",
                        JOptionPane.ERROR_MESSAGE);
                ex.printStackTrace();
            }
        }
    }
    
    
}
public class SoundRecordingUtil {
    private static final int BUFFER_SIZE = 4096;
    private ByteArrayOutputStream recordBytes;
    private TargetDataLine audioLine;
    private AudioFormat format;

    private boolean isRunning;

    /**
     * Defines a default audio format used to record
     */
    AudioFormat getAudioFormat() {
        float sampleRate = 44100;
        int sampleSizeInBits = 16;
        int channels = 2;
        boolean signed = true;
        boolean bigEndian = true;
        return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,
                bigEndian);
    }

    /**
     * Start recording sound.
     * @throws LineUnavailableException if the system does not support the specified 
     * audio format nor open the audio data line.
     */
    public void start() throws LineUnavailableException {
        format = getAudioFormat();
        DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);

        // checks if system supports the data line
        if (!AudioSystem.isLineSupported(info)) {
            throw new LineUnavailableException(
                    "The system does not support the specified format.");
        }

        audioLine = AudioSystem.getTargetDataLine(format);

        audioLine.open(format);
        audioLine.start();

        byte[] buffer = new byte[BUFFER_SIZE];
        int bytesRead = 0;

        recordBytes = new ByteArrayOutputStream();
        isRunning = true;

        while (isRunning) {
            bytesRead = audioLine.read(buffer, 0, buffer.length);
            recordBytes.write(buffer, 0, bytesRead);
        }
    }

    /**
     * Stop recording sound.
     * @throws IOException if any I/O error occurs.
     */
    public void stop() throws IOException {
        isRunning = false;
        
        if (audioLine != null) {
            audioLine.drain();
            audioLine.close();
        }
    }

    /**
     * Save recorded sound data into a .wav file format.
     * @param wavFile The file to be saved.
     * @throws IOException if any I/O error occurs.
     * @throws UnsupportedAudioFileException 
     */
    public void save(File wavFile) throws IOException {
        byte[] audioData = recordBytes.toByteArray();
        ByteArrayInputStream bais = new ByteArrayInputStream(audioData);
        AudioInputStream audioInputStream = new AudioInputStream(bais, format,
                audioData.length / format.getFrameSize());      
        AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, wavFile);

        audioInputStream.close();
        recordBytes.close();
    }
}
public class RecordTimer extends Thread {
    private DateFormat dateFormater = new SimpleDateFormat("HH:mm:ss"); 
    private boolean isRunning = false;
    private boolean isReset = false;
    private long startTime;
    private JLabel labelRecordTime;
    
    RecordTimer(JLabel labelRecordTime) {
        this.labelRecordTime = labelRecordTime;
    }
    
    public void run() {
        isRunning = true;
        
        startTime = System.currentTimeMillis();
        
        while (isRunning) {
            try {
                Thread.sleep(1000);
                labelRecordTime.setText("Record Time: " + toTimeString());
            } catch (InterruptedException ex) {
                ex.printStackTrace();
                if (isReset) {
                    labelRecordTime.setText("Record Time: 00:00:00");
                    isRunning = false;      
                    break;
                }
            }
        }
    }
    
    /**
     * Cancel counting record/play time.
     */
    void cancel() {
        isRunning = false;      
    }
    
    /**
     * Reset counting to "00:00:00"
     */
    void reset() {
        isReset = true;
        isRunning = false;
    }
    
    /**
     * Generate a String for time counter in the format of "HH:mm:ss"
     * @return the time counter
     */
    private String toTimeString() {
        long now = System.currentTimeMillis();
        Date current = new Date(now - startTime);
        dateFormater.setTimeZone(TimeZone.getTimeZone("GMT"));
        String timeCounter = dateFormater.format(current);
        return timeCounter;
    }
}
public class AudioPlayer implements LineListener {
    /**
     * this flag indicates whether the playback completes or not.
     */
    boolean playCompleted;
    
    /**
     * this flag indicates whether the playback is stopped or not.
     */
    boolean isStopped;

    /**
     * Play a given audio file.
     * 
     * @param audioFilePath
     *            Path of the audio file.
     * @throws IOException
     * @throws UnsupportedAudioFileException
     * @throws LineUnavailableException
     */
    void play(String audioFilePath) throws UnsupportedAudioFileException,
            IOException, LineUnavailableException {
        File audioFile = new File(audioFilePath);

        AudioInputStream audioStream = AudioSystem
                .getAudioInputStream(audioFile);

        AudioFormat format = audioStream.getFormat();

        DataLine.Info info = new DataLine.Info(Clip.class, format);

        Clip audioClip = (Clip) AudioSystem.getLine(info);

        audioClip.addLineListener(this);

        audioClip.open(audioStream);

        audioClip.start();
        
        playCompleted = false;
        
        while (!playCompleted) {
            // wait for the playback completes
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
                if (isStopped) {
                    audioClip.stop();
                    break;
                }
            }
        }

        audioClip.close();

    }

    /**
     * Stop playing back.
     */
    public void stop() {
        isStopped = true;
    }
    
    /**
     * Listens to the audio line events to know when the playback completes.
     */
    @Override
    public void update(LineEvent event) {
        LineEvent.Type type = event.getType();
        if (type == LineEvent.Type.STOP) {
            playCompleted = true;
        }
    }
}

标签: javaeclipse

解决方案


推荐阅读