Для фильтрованных цветов, компонент цвета установлен в 0.
Новые цветовые компоненты затем переносятся обратно в 32-битное значение цвета и возвращаются из метода filterRGB.
Обратите внимание, что альфа-компонент значения цвета не изменяется.
Для этого используется маска 0xff000000, потому что альфа-компонент находится в верхнем байте значения цвета.
Помимо обработки изображений, с помощью вставки фильтров изображений между производителем изображения и потребителем изображения,
Java поддерживает фильтрацию изображений с помощью интерфейса BufferedImageOp.
Метод filter интерфейса BufferedImageOp принимает объект BufferedImage как вход (исходное изображение) и выполняет обработку данных изображения, создавая другой объект BufferedImage (конечное изображение).
Напомним, что класс BufferedImage расширяет класс Image, обеспечивая доступ к буферу данных изображения.
Java 2D API предоставляет набор реализаций интерфейса BufferedImageOp.
AffineTransformOp – преобразует изображение геометрически.
ColorConvertOp – выполняет по-пиксельное преобразование цвета в исходном изображении.
ConvolveOp – выполняет свертку, математическую операцию, которая может использоваться для размытия, изменения резкости или другой обработки изображения.
LookupOp – изменяет отдельные составляющие цвета.
RescaleOp – изменяет интенсивность изображения.
Здесь показан пример применения фильтра RescaleOp, изменяющего интенсивность цвета.
В этом примере сначала создается исходный объект BufferedImage на основе изображения, затем создается пустой объект BufferedImage.
Который заполняется отфильтрованными данными исходного изображения, с помощью метода filter созданного объекта RescaleOp.
JavaBeans и POJO
Откроем среду IntelliJ IDEA с созданным проектом Java приложения.
Нажмем правой кнопкой мыши на пакете приложения, и в меню выберем New – GUI Form.
Введем имя формы.
В результате будет создан Java класс и связанное с ним XML описание, которое открывается в редакторе IntelliJ IDEA GUI Designer.
Редактор IntelliJ IDEA GUI Designer позволяет создавать графические пользовательские интерфейсы (GUI) приложения, используя компоненты библиотеки Swing.
Этот инструмент помогает создавать диалоговые окна и группы элементов управления, которые будут использоваться в контейнере верхнего уровня, таком как JFrame.
Когда вы создаете форму с помощью GUI Designer, вы создаете панель, а не фрейм.
Пользуясь палитрой компонентов редактора, вы можете перетаскивать компоненты в форму и редактировать их свойства.
Для того чтобы компонент графического интерфейса пользователя можно было применять в таком визуальном средстве разработки, он должен обладать дополнительными качествами.
У него должен быть ярлык, помещаемый в палитру компонентов.
Среди полей компонента должны быть выделены свойства (properties), которые будут показаны в окне свойств.
У него должны быть определены методы доступа getXxx () /setXxx () /isXxx () к каждому свойству.
Этими методами будет пользоваться IDE среда разработки, чтобы определить свойства компонента.
Компонент, имеющий эти и другие определенные свойства, в технологии Java называется компонентом JavaBean.
В него может входить один или несколько классов.
Как правило, файлы этих классов упаковываются в один jar-файл и отмечаются в его файле MANIFEST. MF как Java-Bean: True.
Все компоненты AWT и Swing являются компонентами JavaBeans.
Спецификация Sun Microsystems определяет JavaBeans как повторно используемые программные компоненты, которыми можно управлять, используя графические конструкторы и средства IDE.
Визуальные средства разработки – это не основное применение JavaBeans.
Главное достоинство компонентов, оформленных как JavaBeans, в том, что они без труда встраиваются в любое приложение.
И приложение можно собрать из готовых JavaBeans как из строительных блоков, остается только настроить их свойства.
Это называется компонентное программирование.
Чтобы класс мог работать как bean, он должен соответствовать определённым соглашениям об именах методов, конструкторе и поведении.
Эти соглашения дают возможность создания инструментов, которые могут использовать, замещать и соединять JavaBeans.
Эти соглашения следующие:
Класс должен иметь конструктор без параметров, с модификатором доступа public.
Такой конструктор позволяет инструментам создать объект без дополнительных сложностей с параметрами.
Свойства класса должны быть доступны через get, set и другие методы (так называемые методы доступа), которые должны подчиняться стандартному соглашению об именах.
Это легко позволяет инструментам автоматически определять и обновлять содержание bean’ов.
Многие инструменты даже имеют специализированные редакторы для различных типов свойств.
Класс должен быть сериализуем.
Это даёт возможность надёжно сохранять, хранить и восстанавливать состояние bean независимым от платформы и виртуальной машины способом.
Класс должен иметь переопределенные методы equals, hashCode и toString.
В среде разработки NetBeans можно легко создать компонент JavaBeans с помощью меню New проекта приложения.
Для создания компонентов JavaBeans Java SE API включает в себя пакет java.beans.
В частности, помимо обычных свойств, представленных отдельными значениями и массивами значений, компонент JavaBeans может иметь связанные свойства, которые уведомляют слушателей, когда изменяется их значение.
Класс компонента JavaBeans содержит методы addPropertyChangeListener и removePropertyChangeListener для управления слушателями, и когда связанное свойство изменяется, компонент отправляет событие PropertyChangeEvent своим зарегистрированным слушателям.
Также класс компонента JavaBeans может запускать любой тип события, включая пользовательские события.
Как и в случае со свойствами, события идентифицируются по определенной схеме имен методов, add
Другое понятие, с которым вы можете столкнуться – это Plain Old Java Object.
Plain Old Java Object – это объект Java, который не расширяет или не реализует специализированные классы и интерфейсы каких-либо фреймворков.
POJO это просто класс Java, который содержит только поля, без логики их обработки и обеспечивает доступ ко все полям только через методы get/set.
Компоненты JavaBeans дополняют Plain Old Java Object наличием конструктора по умолчанию и наличием слушателей listener изменения свойств.
То есть Plain Old Java Object описывает структуру данных для дальнейшего использования в приложении.
Сериализация
Все мы знаем о том, что Java позволяет создавать в памяти объекты для многократного использования.
Однако все эти объекты существуют лишь до тех пор, пока выполняется создавшая их виртуальная машина.
Было бы неплохо, если бы создаваемые нами объекты могли бы существовать и вне пределов жизненного цикла виртуальной машины?
Как уже было сказано, JavaBeans обладает свойством сохранения, когда его свойства, поля и информация о состоянии могут сохраняться и извлекаться из хранилища.
Механизм, который делает возможным такое сохранение, называется сериализацией.
Сериализация объектов означает преобразование объекта в поток данных и запись его в хранилище, при этом объект представлен как последовательность байтов, которая включает в себя данные объекта, а также информацию о типе объекта и типах данных, хранящихся в объекте.
Любое приложение, которое использует такой компонент, может затем «восстановить» его путем десериализации.
Затем объект возвращается в исходное состояние.
Например, приложение Java может сериализовать окно Frame на машине Windows, сериализованный файл можно отправить с помощью электронной почты на машину Solaris, а затем приложение Java сможет восстановить окно Frame в точное состояние, существующее на машине Windows.
Чтобы так сохраняться, компоненты должны поддерживать сериализацию, реализуя либо интерфейс java.io.Serializable, либо интерфейс java.io.Externalizable.
При сериализации объекта в файл, по соглашению создается файл с расширением. ser.
Классы ObjectInputStream и ObjectOutputStream представляют собой потоки, которые содержат методы сериализации и десериализации объекта.
Это два класса, с помощью которых собственно осуществляют сериализацию и десериализацию объекта.
Если какой-либо класс в иерархии наследования класса реализует интерфейс Serializable или Externalizable, тогда этот класс и его подклассы сериализуются.
Примеры сериализуемых классов включают в себя классы Component, String, Date, Vector и Hashtable.
Известные классы, которые не поддерживающие сериализацию, включают в себя классы Image, Thread, Socket и InputStream.
Попытка сериализации объектов этих типов приведет к исключению NotSerializableException.
Java Object Serialization API автоматически сериализует большинство полей объекта Serializable в поток байтов.
Сюда входят примитивные типы, массивы и строки.
API не сериализует или десериализует поля, отмеченные как transient или static.
Transient (нерезидент) – модификатор полей класса.
Отмеченные этим модификатором поля не записываются в поток байт при применении стандартного алгоритма сериализации.
При десериализации объекта такие поля инициализируются значением по умолчанию.
Этот модификатор применяется, например, если поле класса является объектом несериализуемого класса, или некоторые поля могут не сериализоваться из соображений безопасности, например, поле пароля, или значение поля корректно только в рамках текущего контекста.
Вы можете контролировать уровень сериализации объекта.
Есть несколько способов управления серилизацией:
Это автоматическая сериализация, реализуемая интерфейсом Serializable.
Программное обеспечение сериализации Java сериализует весь объект, за исключением полей transient или static.
Интерфейс Serializable не объявляет никаких методов; он действует как маркер, сообщая инструментам сериализации объектов, что ваш класс сериализуется.
Маркировка класса интерфейсом Serializable означает, что вы сообщаете виртуальной машине Java (JVM), что ваш класс будет работать с сериализацией по умолчанию.
Классы, которые реализуют Serializable, должны иметь доступ к конструктору без аргументов супертипа.
Этот конструктор будет вызываться, когда объект будет «восстанавливаться» из файла. ser, в котором хранится сериализованный объект.
Вам не нужно реализовывать Serializable в вашем классе, если он уже реализован в суперклассе.
Все поля, кроме полей transient или static, сериализуются.
Используйте модификатор transient, чтобы указать поля, которые вы не хотите сериализовать, и указать классы, которые не являются сериализуемыми.
Если объект однажды уже записанный в поток, спустя какое-то время записывается в него снова, то по умолчанию, ObjectOutputStream сохраняет ссылки на объекты, которые в него записываются.
Это означает, что, если состояние записываемого объекта, который уже был записан, будет записано снова, новое состояние не сохраняется.
Существует два способа это исправить.
Во-первых, вы можете каждый раз после вызова метода записи закрывать поток, а затем открывать его снова.
Во-вторых, вы можете вызвать метод ObjectOutputStream.reset, который сигнализирует потоку о том, что необходимо освободить кэш от ссылок, которые он хранит, чтобы новые вызовы методов записи действительно записывали данные.
Вы можете дополнительно контролировать, как объекты сериализуются, путем написания собственных реализаций методов writeObject и readObject и включить их в свой сериализуемый класс.
Классы, требующие специальной обработки во время процесса сериализации и десериализации, должны определить эти методы с этими точными сигнатурами.
Метод writeObject класса определяет сериализацию объекта.
А метод readObject восстанавливает поток данных, который вы определили с помощью writeObject.
Если же вы хотите полностью контролировать сериализацию объекта, используйте интерфейс Externalizable, например, при записи и чтении определенного формата файла.
Для использования интерфейса Externalizable вам необходимо реализовать два метода: readExternal и writeExternal.
Классы, которые реализуют Externalizable, должны иметь конструктор без аргументов.
Класс XMLEncoder позволяет сериализовать объект в XML-файл.
Одно из достоинств этой формы сериализации заключается в том, что вы можете легко просмотреть данные объекта в сохраненной форме.
Вы также можете изменить данные в файле в текстовом редакторе.
Соответственно с помощью класса XMLEncoder, можно легко восстановить потом объект из XML-файла.
Библиотека Swing
Графическая библиотека Swing была создана на основе библиотеки AWT для решения таких проблем AWT как недостаточный выбор графических компонентов и зависимость внешнего вида и поведения AWT графического интерфейса пользователя от конкретной операционной системы.
Эти проблемы были решены созданием классов и интерфейсов библиотеки Swing с использованием одного только языка Java.
Компоненты AWT являются тяжеловесными, в то время как компоненты Swing являются легковесными.
Библиотека AWT использует нативный код (код, специфичный для конкретной операционной системы) для отображения компонентов.
Каждая реализация среды выполнения Jave Runtime Environment должна обеспечивать собственные реализации кнопок, меток, панелей и всех других компонентов AWT.
Всякий раз, когда используется компонент AWT, все запросы на рисование пересылаются нативному коду.
Это позволяет использовать кнопку AWT в приложении, но кнопка отображается как кнопка Windows, или кнопка Mac или другая кнопка конкретной платформы, на которой работает приложение.
Эти части нативного кода, к которым обращается среда выполнения JRE при использовании AWT компонентов, называются пирами, так как они берут на себя ответственность за отображение компонента.
Прежде чем AWT компонент будет сначала нарисован на экране, будет создан его пир.
Код пира включает в себя нативный код для отображения компонента, определения текущего размера экрана и решения других проблем с нативной платформой.
Например, когда Java рисует метку, она не просто рисует строку в нужном месте на экране.
Она создает пир и помещает его на экран.
В свою очередь компоненты Swing используют пиры для двух задач.
Во-первых, Swing компоненты JFrame, JWindow, JDialog и JApplet расширяют свои AWT-аналоги.
И все они используют пиры для отображения фактической области рисования на экране.
Другие компоненты Swing легковесные; у них нет пиров.
Эти компоненты отрисовывают себя поверх существующих JFrame, JWindow, JDialog или JApplet.
И поэтому на самом деле они также неявно используют пиры.
В AWT библиотеке использование пиров значительно затрудняло создавать подклассы этих компонентов для изменения их поведения.
Потому что их поведение исходит от нативного пира и поэтому не может быть легко переопределено или расширено.
Далее, наличие нативного кода значительно затрудняет перенос Java на новую платформу.
Проще говоря, хотя сам язык Java был кросс-платформенным, библиотека AWT была его ахиллесовой пятой.
Наконец, нативные пиры потребляют много ресурсов.
Можно было бы ожидать, что использование нативного кода будет намного более эффективным, чем создание компонентов на Java.
Тем не менее, для создания большого количества элементов GUI может потребоваться много времени, когда для каждого из них требуется создание его пира.
Решением было создание легковесных компонентов библиотеки Swing, которые полностью написаны на Java, и поэтому не требуют прямого использования нативного кода.
Легковесный компонент – это просто компонент, полностью реализованный на Java.
Для создания легковесного компонента достаточно расширить AWT класс Component или Container напрямую, реализуя внешний вид компонента на Java, а не делегируя внешний вид пиру.
Легковесные компоненты могут быть прозрачными, и они не должны быть прямоугольными, что является ограничением при работе с компонентами, имеющими пиры.
Вы реализуете весь внешний вид, используя методы paint и update, и вы реализуете поведение компонента, улавливая пользовательские события и, возможно, генерируя новые события.
В библиотеке AWT для создания совершенно нового компонента вам нужно было бы расширять класс Canvas.
Легковесному компоненту достаточно расширить класс Component или Container.
Когда легковесный компонент помещается в контейнер, он не получает нативный пир.
Вместо этого Toolkit создает для компонента объект LightweightPeer, который служит как указатель и идентифицирует компонент как легковесный.
LightweightPeer помечает компонент как зависящий от нативного контейнера, так, чтобы события, связанные с окном, могли быть перенаправлены компоненту.
Поэтому тяжеловесный контейнер, который содержит легковесный компонент, берет на себя обязанности, которые в противном случае обрабатывались бы нативным пиром, а именно берет на себя низкоуровневую доставку событий и запросы на рисование.
Контейнер принимает события перемещения мыши, нажатия клавиш, запросы на рисование и т. д. для легковесного компонента и отправляет их ему.
Метод setBackground легковесного компонента, просто расширяющего класс Component, не работает, так как всю работу по изображению кнопки на экране выполняет не peer-двойник компонента, а тяжеловесный контейнер, в котором расположен компонент.
Контейнер ничего не знает о том, что надо обратиться к методу setBackground, он рисует только то, что записано в методе paint.
Если же мы создаем легковесный контейнер, то такой контейнер не умеет рисовать находящиеся в нем легковесные компоненты, поэтому в конце метода paint легковесного контейнера нужно вызвать метод paint суперкласса.
Тогда рисованием займется тяжеловесный суперкласс-контейнер. Он нарисует и лежащий в нем легковесный контейнер, и размещенные в контейнере легковесные компоненты.
Предпочтительный размер тяжеловесного компонента устанавливается peer-объектом, поэтому для легковесных компонентов его надо задать явно, переопределив метод getPreferredSize, иначе некоторые менеджеры компоновки, например FlowLayout (), установят нулевой размер, и компонент не будет виден на экране.
Легковесные компоненты изначально рисуются прозрачными, и незакрашенная часть прямоугольного объекта не будет видна. Это позволяет создать компонент любой видимой формы.
Таким образом, на основе библиотеки AWT, появилась библиотека Swing – Java-библиотека классов и интерфейсов, представляющих такие стандартные графические компоненты интерфейса пользователя как кнопки, таблицы, поля ввода и др., а также методы для работы с ними.
Библиотека Swing составляет основную часть библиотеки JFC (Java Foundation Classes), которая объединяет классы и интерфейсы, обеспечивающие интерфейс пользователя Swing-компонентами, выбор внешнего вида и поведения интерфейса, поддержку технологий для людей с ограниченными возможностями, работу с высококачественной двухмерной графикой, текстом и изображениями, а также интернационализацию графического интерфейса пользователя.
В настоящее время библиотека Swing входит в набор настольных Java-технологий.
Все классы Swing-компонентов являются наследниками базового класса JComponent пакета javax. swing.
При конструировании Swing-интерфейса компоненты помещаются в контейнеры, образующие иерархию, которая берет свое начало от контейнеров верхнего уровня, представленных классами JApplet, который уже запрещен, JDialog, JFrame и JWindow.
Основные свойства графической библиотеки Swing можно суммировать как:
Кроссплатформенность.
Механизм сменного внешнего вида и поведения компонентов (pluggable look and feel).
Внешний вид и поведение графического интерфейса пользователя может определяться программным образом или может выбираться при выполнении приложения.
Расширяемость за счет возможности расширения классов и интерфейсов библиотеки.
Архитектура Swing-компонентов основана на технологии Java Beans.
Возможность настройки внешнего вида Swing-компонентов за счет изменения свойств таких элементов компонентов как рамки, цвет, фон и др.
Легковесность.
Так как AWT-компоненты непосредственно взаимодействуют с операционной системой и представляют собой каждый маленькое индивидуальное окно, то их называют тяжеловесными.
Компоненты Swing представляют собой области в окне, характеризующиеся координатами и размером, при этом они не работают напрямую с операционной системой, их отображение основывается на реализации Java 2D API, поэтому их называют легковесными.
Если легковесные компоненты используются совместно с тяжеловесными, то так как тяжеловесные напрямую связаны с операционной системой, то они будут прорисовываться в первую очередь, поэтому в случае размещения тяжеловесных компонентов в легковесных, они будут перекрывать собой легковесные, что приведет к неверному отображению графического интерфейса.
В библиотеке Swing автоматически заложена двойная буферизация при выводе изображения, т.е. изображение сначала полностью формируется в оперативной памяти, а затем целиком выводится на экран, таким образом устраняется эффект мерцания изображения и повышается скорость рисования.
Использование библиотеки Swing не является потоково-безопасной.
Доступ к Swing-компонентам должен осуществляться в специальном потоке Event Dispatch Thread (EDT).
Поддержка технологий для людей с ограниченными возможностями.
Снабжение компонентов всплывающими подсказками и механизмом управления клавиатурой.
Возможность настройки текста, отображаемого Swing-компонентами с помощью HTML-тэгов.
С помощью разметки HTML, компоненты могут отображать многострочный, многошрифтовый текст с использованием простого форматирования HTML.
Чтобы отобразить форматированный текст, нужно просто указать строку текста HTML, которая начинается с тега .
Возможность отображения иконок Swing-компонентами.
Реализация модели MVC (Model-View-Controller) – модели отделения данных от внешнего вида и поведения интерфейса.