Hi,
in my project I've got a class FrameProducer
firing events each time a video frame has been created. Each frame is an image returned as an java.awt.Image.BufferedImage
object.
I've got 2 FrameProducer
objects and would like to render BufferedImage's
produced by them simultaneously on the screen. I would like the picture rendered on the screen to be scalable (ie. when I drag the application-window's corner the rendered video gets smaller or bigger).
How do you think is this best do be achieved?
I've considered using java.awt.Graphics2D
embedded in an java.awt.Frame
, but don't know how such a thing can be done or if this is the best choice. I just need this for algorithm visualisation, it doesn't need to be nice and shiny, just fast and easy. Has maybe anyone got some ready code I could use or suggestions?
Edit: Ok, I implemented the solution as Rekin suggested, and it works. But as I'm not an Java expert and definately not a Swing expert, I'd like to ask you for kind remarks on my code - I'm sure many will benefit from that in the future.
As I said, there is a FrameProducer
(never mind the implementation):
public abstract class FrameProducer extends Observable {
public abstract BufferedImage getFrame();
public void fireEvent() {
setChanged();
notifyObservers();
}
}
Then there is also a FrameRenderer
waiting for events from the FrameProducer
(a simple observer-pattern implementation using java.util
):
public class FrameRenderer extends JPanel implements Observer {
private BufferedImage frame;
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(frame, null, 0, 0);
g2d.dispose();
}
@Override
public void update(Observable observable, Object arg) {
System.out.println("Cought an event from " + observable.getClass());
if (observable instanceof FrameProducer) {
frame = ((FrameProducer) observable).getFrame();
paint(getGraphics());
}
}
}
And then there is also the thing that needs rework: the MainFrame
.
public class MainFrame extends JFrame {
FrameProducer[] producers;
public MainFrame(FrameProducer[] producers) {
this.setTitle("Playing what you feed.");
this.producers = producers;
initContents();
setVisible(true);
}
private void initContents() {
FrameRenderer renderer = new FrameRenderer();
renderer.setLocation(0, 0);
this.add(renderer);
producers[0].addObserver(renderer);
}
}
It all gets initialised in the main method:
public class FrameAccessTest {
public static void main(String[] args) {
final FrameProducer frameGrabber = new CameraFrameGrabber("vfw://0");
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
MainFrame mainFrame =
new MainFrame(new FrameProducer[] {frameGrabber});
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
How do I implement initContents() in such a way, that all the video streams provided in MainFrame's
constructor as FrameProducer[]
get rendered in a row and that they are scalable?
Again, thanks for any help.