Как обращаться с веб-камерой отключите, а затем снова подключите веб-камеру sarxos java?

#java #multithreading #singleton #qr-code #webcam

Вопрос:

Я попытался создать одноэлементный класс WebCamFrame для создания веб-камеры, используя библиотеку веб-камер sarxos. Я пытаюсь справиться с ситуацией, когда моя веб-камера отключена, а затем снова подключена. Я пытался справиться с этим случаем, но на моей рамке веб-камеры отображается текст «изображение недоступно», когда я снова открываю рамку веб-камеры. Правильна ли моя попытка разобраться с этим делом?

Мой класс веб-кадров:

 /**
 * WebCam Frame which is a singleton class that runs on a new thread
 * It reads in video stream from webcam and attempts to read a qr code
 */
public class WebCamFrame extends JFrame implements Runnable, WebcamDiscoveryListener {
    private static WebCamFrame singleton;
    private Webcam webcam = null;
    private WebcamPanel panel = null;
    private JLabel playedCardLabel = null;
    private JButton confirmButton = null;
    private boolean running;
    
    public static WebCamFrame getInstance() {
        if( singleton == null ) 
            singleton = new WebCamFrame();
        return singleton;
    }
    
    @Override
    public void webcamFound( WebcamDiscoveryEvent event ) {
        if( webcam == null ) return;
        Webcam newWebcam = event.getWebcam();
        if( newWebcam.getName().equals( webcam.getName()) ) {
            close();
            webcam = Webcam.getWebcamByName( webcam.getName() );
            webcam.open();
            panel = new WebcamPanel( webcam );
        }
    }

    @Override
    public void webcamGone( WebcamDiscoveryEvent event ) {
        if( webcam == null ) return;
        Webcam disconnectedWebCam = event.getWebcam();
        if( disconnectedWebCam.getName().equals( webcam.getName()) ) {
            playedCardLabel.setText( "WebCam disconnected, please reconnect." );
            webcam.close();
        }
    }
    
    private WebCamFrame() {
        super();
        Webcam.addDiscoveryListener( this );
        running = true;
        setLayout( new FlowLayout() );
        setTitle( "Scan a card to make your move" );
        setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
        addWindowListener( new WindowAdapter() {
            @Override
            public void windowClosing( WindowEvent e ) {
                super.windowClosing( e );
                close();
            }
        } );
        Dimension size = WebcamResolution.QVGA.getSize();
        webcam = Webcam.getWebcams().get( 1 );
        webcam.setViewSize( size );
        panel = new WebcamPanel( webcam );
        panel.setPreferredSize( size );
        panel.setFPSDisplayed( true );
        panel.setLayout( new BorderLayout() );
        playedCardLabel = new JLabel( "", SwingConstants.CENTER );
        if( Webcam.getDefault() == null ) playedCardLabel.setText( "No Webcam detected" );
        confirmButton = new JButton( "Confirm Selection" );
        confirmButton.setVisible( false );
        confirmButton.addActionListener( e -> {
          close();
        } );
        add( panel );
        JPanel subPanel = new JPanel();
        subPanel.setLayout( new BorderLayout() );

        subPanel.add( playedCardLabel, BorderLayout.NORTH );
        subPanel.add( confirmButton, BorderLayout.SOUTH );
        panel.add( subPanel, BorderLayout.SOUTH );
        pack();
        setVisible( false );
    }

    @Override
    public void run() {
        do {
            try {
                if( !running ) return;
                Thread.sleep( 100 );
            } catch( InterruptedException e ) {
                e.printStackTrace();
            }
            Result result = null;
            BufferedImage image;
            // Only try to read qr code if webcam is open and frame is webCamFrame is visible
            if( webcam.isOpen() amp;amp; isVisible() ) {
                System.out.println("Entering");
                if( (image = webcam.getImage()) == null ) {
                    continue;
                }
                LuminanceSource source = new BufferedImageLuminanceSource( image );
                BinaryBitmap bitmap = new BinaryBitmap( new HybridBinarizer(source) );
                try {
                    result = new MultiFormatReader().decode( bitmap );
                } catch( NotFoundException e ) {
                    // fall through if there is no QR code in image
                }
            }
            if( result != null ) {
                playedCardLabel.setText( "You have played card "   result.getText() );
                confirmButton.setVisible( true );
            }
        } while( true );
    }

    /* Hide the webcam frame and reset its swing components */
    public void close() {
        setVisible( false );
        resetComponents();
    }

    public void open() {
        setVisible( true );
    }
    
    public void toggleOpen() {
        if( isVisible() )
            close();
        else 
            open();
    }
    
    // Kill the webcam, join the webcam thread and dispose of the webcam frame
    public void kill() throws InterruptedException {
        dispose();
        webcam.close();
        singleton = null;
        running = false;
    }

    private void resetComponents() {
        confirmButton.setVisible( false );
        playedCardLabel.setText( "" );
    }
}
 

Я создаю новую тему для своей веб-камеры в своем основном классе примерно так:

 Thread webcamThread = new Thread( WebCamFrame.getInstance() );
webcamThread.start();
try {
            webcamThread.join();
        } catch ( InterruptedException ex ) {
            Logger.getLogger( tsInfluence.class.getName() ).log( Level.SEVERE, null, ex );
        }
 

Это моя первая попытка реализовать одноэлементный класс, и я чувствую, что именно в этом может заключаться моя проблема, заранее прошу прощения за любые ошибки. Спасибо

Комментарии:

1. я предлагаю создать отдельный класс для непосредственной обработки событий веб-камеры, а затем вы можете создать свой собственный прослушиватель для предоставления обратных вызовов классу пользовательского интерфейса

2. @silentsudo Я переделал, чтобы сделать именно это, и теперь это работает! Большое спасибо

Ответ №1:

@silentsudo предложение в комментариях сработало для меня:

«я предлагаю создать отдельный класс для непосредственной обработки событий веб-камеры, а затем вы можете создать свой собственный прослушиватель для предоставления обратных вызовов классу пользовательского интерфейса».