Swing / JFrame vs AWT / Frame для рендеринга вне EDT - PullRequest
6 голосов
/ 01 августа 2011

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

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

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

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

Итак, что лучше, 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());
}

}

Ответы [ 2 ]

2 голосов
/ 01 августа 2011

Расширяя @ 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.
  • * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PanelUI
2 голосов
/ 01 августа 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);
    }

}
...