Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Java Модуль 1.docx
Скачиваний:
4
Добавлен:
01.07.2025
Размер:
2.24 Mб
Скачать

Занятие 6. Работа с графическими изображениями

Откроем студию разработки Eclipseи создадим новый проект с номером нашего занятия – 6.

Удалим появившуюся заготовку программы, т.к. сегодня мы будем использовать начальную заготовку программы,сделанную нами на прошлом занятии. Откроем программу прошлого занятия с готовым исходным кодом, скопируем этот и вставим его в наш новый проект. Поменяем номер урока в комментарии и изменим название класса с prog5на prog6. У нас получится следующий программный код:

// Урок №6

import javax.swing.*;

import java.awt.*;

public class prog6 {

public static void main(String[] args) {

myFrame okno = new myFrame();

}

}

class myFrame extends JFrame

{

public myFrame()

{

myPanel np = new myPanel(); // Создаем панельобъект

// Создаем переменную для связывания

// окна и панели

Container cont = getContentPane();

cont.add(np); // Добавляем, прикрепляем панель к окну

setBounds(10, 10, 800, 600);

setVisible(true);

}

}

class myPanel extends JPanel

{

public void paintComponent(Graphics gr)

{

gr.setColor(Color.BLUE);

for (int i=0;i<10;i++)

{

gr.fillRect(10*i, 10*i, 50*i, 50*i);

}

}

}

Рассмотрим исходный код и, комментируя его, повторим основные моменты прошлого занятия.

Начнем с команды import,которая осуществляет добавление библиотек для возможности их использования в нашей программе. Библиотека – это набор определенных функций, вызываемых в виде команд для выполнения тех или иных задач.

Перейдём к блоку Основной класс программы. Этот класс всегда называется так же, как и имя файла,содержащего программу. В данном случае – prog6.Внутри этого класса находится метод, который создаётся при установке галочки для создания классов public static void main. Метод main – метод, запускающий программу.

После запуска программа сразу переходит на строку myFrame okno = new myFrame();, которая создает объект окна на основании класса,который описан ниже: class myFrame extends JFrame. Внутри этого класса описывается настройка, связанная с окном. Слово class говорит о том, что создан класс под названием myFrame. Название класса может быть произвольным, как и название переменой. Оператор extendsприсваивает классу myFrame наследование свойств класса JFrame,класса всех окон. myFrame – это тоже класс окон, с наследованными у класса JFrameсвойствами, а значит, имеющий все возможности окна. Класс myFrame содержит один метод. Метод производит инициализацию окна, т. е., содержит основные настройки, задающие размер окна и положение на экране.

setBounds – установка положения окна и его размеров. Первые две характеристики, это положение верхней левой точки окна, далее ширина, затем высота.

myPanel - это тип переменной под названием np. В части new myPanel();мы создаем объект под названием np.Эта панель будет вставлена в наше окно. На ней будет отображаться графика:определенные картинки, загруженные из файлов или созданные нами при помощи операторов рисования геометрических фигур. Панель представляет из себя прямоугольную область, размещённую внутри окна. Далее идёт строка Container,позволяющая подключать к окну компоненты, т. е. связать их в единое целое. Эта связка происходит через переменную под названием сont. Название может быть любым, но желательно имя переменой задавать созвучным её назначению. Cтрока сont.add(),добавить, в скобках указано: np.Эта строка прикрепляет панель к нашему окну – вкладывает её в окно. Cтрока setVisibleпозволяет сделать окно видимым, т. е. отобразить его на экране: значение true– истина – говорит о том, что окно должно быть показано. Этот класс и создает шаблон для формирования окна. На основании шаблона можно создать реальный объект: строка myFrame okno = new myFrame();. Спустимся ещё ниже. Здесь описан ещё один класс, – класс под названием myPanel, он наследуется от класса JPanel. Класс JPanel–класс панелей, которые можно размещать внутри окна.

