Оглядываясь назад, я еще не дал +100, так как эта реализация рисует в EDT, что как бы ломает модель. Он синхронизирован, поэтому он может работать в модели визуализации с внешним EDT, и я проверю это и вернусь к вам.

трю на это в течение нескольких месяцев, и пока это лучшее, что я придумал.

Структура (визуализация вне EDT) не подлежит обсуждению, так как наше приложение работает таким образом и не будет переписано. Приложение имеет модель макета и модель сценариев, которые интегрированы и управляют рендерингом, поэтому рендеринг должен выполняться вне модели рисования AWT.

Я пытаюсь прийти к оптимальному и надежному способу выполнения пользовательского рендеринга.

Следующий SSCCE работает довольно хорошо для нас. Однако при изменении размеров кадра у него есть 2 недостатка:

Иногда наблюдается мерцание, особенно при быстром изменении размераХак с "плавным изменением размера", который должен вызывать изменение размера (через checkSize здесь) из вызова paint (), хорошо работает только для расширений. При уменьшении кадра он обычно не рендерится, пока не отпущена кнопка мышиКроме того, но здесь это не так очевидно, он создает случайные исключения IllegalStateExceptions - это нормально, просто перехватывать / игнорировать их?

Также полезно указать, является ли это оптимальным подходом для пользовательского пути рендеринга, который происходит за пределами EDT. Я попробовал больше всего, и сделал довольно обширные исследования. Эта комбинация (образ буфера, стратегия двойного буфера), кажется, работает лучше всего.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;

public class SmoothResize extends Frame implements ComponentListener, MouseMotionListener {

    public SmoothResize() {
        addComponentListener(this);
        addMouseMotionListener(this);
    }

    private boolean sizeChanged = false;
    private Dimension old = new Dimension(0, 0);
    private synchronized void checkSize(String source) {
        int width = getWidth();
        int height = getHeight();
        if (old.width == width && old.height == height)
            return;
        sizeChanged = true;
        String type =
            (old.width > width && old.height > height) ? "shrink" :
                (old.width < width && old.height < height) ? "expand" : "resize";
        System.out.println(source + " reports " + type + ": "+getWidth()+", "+getHeight());
        old.setSize(width, height);
    }

    public void componentResized(ComponentEvent arg0) { checkSize("componentResized"); }
    public void mouseMoved(MouseEvent e) { checkSize("mouseMoved"); }
    public void paint(Graphics g) { checkSize("paint"); }
    public void update(Graphics g) { paint(g); }

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

    private synchronized void render() {
        BufferStrategy strategy = getBufferStrategy();
        if (strategy==null || !sizeChanged) return;
        sizeChanged = false;
        // 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 {
                System.out.println("render");
                Graphics draw = strategy.getDrawGraphics();
                Insets i = getInsets();
                int w = getWidth()-i.left-i.right;
                int h = getHeight()-i.top-i.bottom;
                draw.setColor(Color.YELLOW);
                draw.fillRect(i.left, i.top+(h/2), w/2, h/2);
                draw.fillRect(i.left+(w/2), i.top, w/2, h/2);
                draw.setColor(Color.BLACK);
                draw.fillRect(i.left, i.top, w/2, h/2);
                draw.fillRect(i.left+(w/2), i.top+(h/2), w/2, h/2);
                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());
    }

    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);
        while (true) {
            srtest.render();
        }
    }

    public void componentHidden(ComponentEvent arg0) { }
    public void componentMoved(ComponentEvent arg0) { }
    public void componentShown(ComponentEvent arg0) { }

    public void mouseDragged(MouseEvent e) { }
}

Ответы на вопрос(2)

Ваш ответ на вопрос