6

What are the principle differences between using an AWT Frame and a Swing JFrame when implementing your own rendering and not using standard Java GUI components?

This is a follow on from a previous question:

AWT custom rendering - capture smooth resizes and eliminate resize flicker

The typical talking points on Swing vs AWT don't seem to apply because we're only using frames. Heavyweight vs Lightweight goes out the window (and JFrame extends Frame), for example.

So which is best, JFrame or Frame for this situation? Does it make any meaningful difference?

Note: this scenario is one where rendering in the EDT is not desirable. There is an application workflow which is not linked to the EDT and rendering is done on an as-needs basis outside of the EDT. To synchronize rendering with the EDT would add latency to the rendering. We are not rendering any Swing or AWT components other than the Frame or JFrame (or an enclosed JPanel/Component/etc if it is best).

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.image.BufferStrategy;
import java.awt.Frame;

public class SmoothResize extends Frame {

public static void main(String[] args) {
    Toolkit.getDefaultToolkit().setDynamicLayout(true);
    System.setProperty("sun.awt.noerasebackground", "true");
    SmoothResize srtest = new SmoothResize();
    //srtest.setIgnoreRepaint(true);
    srtest.setSize(100, 100);
    srtest.setVisible(true);
}

public SmoothResize() {
    render();
}

private Dimension old_size = new Dimension(0, 0);
private Dimension new_size = new Dimension(0, 0);

public void validate() {
    super.validate();
    new_size.width = getWidth();
    new_size.height = getHeight();
    if (old_size.equals(new_size)) {
        return;
    } else {
        render();
    }
}

public void paint(Graphics g) {
    validate();
}

public void update(Graphics g) {
    paint(g);
}

public void addNotify() {
    super.addNotify();
    createBufferStrategy(2);
}

protected synchronized void render() {
    BufferStrategy strategy = getBufferStrategy();
    if (strategy == null) {
        return;
    }
    // Render single frame
    do {
        // The following loop ensures that the contents of the drawing buffer
        // are consistent in case the underlying surface was recreated
        do {
            Graphics draw = strategy.getDrawGraphics();
            Insets i = getInsets();
            int w = (int)(((double)(getWidth() - i.left - i.right))/2+0.5);
            int h = (int)(((double)(getHeight() - i.top - i.bottom))/2+0.5);
            draw.setColor(Color.YELLOW);
            draw.fillRect(i.left, i.top + h, w,h);
            draw.fillRect(i.left + w, i.top, w,h);
            draw.setColor(Color.BLACK);
            draw.fillRect(i.left, i.top, w, h);
            draw.fillRect(i.left + w, i.top + h, w,h);
            draw.dispose();

            // Repeat the rendering if the drawing buffer contents 
            // were restored
        } while (strategy.contentsRestored());

        // Display the buffer
        strategy.show();

        // Repeat the rendering if the drawing buffer was lost
    } while (strategy.contentsLost());
}

}
Community
  • 1
  • 1
Charles Goodwin
  • 6,402
  • 3
  • 34
  • 63
  • some `Nested and Inherit` methods from `Frame` are implemented directly in `JFrame API` http://download.oracle.com/javase/6/docs/api/javax/swing/JFrame.html, – mKorbel Aug 01 '11 at 13:36
  • I can't see any differencies between `Frame` and `JFrame` and `MsExcell` and `MozillaFirefox`, remove `notify` if done (i3/530/3,43Gb RAM, WinXP, onBoard GPU/no sharedMemory/ compiled JDK1.6.22) – mKorbel Aug 01 '11 at 13:49
  • @mKorbel: What do MsExcel and MozillaFirefox have to do with anything? – Charles Goodwin Aug 01 '11 at 14:07
  • with resize and movement of Container on the monitor, nothing else – mKorbel Aug 01 '11 at 14:15

2 Answers2

2

Swing is double buffered by default so generally you only need to concentrate on your painting.

Here is the Swing version:

import java.awt.*;
import javax.swing.*;

public class SwingResize extends JPanel
{
    protected void paintComponent(Graphics g)
    {
        int w = (int)(((double)(getWidth()))/2+0.5);
        int h = (int)(((double)(getHeight()))/2+0.5);
        g.setColor(Color.YELLOW);
        g.fillRect(0, h, w,h);
        g.fillRect(w, 0, w,h);
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, w, h);
        g.fillRect(w, h, w,h);
    }

    public static void main(String[] args)
    {
//      Toolkit.getDefaultToolkit().setDynamicLayout(true);
//      System.setProperty("sun.awt.noerasebackground", "true");

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add( new SwingResize() );
        frame.setSize(100, 100);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }

}
camickr
  • 321,443
  • 19
  • 166
  • 288
  • My fault, but I've made this question too ambiguous and the subsequent answers miss the point, forcing you down the Swing render-in-EDT paradigm. This is for a total custom UI, with nothing Swing or AWT required. Painting in the EDT is not desirable as it for this scenario as it requires juggling the application cycle and the rendering cycle, where rendering is totally custom. – Charles Goodwin Aug 01 '11 at 16:46
2

Expanding on @camickr's answer, the "missing detail" is JRootPane, which manages the contentPane. Note that for JFrame "add and its variants, remove and setLayout have been overridden to forward to the contentPane as necessary." JRootPane#createContentPane() "creates a new JComponent a[n]d sets a BorderLayout as its LayoutManager." As an implementation detail, that JComponent happens to be a new JPanel(). This has several consequences for the contentPane of JFrame:

  • The contentPane is double buffered by default.
  • The contentPane has a BorderLayout, although JPanel ordinarily defaults to FlowLayout.
  • The contentPane has a L&F specific UI delegate, typically derived from PanelUI, that may affect appearance and geometry.
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I guess I was ambiguous, but this is a completely custom render cycle. No delegates, no L&F, nothing but the wrapping Frame (or JFrame or whatever else is desirable) and rendering done *outside* the EDT because doing it in the EDT would involve latency or hackery or both. – Charles Goodwin Aug 01 '11 at 16:52
  • [*Painting in AWT and Swing: Double Buffering Support*](http://java.sun.com/products/jfc/tsc/articles/painting/index.html#db) may be apropos: "the setting that really matters is on `JRootPane`, because that setting effectively turns on double-buffering for everything underneath the top-level Swing component." I've never had a reason to turn it off. AFAIK, all extant host rendering engines are single threaded. Why _not_ use the EDT? – trashgod Aug 02 '11 at 01:03
  • Application structure and latency. The application in question has its own scripting and layout engine, which are integrated and drive rendering. Think of it as a game rather than an application (although it is the latter) in terms of rendering requirements. It renders to a backbuffer on-demand, which is then painted to screen. Both the EDT and the application thread working with the same image (backbuffer) tends to cause minor issues. – Charles Goodwin Aug 02 '11 at 01:22
  • Would it be correct to say that your existing application's model and view cannot easily be disentangled. – trashgod Aug 02 '11 at 01:44
  • The closest analog I've seen is [Processing](http://processing.org/), mentioned [here](http://stackoverflow.com/questions/6146986/is-it-possible-to-attach-a-window-from-processingjava-3d-into-a-swing-unit-like/6147329#6147329). – trashgod Aug 02 '11 at 13:11