Метод – public void paintСomponent используется для возможности рисования на панели или отображения внешних графических файлов с диска. В конце прошлого занятия мы с вами вывели при помощи цикла for внутри этого метода несколько синих закрашенных квадратов. Часть кода, размещённая в теле этого метода, в фигурных скобках, будет отображать созданную нами графику на панели окна, вставленной в окно. В строчке myPanel np =new myPanel(); создаётся объект np на основании класса myPanel.

Мы продолжаем работать с графикой в среде разработки приложений на языке программирования Javaи сейчас мы рассмотрим работу с изображениями, находящимися в графических файлах.

Для возможности использования изображений, хранящихся в файлах на вашем компьютере, при создании приложений, их следует в программу загрузить. Откроем заранее заготовленный на диске Сфайл с изображением нашей планеты (cм. рисунок48).

Рисунок 48

Любое изображение можно поместить в прямоугольную область (в данном случае, в квадратную). Именно эта область определяет характеристики изображения. Представим, что прямоугольник внутри нашего окна – это панель, и зададим расположение точки, относительно которой рассчитывается положение объекта (верхний левый угол – начало координат). Чтобы задать положение этого изображения в нашем окне, нужно указать отступ по X и отступ по Y (в количестве пикселей) – координаты верхнего левого угла изображения. После этого следует задать ширину изображения – width и высоту изображения – height. Эти характеристики присутствуют у любого изображения. Выведем в окно изображение,помещённое на диск C. Для этого в класс под названием myPanel добавим новую переменную. Объявим её в самом верху класса после открывающей фигурной скобки. Используем модификатор private,тогда переменная класса будет закрытой, т. е. доступной только внутри класса.Далее мы указываем ее тип: Image, то есть изображение и её имя, например, img. Мы создали переменную класса, являющуюся картинкой: private Image img;.Далее добавим новый метод под названием public myPanel, а код внутри метода public void paintСomponent удалим, класс myPanel теперь будет выглядеть так:

class myPanel extends JPanel

{

private Image img;

public myPanel()

{

}

public void paintComponent(Graphics gr)

{

}

}

В метод public myPanel() следует добавить строки:

try

{

img = ImageIO.read(new File("c:\\m.gif"));

}

catch(IOException exp) {}

В самом верху под комментарием с номером урока добавим:

import javax.imageio.*;

import java.io.*;

А внутри метода public void paintComponent(Graphics gr) добавим строку:

gr.drawImage(img,10,10,null);

После этого у нас получится программа, как на (cм. рисунок 49).

Рисунок 49

В верхних двух строчках мы подключили при помощи importдве библиотеки, которые нужны для загрузки графических файлов. При помощи команды img = ImageIO.read(new File("c:\\m.gif")); мы загрузили в нашу программу файл под названием, в нашем случае, m.gif, который находится на диске C.

Часть строки ImageIO.readвыполняет функцию чтения изображения. В первых круглых скобках создаётся новый объект типа File: new File,во внутренних скобках указывается конкретный путь к месту нахождения изображения на диске С. Т. е. часть строки new File создает объект типа Fileи путь к этому файлу "c:\\m.gif".Путь указывается в двойных кавычках, как строка. Т. е. путь является строковым типом, String. Обратите внимание, при описании пути необходимо указывать именно две косые черты \\.Одна косая черта является специальным символом. Чтобы дать понять компилятору,что это не специальный символ, а косая черта – их нужно писать две. Изображение загружается и связывается с переменной img,специально для этого созданной. Её тип Image– картинка. Чуть-чуть ниже, там, где мы работаем с графикой и можем выводить её на панель, мы добавили строку gr.drawImage(img,10,10,null);, котораявыводит этот файл на нашу панель окна.

Мы обратились к переменной с именем gr типа Graphics,которая отвечает за выведение графики на нашу панель. В дальнейшем, для произведения графических манипуляций мы будем обращаться к этой переменной.

