Java рисовать для графики в собственном потоке, вне EDT? - PullRequest
2 голосов
/ 14 января 2020

Я пишу Swing-приложение, оно использует Apache PDFBox для рисования страницы PDF в объекте Graphics2D JPanel в методе paintComponent. Рисование занимает некоторое время, поэтому, когда моему приложению нужно одновременно отобразить много страниц PDF, оно становится медленным и медленным. Я знаю, что поскольку JPanel, на которую я рисую страницу PDF, является частью GUI, она должна быть нарисована в потоке отправки событий. Но нет ли абсолютно никакой возможности нарисовать каждый JPanel в отдельном потоке? Как использовать SwingWorker или около того?

Пример кода (упрощенный):

public class PDFPanel extends JPanel {
    @Override
    protected void paintComponent(Graphics graphics) {
        super.paintComponent(graphics);

        Graphics2D g2 = (Graphics2D) graphics;
        int scale = 1;   // (simplified this line)

        g2.setColor(getBackground());
        g2.fillRect(0, 0, getWidth(), getHeight());

        try {
            pdfRenderer.renderPageToGraphics(pageNumber, g2, (float) scale, (float) scale);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

1 Ответ

3 голосов
/ 14 января 2020

Используйте BufferedImage поле изображения. У него есть метод createGraphics(), где вы можете рисовать. Позже позвоните Graphics.dispose(), чтобы очистить ресурсы.

Затем в paintComponent проверьте доступность изображения для его отображения.

Рендеринг может быть выполнен в Future, SwingWorker или любом другом , Вы правы в том, что тяжелые операции никогда не должны выполняться в paintComponent, особенно потому, что они могут вызываться повторно.

Лучше запустить рендеринг в конструкторе или в вашем контроллере.

    BufferedImage image = new BufferedImage(getWidth(), getHeight(),
        BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = image.createGraphics();
    try {
        pdfRenderer.renderPageToGraphics(pageNumber, g2, (float) scale, (float) scale);
    } finally {
        g2d.dispose();
    }

Первоначально ширина и высота не заполнены, поэтому лучше использовать ширину и высоту из PDF. Также не то, что Graphics2D позволяет масштабировать; Вы можете легко добавить масштабирование.

Как атомарно обрабатывать прохождение отрендеренного изображения, вероятно, понятно.

...