Swing/JFrame против AWT/Frame для рендеринга вне EDT

Каковы принципиальные различия между использованием AWT Frame и Swing JFrame при реализации собственного рендеринга и без использования стандартных компонентов Java GUI?

Это продолжение предыдущего вопроса:

Пользовательский рендеринг AWT - плавный захват изменение размера и устранение мерцания при изменении размера

Типичные темы для обсуждения Swing vs AWT, похоже, не применимы, потому что мы используем только фреймы. Например, Heavyweight vs Lightweight выходит из окна (и JFrame расширяет Frame).

Итак, что лучше, JFrame или Frame для этой ситуации? Имеет ли это какое-то существенное значение?

Примечание. В этом сценарии рендеринг в EDT нежелателен. Существует рабочий процесс приложения, который не связан с EDT, и рендеринг выполняется по мере необходимости вне EDT. Синхронизация рендеринга с EDT приведет к увеличению задержки рендеринга. Мы не визуализируем какие-либо компоненты Swing или AWT, кроме Frame или JFrame (или вложенного JPanel/Component/etc, если это лучше).

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());
}

}

person Charles Goodwin    schedule 01.08.2011    source источник
comment
некоторые Nested and Inherit методы из Frame реализованы непосредственно в JFrame API загрузке. oracle.com/javase/6/docs/api/javax/swing/JFrame.html,   -  person mKorbel    schedule 01.08.2011
comment
Я не вижу никаких различий между Frame и JFrame и MsExcell и MozillaFirefox, удалите notify, если сделано (i3/530/3,43Gb RAM, WinXP, встроенный графический процессор/без разделяемой памяти/скомпилированный JDK1.6.22)   -  person mKorbel    schedule 01.08.2011
comment
@mKorbel: При чем здесь MsExcel и MozillaFirefox?   -  person Charles Goodwin    schedule 01.08.2011
comment
с изменением размера и перемещением Контейнера на мониторе, больше ничего   -  person mKorbel    schedule 01.08.2011


Ответы (2)


Расширение ответа @camickr "отсутствующая деталь" — это JRootPane, который управляет contentPane. Обратите внимание, что для JFrame "add и его варианты, remove и setLayout были переопределены для пересылки на contentPane по мере необходимости." JRootPane#createContentPane() " создает новый JComponent a[n]d устанавливает BorderLayout в качестве своего LayoutManager." Что касается детали реализации, то JComponent оказывается new JPanel(). Это имеет несколько последствий для contentPane из JFrame:

  • contentPane по умолчанию имеет двойную буферизацию.
  • У contentPane есть BorderLayout, хотя JPanel обычно по умолчанию равно FlowLayout.
  • contentPane имеет делегат пользовательского интерфейса, специфичный для L&F, обычно производный от PanelUI, который может влиять на внешний вид и геометрию.
person trashgod    schedule 01.08.2011
comment
Наверное, я выразился неоднозначно, но это полностью настраиваемый цикл рендеринга. Никаких делегатов, никаких L&F, ничего, кроме обертывания Frame (или JFrame, или чего-то еще желательного) и рендеринга, выполняемого вне EDT, потому что выполнение этого в EDT потребует задержки или хакерства, или и того, и другого. - person Charles Goodwin; 01.08.2011
comment
Рисование в AWT и Swing: поддержка двойной буферизации может быть уместно: действительно важным параметром является JRootPane, потому что этот параметр фактически включает двойную буферизацию для всего, что находится под компонентом Swing верхнего уровня. У меня никогда не было причин его выключать. Насколько я знаю, все существующие механизмы рендеринга хоста являются однопоточными. Почему бы не использовать EDT? - person trashgod; 02.08.2011
comment
Структура приложения и задержка. Рассматриваемое приложение имеет собственный механизм сценариев и компоновки, которые интегрированы и управляют рендерингом. Думайте об этом как об игре, а не приложении (хотя это последнее) с точки зрения требований к рендерингу. Он рендерится в резервный буфер по запросу, который затем отображается на экране. И EDT, и поток приложения, работающий с одним и тем же изображением (бэкбуфером), имеют тенденцию вызывать незначительные проблемы. - person Charles Goodwin; 02.08.2011
comment
Было бы правильно сказать, что модель и представление вашего существующего приложения не могут быть легко распутаны. - person trashgod; 02.08.2011
comment
Самый близкий аналог, который я видел, это Processing, упомянутый здесь. - person trashgod; 02.08.2011

По умолчанию Swing имеет двойную буферизацию, поэтому обычно вам нужно сосредоточиться только на рисовании.

Вот версия Swing:

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);
    }

}
person camickr    schedule 01.08.2011
comment
Моя вина, но я сделал этот вопрос слишком двусмысленным, и последующие ответы упускают суть, заставляя вас отказаться от парадигмы Swing render-in-EDT. Это для полностью пользовательского пользовательского интерфейса, без необходимости Swing или AWT. Рисование в EDT нежелательно для этого сценария, так как требует жонглирования циклом приложения и циклом рендеринга, где рендеринг полностью индивидуален. - person Charles Goodwin; 01.08.2011