Метод drawImageотвечает за выведение изображения на экран. Первый параметр – изображение img, которое мы выводим (это та переменная,которую мы создали, и затем загрузили в неё изображение). Вторые два параметра в круглых скобках этой строки – два числа, координаты угловой точки. Первая координата – Х и вторая Y. Значения 10, 10 говорят о том, что изображение выводится почти из верхнего левого угла окна. Последний параметр в круглых скобках не указан. Неуказанные параметры отображаются, как null –специальное служебное слово, говорящее о том, что параметр пустой.

Попробуем запустить нашу программу, и если она написана без ошибок, то мы увидим изображение, выведенное на экран. Координата 10, 10 находится в левом верхнем углу окна, именно из этой точки начинается прямоугольник, содержащий изображение. Соответственно,если эту координату поменять и поставить, например, 200, 200, –после выполнения программы можно увидеть, что изображение сместилось, так как точка его начала координат переместилась. Таким образом, можно менять положение изображения на рабочей области и выводить его в любой точке. Можно использовать любые картинки, изображения, подготовленные в каком-либо графическом редакторе.К примеру, можно взять что-то готовое, и использовать в программах, например,для оформления какой-то игры, чтобы наполнить ее дизайном и графическими объектами.

Теперь перейдём к понятию анимация.Анимация движений – это перемещение графического объекта по определённой области или его изменение, в данном случае, области панели,вложенной в окно.

Можно заложить траекторию движения изображения, например, прямую линию. Вдоль этой линии будет двигаться заданный объект. Можно взять более сложную траекторию движения, например,окружность. Тогда объект будет двигаться по окружности. Для создания нашей анимации нам нужно выполнить несколько действий:

во-первых, перемещать изображение на небольшое расстояние(пошагово). Если необходимо перемещать изображение по диагонали, его координату по X и Y нужно изменять на один пиксель, тогда оно переместится совсем немного.

во-вторых, после перемещения очистить его предыдущее положение (ещё лучше это сделать до перемещения: перед тем, как поместить изображение в новую точку).

Тогда изображение будет двигаться. В зависимости от того, насколько пикселей за шаг перемещается изображение, меняется плавность его движения. Есть еще одно необходимое условие- определенная временная задержка. Если её не предусмотреть,после запуска программы по перемещению изображения, например, вдоль прямой линии, компьютер выполнит это действие мгновенно, и изображение промелькнёт на экране, но заметить это будет практически невозможно, останется лишь след.Поэтому необходимо задавать скорость движения объекта, не зависящую от скорости работы компьютера. Перед переходом на новый кадр, на новое положение изображения, делается временная задержка, допустим, какая-то доля секунды. Для этого есть специальный инструмент – таймер. Таймер позволяет выполнять задержку с точностью до одной тысячной секунды, т. е. тысяча единиц параметра таймера равна одной секунде. Попробуем создать этот инструмент и начнем с ним работать. Добавим ещё несколько полей в наш класс и назовем их x и y. Зададим им начальное значение 0 и 0.

class myPanel extends JPanel

