Обычная версия
Java форум JavaTalks
форум программистов

Поиск   Пользователи   Группы   Регистрация 
 Профиль   Личные сообщения 

 Вход 

Swing. Frame Repaint. More than 1000 fps. @ tilex
Список форумов
 ->  Примеры


 
Начать новую тему 
Предыдущая тема :: Следующая тема  
Автор Сообщение
Jean : 1992
JavaTalks Team Member
Откуда: Санкт-Петербург

СообщениеФев 13, 2010 19:33 
Ответить с цитатой
Данный пример написан tilex

Пример показывает, как сделать очень быстрый цикл с постоянной перерисовкой всего изображения в окне, как это обычно происходит в играх. Такой режим в терминах Swing называется active rendering. Используется аппаратная двойная буферизация через объект java.awt.image.BufferStrategy. Пример написан с учетом рекомендаций, данных здесь: http://java.sun.com/docs/books/tutorial/extra/fullscreen/index.html

Код:

package test;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferStrategy;
import java.util.Random;
import javax.swing.*;

public class FastFrame extends JFrame implements Runnable {

    private long startTime = 0;
    private long frames = 0;
    private int width, height;
    private GraphicsDevice device = null;
    private boolean running = false;

    private FastFrame(String title, int width, int height) {
        super(title);
        this.width = width;
        this.height = height;

        // отключаем repaint и двойную буферизацию swing-компонентов,
        // потому что всё равно всё сами перерисовываем
        setIgnoreRepaint(true);
        getRootPane().setDoubleBuffered(false);
        setResizable(false);
        setVisible(true);
        // устанавливаем размеры окна такими, чтобы клиентская область окна была width x height
        Insets ins = getInsets();
        setSize(ins.left + ins.right + width, ins.top + ins.bottom + height);
        setLocationRelativeTo(null);
        init();
    }

    private FastFrame(String title, int width, int height, GraphicsDevice device) {
        super(title, device.getDefaultConfiguration());
        this.width = width;
        this.height = height;
        this.device = device;

        setIgnoreRepaint(true);
        getRootPane().setDoubleBuffered(false);
        setUndecorated(true);
        // включаем полноэкранный режим
        device.setFullScreenWindow(this);
        if (device.isDisplayChangeSupported()) {
            device.setDisplayMode(new DisplayMode(width, height, 32, DisplayMode.REFRESH_RATE_UNKNOWN));
        }
        init();
    }

    private void init() {
        // время нужно для подсчета fps
        startTime = System.currentTimeMillis();
        // включаем аппаратную двойную буферизацию
        createBufferStrategy(2);

        addWindowListener(new WindowAdapter() {
            @Override public void windowClosing(WindowEvent ev) {
                close();
            }
        });
        addKeyListener(new KeyAdapter() {
            @Override public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                    close();
                }
            }
        });

        Thread th = new Thread(this);
        running = true;
        th.start();
    }

    private void close() {
        running = false;
        // показываем fps
        System.out.println("FPS: " + frames * 1000 / (System.currentTimeMillis() - startTime));
        // если мы в полноэкранном режиме, возвращаемся в исходный режим
        if (device != null) {
            device.setFullScreenWindow(null);
        }
        System.exit(0);
    }

    public static FastFrame create(String title, int width, int height, boolean fullscreen) {
        if (fullscreen) {
            GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
            GraphicsDevice device = env.getDefaultScreenDevice();
            return new FastFrame(title, width, height, device);
        } else {
            return new FastFrame(title, width, height);
        }
    }

    public void run() {
        BufferStrategy bs = getBufferStrategy();
        while (running) {
            Graphics2D g = (Graphics2D) bs.getDrawGraphics();

            // т.к. аппаратный буфер создается для всего окна целиком,
            // то при перерисовке приходится учитывать размер рамки и заголовок окна,
            // чтобы рисовать только в клиентской области окна
            Insets ins = getInsets();

            // выводим 1000 случайных линий
            g.clearRect(ins.left, ins.top, width, height);
            Random rnd = new Random();
            for (int i = 0; i < 1000; i++) {
                int x1 = ins.left + rnd.nextInt(width);
                int y1 = ins.top + rnd.nextInt(height);
                int x2 = ins.left + rnd.nextInt(width);
                int y2 = ins.top + rnd.nextInt(height);
                g.drawLine(x1, y1, x2, y2);
            }

            // обязательно
            g.dispose();
            // выводим буфер на экран
            bs.show();
            // ждем завершения всех аппаратных операций
            Toolkit.getDefaultToolkit().sync();
            frames++;

            // чтобы сильно не нагружать процессор, надо вставить небольшую паузу
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {}
            // если fps критичен и надо выжать максимум,
            // то Thread.sleep() надо заменить на Thread.yield()

            // на тестовой машине этот пример со sleep() дает около 400 fps (загрузка CPU 1-2%),
            // с yield() - 1300 fps (загрузка CPU 100%)
        }
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {}

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                FastFrame.create("Fast Updates", 640, 480, false); // оконный режим
//              FastFrame.create("Fast Updates", 1280, 1024, true); // полноэкранный режим
            }
        });
    }
}

_________________
Всякое решение плодит новые проблемы
К началу Посмотреть профиль Отправить личное сообщение
 
Начать новую тему  Ответить на тему
Страница 1 из 1
Список форумов
 -> Примеры


 
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Java and all Java-related trademarks and logos are trademarks or registered trademarks of Oracle Corporation in the United States and other countries.
Это сайт не относится к фирме Oracle Corporation и не поддерживается ею.

© 2006-2010 www.javatalks.ru: форум java программистов
Используется скрипт phpBB © 2001, 2010 phpBB Group

Хостинг от bizname.ru