|
Модераторы: LSD, AntonSaburov |
|
SplinterL |
|
||||
Новичок Профиль Группа: Участник Сообщений: 3 Регистрация: 29.6.2006 Репутация: нет Всего: нет |
Делаю программу, которая должна отрисовывать графику на отдельной панели в том же окне , что и основная программа. При перетаскивании этой графики мышкой, она не должна мерцать. Для этого я использовал двойную буферизацию. Делал, так как описано в книге по Java, но во-первых изображение все равно мерцает, а во-вторых на панели где должна отрисовываться графика, рисуется еще и весь интерфейс программы: все кнопки и текстовые поля. Подскажите где я допускаю ошибку в коде и как правильно реализовывать двойную буферизацию в GUI приложениях?
Surface - панель где рисуется графика. Вставляется в основную программу так:
Код класса Surface:
|
||||
|
|||||
powerOn |
|
|||
software saboteur Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 31 Всего: 159 |
Это означает, что ты перерисовываешь только сам компонент, а прорисовать его контейнер забываешь Вызывай метод repaint() для контейнера в котором находится целевой компонент и все будет в порядке. Например, если ты рисуешь на JPanel, которая находится на JFrame, то вызывай repaint для JFrame (или для ContentPane этого JFrame). Он пререрисует себя и свои компоненты. |
|||
|
||||
Samuil |
|
|||
в(Job)ываю Профиль Группа: Участник Сообщений: 705 Регистрация: 26.4.2006 Где: Uzbekistan.Tashke nt Репутация: нет Всего: 6 |
|
|||
|
||||
powerOn |
|
|||
software saboteur Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 31 Всего: 159 |
Samuil, а про комментировать код? Что он делает то?
|
|||
|
||||
SplinterL |
|
|||
Новичок Профиль Группа: Участник Сообщений: 3 Регистрация: 29.6.2006 Репутация: нет Всего: нет |
Samuil, твой код не помогает. Все работает как и раньше: мерцает и под слоем графики рисуется интерфейс.
MoonCat, где писать repaint() для контейнера, в основной программе? Разъясни пожалуйста.... Лучше всего кодом. Значит пойду читать тексты программ, которые к jsdk прилагаются, у них то все работает.. |
|||
|
||||
powerOn |
|
|||
software saboteur Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 31 Всего: 159 |
||||
|
||||
powerOn |
|
||||
software saboteur Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 31 Всего: 159 |
Вот пример кода.
Панель:
Фрайм для запуска.
|
||||
|
|||||
SplinterL |
|
|||
Новичок Профиль Группа: Участник Сообщений: 3 Регистрация: 29.6.2006 Репутация: нет Всего: нет |
MoonCat твой код тоже не работает, ЧЕСТНО! Когда синий квадрат на белом фоне двигаешь то все нормально. А когда попробуешь что-нибудь посложнее вроде
то изображение начинает мерцать, когда его передвигаешь или если двигаешь все окно целиком. Я специально проверил стандартные программы из jsdk. В них все нормально. ? |
|||
|
||||
Samuil |
|
|||
в(Job)ываю Профиль Группа: Участник Сообщений: 705 Регистрация: 26.4.2006 Где: Uzbekistan.Tashke nt Репутация: нет Всего: 6 |
Привет вот код только ошибки в нем есть придется тебе исправлять!
Улучшение изображения двойной буферизацией Суть двойной буферизации в том, что в оперативной памяти создается буфер — объект класса image или Bufferedimage, и вызывается его графический контекст, в котором формируется изображение. Там же происходит очистка буфера, которая тоже не отражается на экране. Только после выполнения всех действий готовое изображение выводится на экран. Все это происходит в методе updateo, а метод paint о только обращается к update (). Листинги 15.10—15.11 разъясняют данный прием. Листинг 15.10. Двойная буферизация с помощью класса image public void update(Graphics g){ int w = getSize().width, h = getSize().height; // Создаем изображение-буфер в оперативной памяти Image offlmg = createlmage(w, h); // Получаем его графический контекст Graphics offGr = offImg.getGraphics(); // Меняем текущий цвет буфера на цвет фона offGr.setColor(getBackground()); //и заполняем им окно компонента, очищая буфер offGr.fillRect(0, 0, w, h); // Восстанавливаем текущий цвет буфера offGr.setColor(getForeground()); // Для листинга 15.9 выводим в контекст изображение offGr.drawlmage(img[count % 10], 0, 0, this); // Рисуем в графическом контексте буфера // (необязательное действие) paint(offGr); // Выводим изображение-буфер на экран // (можно перенести в метод paint()) g.drawlmage(offlmg, 0, 0, this); } // Метод paint() необязателен public void paint(Graphics g)J update(g); } Листинг 15.11. Двойная буферизация с помощью класса Bufferedimage public void update(Graphics g){ Graphics2D g2 = (Graphics2D},g; int w = getSize().width, h = getSize().height; // Создаем изображение-буфер в оперативной памяти Bufferedimage bi = (Bufferedimage)createlmage(w, h); // Создаем графический контекст буфера Graphics2D big = bi.createGraphics(); // Устанавливаем цвет фона big.setColor(getBackground()); // Очищаем буфер цветом фона big.clearRect(0, 0, w, h); // Восстанавливаем текущий цвет big.setColor(getForeground()); // Выводим что-нибудь в графический контекст big // ... // Выводим буфер на экран g2.drawImage(bi, 0, 0, this); } Метод двойной буферизации стал фактическим стандартом вывода изменяющихся изображений, а в библиотеке Swing он применяется автоматически. Данный метод удобен и при перерисовке отдельных частей изображения. В этом случае в изображении-буфере рисуется неизменяемая часть изображения, а в методе paint() — то, что меняется при каждой перерисовке. В листинге 15.12 показан второй способ анимации — кадры изображения рисуются непосредственно в программе, в методе update (), по заданному закону изменения изображения. В результате красный мячик прыгает на фоне изображения. Листинг 15.12. Анимация рисованием import Java.awt.*; import j ava.awt.event.*; import Java.awt.geom.*; import java.awt.image.*; class DrawAniml extends Frame{ private Image img; private int count; DrawAniml(String s) { super(s); MediaTracker tr = new MediaTracker(this); img = getToolkit().getlmage("back2.jpg"); tr.addlmage(img, 0); try{ tr.waitForlD(0) ; }catch(InterruptedException e) {} SetSize(400, 400); setvisible(true); } public void update(Graphics g){ Graphics2D g2 = (Graphics2D)g; int w = getSizeO.width, h = getSize().height; Bufferedlmage bi = (Bufferedlmage)createlmage(w, h) ; Graphics2D big = bi.createGraphics(); // Заполняем фон изображением img big.drawlmage(img, 0, 0, this); // Устанавливаем цвет рисования big.setColor(Color.red); // Рисуем в графическом контексте буфера круг, // перемещающийся по синусоиде big.fill(new Arc2D.Double(4*count, 50+30*Math.sin(count), 50, 50, 0, 360, Arc2D.OPEN)); // Меняем цвет рисования big.setColor(getForeground()); // Рисуем горизонтальную прямую big.draw(new Line2D.Double(0, 125, w, 125)); // Выводим изображение-буфер на экран g2.drawlmage(bi, 0, 0, this); } public void go(){ while(count < 100){ repaint(); try{ Thread.sleep(10); }catch(InterruptedException e){} count++; } } public static void main(String[] args){ DrawAniml f = new DrawAniml(" Анимация"); f.go(); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent ev){ System.exit(0); } }); } } Эффект мерцания, переливы цвета, затемнение и прочие эффекты, получающиеся заменой отдельных пикселов изображения, удобно создавать с помощью класса Memoryimagesource. Методы newPixeis() этого класса вызывают немедленную перерисовку изображения даже без обращения к методу repaint(), если перед этим выполнен метод setAnimated(true). Чаще всего применяются два метода: newPixels(int x, int y, int width, int height) — получателю посылается указанный аргументами прямоугольный фрагмент изображения; nevPixels() — получателю посылается все изображение. В листинге 15.13 показано применение этого способа. Квадрат, выведенный на экран, переливается разными цветами. Листинг 15.13. Анимация с помощью MemorylmageSource import Java.awt.*; import java.awt.event.*; import java.awt.image.*; class InMemory extends Frame{ private int w = 100, h = 100, count; private int[] pix = new int[w * h]; private Image img; MemorylmageSource mis; InMemory(String s){ super(s); int i = 0; for(int у = 0; у < h; y++){ int red = 255 * у / (h - 1); for(int x = 0; x < w; x++){ int green = 25$ * x / (w - 1); pix[i++] = (255 « 24}|(red << 16)|(green << 8) | 128; } } mis = new MemorylmageSource(w, h, pix, 0, w); // Задаем возможность анимации mis.setAnimated(true); img = createImage(mis); setSize(350, 300); setVisible(true); } public void paint(Graphics gr){ gr.drawImage(img, 10, 30, this); } public void update(Graphics g) { paint(g); } public void got){ while (count < 100){ int i = 0; // Изменяем массив пикселов по некоторому закону for(int у - 0; у < h;,y++) for (int x. = 0; x < w; x++) pix[i++J = (255 « 24)|(255 + 8 * count « 16)| (8*count «8)| 255 + 8 * count; // Уведомляем потребителя об изменении mis.newPixels(); try{ Thread.sleep(100); }catch(InterruptedException e){} count++; } } public static void main(String[] args){ InMemory f= new InMemory(" Изображение в памяти"); f.go(); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent ev){ System.exit(0); } )); } } Вот и все средства для анимации, остальное — умелое их применение. Комбинируя рассмотренные способы, можно добиться удивительных эффектов. В документации SUN J2SDK, в каталогах demo\applets и demo\jfc\Java2D \src, приведено много примеров апплетов и приложений с анимацией. |
|||
|
||||
powerOn |
|
|||
software saboteur Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 31 Всего: 159 |
SplinterL, примеры, кстати, с исходниками идут, посмотри как там прорисовка идет и сделай по аналогии Samuil, используй кнопку код для оформления исходников. И если это не твои мысли, то лучше просто выложить ссылку на источник, чем копировать все сюда в качестве ответа. http://www.lib.csu.ru/dl/text/programm/inf...a15/Index13.htm |
|||
|
||||
Правила форума "Java" | |
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, jk1. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java: GUI и Java FX приложения | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |