0

我已经为 Xuggler 的 IMediaReader 编写了一个侦听器。它应该在 JPanel 中显示我可以添加到 JFrame 的视频。

我在主类中创建了这个 JFrame:

class Window extends JFrame {

    static IMediaReader reader;
    static Window main;

    public static void main(String[] args) {



        new Thread() {
            public void run() {
                reader = ToolFactory.makeReader("C:/Users/André/Desktop/Detail.wmv");
                reader.addListener(new Player(IMediaViewer.Mode.AUDIO_VIDEO, main));

                while (reader.readPacket() == null)
                    do {} while(false);  
            }
        }.start();

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                main = new Window();
            }
        });
    }

    private Window() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                setVisible(true);
                setSize(700, 700);
            }
        });


    }

    // invoked by Player with the video panel 
    public void add(final JPanel videoPanel) {

        add(videoPanel, BorderLayout.CENTER);        
    }
}

它显示了视频,但仅在我手动调整窗口大小时才有效,这是我的问题。否则,它会显示一个黑色的小方块。

使用 pack() 而不是 setSize() 或调用 repaint 没有帮助。

类 Player 的代码不只是来自我。我刚刚改变了一些东西:

public class Player extends MediaListenerAdapter implements IMediaListener, IMediaViewer {

    private static Main main;

    Player(Mode mode, Main main) {
        setMode(mode);
        Player.main = main;
    }


        @Override
        public void onAddStream(IAddStreamEvent event)
        {
                [...]
            MediaFrame frame = new MediaFrame(stream, this, main);
                [...]
        }

        @Override
        public void onVideoPicture(IVideoPictureEvent event)
        {

            MediaFrame frame = mFrames.get(event.getStreamIndex());
                frame.setVideoImage(event.getPicture(), event.getImage());
        }

        static class PositionFrame extends JPanel
        {

            public PositionFrame(Player viewer, Main main)
            {
                main.add(this);



                mFrames.add(this);


            }



            protected void adjustSize()
            {
                invalidate();
            }


        }



        private class MediaFrame extends PositionFrame
        {

            // the video image

            private BufferedImage mImage;

            // the video panel

            private final JPanel mVideoPanel;

            // the stream

            private final IStream mStream;

            // the index of the stream (incase it's closed)

            private final int mStreamIndex;

            /**
             * Construct a media frame.
             * 
             * @param defaultCloseOperation what should Swing do if the window
             *              is closed. See the {@link javax.swing.WindowConstants}
             *              documentation for valid values.
             * @param stream the stream which will appear in this frame
             * @param viewer containing media viewer
             */

            public MediaFrame(IStream stream, 
                Player viewer, Main main)
            {
                super(viewer, main);

                // get stream and set title based it, establish a copy of the
                // stream since it lives in a separate thread

                mStream = stream.copyReference();
                mStreamIndex = mStream.getIndex();

                // the panel which shows the video image

                mVideoPanel = new JPanel()
                {


                    public void paint(Graphics graphics)
                    {
                        paintPanel((Graphics2D) graphics);
                    }
                };

                // add the videoPanel

                add(mVideoPanel);

                // show the frame

                setVisible(true);
            }


            // set the video image

            protected void setVideoImage(IVideoPicture picture, BufferedImage image)
            {
                       [...]
                    }

            protected void paintPanel(Graphics2D graphics)
            {
                if (mImage != null)
                    graphics.drawImage(mImage, 0, 0, null);
            }
        }

}

它由 MediaViewer 类组成 http://code.google.com/p/xuggle/source/browse/trunk/java/xuggle-xuggler/src/com/xuggle/mediatool/MediaViewer.java?r=644

编辑:如果我这样做,如果不手动调整大小,它就无法工作。如果我对你的理解是正确的,我不确定。

4

1 回答 1

2

您在两个地方有此代码。

 pack();
 setSize(700, 700);

pack() 类是浪费的,因为您在之后立即设置大小。此外,第一次调用构造函数时,您甚至还没有添加任何内容。

在添加视频组件并且使帧可见之后,尝试设置大小或调用 pack。

根据您的编辑,我认为问题在于您在组件就位之前将框架设置为可见。将您的 setVisible 和 pack() 调用移动到Main类而不是add()方法的构造函数的末尾。

基于对您问题的更多编辑:正如我在评论中提到的,确保您在单独调用 invokeLater 时将 GUI 代码分开,以使 EDT 上发生的事情。因此,您需要将您的 IMediaReader 创建和线程开始移动到您的 main() 方法中,然后创建一个对 SwingUtilities.invokeLater 的新调用,该调用创建一个新的 Main 类。顺便说一句,Main 是一个令人困惑的类名称。

于 2013-10-28T12:35:11.980 回答