问题
I Have written a listener for an IMediaReader from Xuggler. It should show a video in a JPanel what i can add to a JFrame.
I have created this JFrame in the class main:
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);
}
}
It shows the video but it only works when i resize the window manually and that is my problem. Else, it shows a small black square.
Using pack() instead of setSize() or invoke repaint doesn't help.
The Code of class Player isn't just from me. I've just changed some things:
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);
}
}
}
It is made up from the class MediaViewer http://code.google.com/p/xuggle/source/browse/trunk/java/xuggle-xuggler/src/com/xuggle/mediatool/MediaViewer.java?r=644
EDIT: If I do it like this, it doesn't work without resizing manually. I'm not shure if I have unterstood you right.
回答1:
You have this code in two places.
pack();
setSize(700, 700);
The pack() class is wasteful since you are setting the size immediately afterwards. Also, the first time you call in your constructor you haven't even added anything yet.
Try setting the size or calling pack after you have added the video component and after you have made the frame visible.
Based on your edits, I believe the issue is that you are setting the frame visible before the component is in place. Move your setVisible and pack() calls to the end of your constructor for the Main
class instead of the add()
method.
Based on more edits to your question: As I mentioned in the comments, make sure you separate off the GUI code in a separate call to invokeLater to get things happening on the EDT. Therefore you need to move your IMediaReader creation and thread starting into your main() method, then after that create a new call to SwingUtilities.invokeLater that creates a new Main, class. By the way, Main is a confusing name for a class.
来源:https://stackoverflow.com/questions/19633504/jframe-displays-content-only-after-resizing-xuggler