{

private int x=0,y=0;

Это переменные x и y целого типа, они так же закрытые – private, то есть доступны только внутри класса. Переменные x и y будут отвечать за положение нашего изображения на экране, то есть за положение верхней левой точки. Меняя значение переменных x и y, можно перемещать объект. Чтобы перемещение не оставляло следа и получилась реальная анимация,перед тем как отобразить изображение в новом месте, нужно очистить область от прежнего изображения. Для этой цели применяется метод clearRect– очищение прямоугольной области. Добавим над строкой вывода изображения строчку:

gr.clearRect(x-1, y-1, img.getWidth(null)+1, img.getHeight(null)+1);

и в самой строке вывода поменяем значения координат 10, 10 на xи y. Получится следующий фрагмент программного кода:

public void paintComponent(Graphics gr)

{

gr.clearRect(x-1, y-1, img.getWidth(null)+1, img.getHeight(null)+1);

gr.drawImage(img,x,y,null);

}

Обращение к методам очищения и вывода идёт через переменную gr, типа Graphics. Внутри круглых скобок метода gr.clearRect,указываются: первые два параметра – координаты верхней левой точки прямоугольной области очищения. Если перемещать объект на один пиксель,достаточно делать очищение в радиусе плюс минус один пиксель (x-1 и y-1).Получается точка, удалённая на один пиксель по xи по y, соответственно, вверх и влево.Вторые два параметра: ширина и высота прямоугольной области очищения. Обратимся к изображению img и вызовем команду getWidth(null), позволяющую вычислить ширину изображения выведенного на экран. null говорит о том, что параметр не указывается, он остается пустым. Снова обращаемся к изображению imgи вызываем команду getНеight(null), она задаёт высоту нашего графического объекта. Именно эти два параметра указывают на ширину и высоту области, которая будет очищена. К высоте и ширине прибавляем по одному пикселю, чтобы охватить чуть больший фрагмент, потому что объект каждый раз перемещается на один пиксель. Перед тем, как выводить изображение в новом положении панели, программа будет производить очищение области, большей на единицу со всех сторон. Так осуществляется анимация, т. е. движение.

Теперь добавим несколько строчек для работы с таймером. Их необходимо поместить в метод public myPanel():

public myPanel()

{

Timer nt = new Timer(50,new ActionListener() {

public void actionPerformed(ActionEvent e) {

x++;

repaint();

}

});

nt.start();

Таким образом, мы создали таймер,он будет работать с нашим приложением. Первый параметр, который необходимо указать - его временную задержку. Мы указали 50, это значит, что задержка будет 50 тысячных секунды. При срабатывании таймера будет происходить отрисовка заданной области, т. е. панели. Метод repaint();вызывает перерисовку, вызывает на исполнение метод public void paintComponent(Graphics gr), он заново перерисовывает заданную область.В нем у нас выполняются две команды – очищение области с положением изображения на предыдущем шаге и вывод изображения в новом месте. Перерисовка будет выполняться 20 раз в секунду – именно этому соответствует задержка 50 тысячных секунды.

Сверху подключим еще одну библиотеку, она нужна для работы с таймером:

import java.awt.event.*;

Запустим программу и увидим перемещение, анимацию нашего изображения. Полный код программы должен выглядеть так:

// Урок №6

import javax.imageio.*;

import java.io.*;

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class prog6 {

public static void main(String[] args) {

myFrame okno = new myFrame();

}

}

class myFrame extends JFrame

{

public myFrame()

{

myPanel np = new myPanel(); // Создаем панельобъект

// Создаем переменную для связывания

// окна и панели

Container cont = getContentPane();

cont.add(np); // Добавляем, прикрепляем панель к окну

setBounds(10, 10, 800, 600);

setVisible(true);

}

}

class myPanel extends JPanel

{

private int x=0,y=0;

private Image img;

public myPanel()

{

Timer nt = new Timer(50,new ActionListener() {

public void actionPerformed(ActionEvent e) {

x++;

repaint();

}

});

nt.start();

try

{

img = ImageIO.read(new File("c:\\m.gif"));

}

catch(IOException exp) {}

}

public void paintComponent(Graphics gr)

{

gr.clearRect(x-1, y-1, img.getWidth(null)+1, img.getHeight(null)+1);

gr.drawImage(img,x,y,null);

}

}

Добавим на одну строку ниже от объявления переменных x и y еще одну, переменную целого типа и назовем её napr, присвоим ей начальное значение равное 2,переменная будет закрытой:

private int napr = 2;

Переменная napr отвечает за направление движения графического объекта.Договоримся, что у нас будет четыре возможных направления: вверх, вниз,вправо, влево. Каждое из направлений будет обозначаться цифрой 0,1,2,3.Тогда 2 отвечает за движения вправо. Если napr=2, объект перемещается в правом направлении. Теперь вместо строки x++;- там где мы создавали таймер, поместим строки:

if (napr==0) x--;

if (napr==1) y--;

if (napr==2) x++;

if (napr==3) y++;

Операция x--; означает, что значение x будет уменьшаться на единицу. Если x был равен 100, после выполнения этой операции он станет равным 99. Еслиnapr==0, координата xуменьшится на единицу. Если napr==1,координата y уменьшится на единицу. Если napr==2, координата xувеличится на единицу. И, наконец, если napr==3,координата y увеличится на единицу.

Мы прописали следующее условие:если направление равно 0, координата Х будет уменьшаться на единицу, и объект перемещается влево. Если направление равно 1, y уменьшается и объект перемещается вверх. Если направление равно 2, x увеличивается на единицу, и объект перемещается вправо. И, наконец, если направление равно 3,координата y увеличивается, объект будет перемещаться вниз. Таким образом, можно работать с четырьмя направлениями движения.

Часть программного кода,описывающая таймер теперь будет выглядеть так:

Timer nt = new Timer(50,new ActionListener() {

public void actionPerformed(ActionEvent e) {

if (napr==0) x--;

if (napr==1) y--;

if (napr==2) x++;

if (napr==3) y++;

repaint();

}

});

nt.start();

Последняя строка этого кода nt.start(); запускает таймер. После ее выполнения таймер начинает работать. Давайте чуть-чуть поменяем скорость движения объекта, изменим задержку с 50 на 100и запустим программу, вы увидим, что объект стал двигаться медленнее. А теперь поменяем ее на 25, мы увидим, что объект стал двигаться быстрее.

Для создания любой компьютерной игры нужно обеспечить необходимое условие: возможность управления ею. Для этих целей используются, например, клавиатура или мышь. В нашем случае можно использовать клавиатуру для управления движением нашего графического объекта,каждая стрелочка будет задавать направление движения вверх, вниз,вправо или влево. При нажатии клавиши происходит определенное событие. Событие, организованное нажатием клавиши на клавиатуре.Это событие передаётся в программу, где программист может его обработать.Каждая клавиша имеет свой уникальный код, то есть номер. Допустим, стрелочка вправо имеет код 39, соответственно, каждая другая клавиша имеет другой код. По номеру нажатой клавиши, по её коду программа может четко определить, какую клавишу нажал пользователь и среагировать именно на это нажатие. Возьмём переменную под названием napr,принимающую четыре значения. Можно сделать так, что при нажатии, например, стрелочки вправо, значение переменной napr будет меняться на двойку, при нажатии клавиши вниз, оно будет меняться на тройку, при нажатии клавиши вверх – на единицу и, наконец, при нажатии клавиши влево – на ноль. Если организовать такую логику, объект будет перемещаться в зависимости от нажимаемых на клавиатуре стрелочек. Добавим программный код,позволяющий обрабатывать нажатие клавиш. Под кодом:

class myPanel extends JPanel

{

private int x=0,y=0;

private int napr = 2;

private Image img;

добавим следующий программный код:

// Обработчик событий нажатийна клавиши

private class myKey implements KeyListener

{

// Метод, который срабатывает при нажатии

public void keyPressed(KeyEvent e)

{

// Получение кода нажатой клавиши

int key_ = e.getKeyCode();

if (key_==37) napr = 0; // Если нажата стрелка влево

if (key_==39) napr = 2; // Если нажата стрелка вправо

if (key_==38) napr = 1; // Если нажата стрелка вверх

if (key_==40) napr = 3; // Если нажата стрелка вниз

}

public void keyReleased(KeyEvent e) {}

public void keyTyped(KeyEvent e) {}

}

Как работает эта конструкция, мы будем рассматривать позднее (не забывайте, что регистр букв имеет значение, заглавная и маленькая буквы считаются разными).

В строке int key_ = e.getKeyCode();объявлена переменная целого типа под названием key_. Она содержит код нажатой клавиши, номер,определяемый при помощи метода e.getKeyCode();. Далее, анализируем, какую клавишу нажимает пользователь. Если код клавиши равен 37, направление движения устанавливаем 0. Если код клавиши равен 38, указываем направление 1.Если код клавиши – 39, то направление 2. И, наконец, если код клавиши равен 40, то направление 3. Коды клавиш можно найти в любой тематической литературе, узнать в интернете. А можно сделать намного проще:написать строку вывода на экран значений переменной key_: после строки int key_ = e.getKeyCode(); вставить строку:

System.out.println(key_);

тогда при нажатии клавиши – в консольном окне будет выводиться код нажатой клавиши. Для обработки нажатий клавиш – нам осталось выполнить последнее, вставить перед объявлением таймера строки:

addKeyListener(new myKey());// Подключение обработчика события для клавиатуры к окну

setFocusable(true);

эти строки подключают обработчик событий клавиатуры к нашей панели окна. Теперь можно запустить программу, при нажатии стрелочек на клавиатуре – наш графический объект будет перемещаться в нужных направлениях. Полный код нашей программы должен выглядеть так:

// Урок №6

import javax.imageio.*;

import java.io.*;

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class prog6 {

public static void main(String[] args) {

myFrame okno = new myFrame();

}

}

class myFrame extends JFrame

{

public myFrame()

{

myPanel np = new myPanel(); // Создаем панельобъект

// Создаем переменную для связывания

// окна и панели

Container cont = getContentPane();

cont.add(np); // Добавляем, прикрепляем панель к окну

setBounds(10, 10, 800, 600);

setVisible(true);

}

}

class myPanel extends JPanel

{

private int x=0,y=0;

private int napr = 2;

private Image img;

// Обработчик событий нажатий на клавиши

private class myKey implements KeyListener

{

// Метод, который срабатывает при нажатии

public void keyPressed(KeyEvent e)

{

// Получение кода нажатой клавиши

int key_ = e.getKeyCode();

if (key_==37) napr = 0; // Если нажата стрелка влево

if (key_==39) napr = 2; // Если нажата стрелка вправо

if (key_==38) napr = 1; // Если нажата стрелка вверх

if (key_==40) napr = 3; // Если нажата стрелка вниз

}

public void keyReleased(KeyEvent e) {}

public void keyTyped(KeyEvent e) {}

}

public myPanel()

{

// Подключение обработчика события для клавиатуры к окну

addKeyListener(new myKey());

setFocusable(true);

Timer nt = new Timer(25,new ActionListener() {

public void actionPerformed(ActionEvent e) {

if (napr==0) x--;

if (napr==1) y--;

if (napr==2) x++;

if (napr==3) y++;

repaint();

}

});

nt.start();

try

{

img = ImageIO.read(new File("c:\\m.gif"));

}

catch(IOException exp) {}

}

public void paintComponent(Graphics gr)

{

gr.clearRect(x-1, y-1, img.getWidth(null)+1, img.getHeight(null)+1);

gr.drawImage(img,x,y,null);

}

}

Мы реализовали возможность управления объектом с помощью клавиатуры. Давайте обсудим полученный результат.

При нажатии определенной клавиши мы меняли значение переменной napr,соответственно: 0, 1, 2, 3. В таймере, в зависимости от переменной napr, по-разному менялись переменные x и y. Объект двигался в разных направлениях, а отрисовка движений происходила всегда здесь:

public void paintComponent(Graphics gr)

{

gr.clearRect(x-1, y-1, img.getWidth(null)+1, img.getHeight(null)+1);

gr.drawImage(img,x,y,null);

}

Первая строчка очищала предыдущую область, где располагался объект, затем объект помещался в новом месте. Вызов метода отрисовки происходил каждый раз при срабатывании таймера, это выполняла строка:

repaint();

Таким образом, получилась управляемая анимация движения.

Теперь у нас еще больше возможностей для создания компьютерных игр. Во-первых, мы умеем управлять объектами при помощи клавиатуры. Можем вывести любой объект на экран,перемещать этот объект по экрану, т. е. создавать анимацию. В данном случае был создан один объект, а можно создать множество объектов, каждый из которых будет двигаться по своей траектории движения. Объекты могут быть разные,соответственно, поведение на игровом поле у них тоже может быть разным. Таким образом, мы уже можем создать небольшую компьютерную игру, оформить её, и организовать её управление.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]