shkolaput.ru 1



Graphical User Interface – heavy weight components

  • В первой версии java был пакет java.awt – abstract window toolkit;

  • Эта библиотека (AWT) предоставляет средства программирования пользовательского интерфейса, использующие платформо-зависимые средства (средства системы, на которой работает JVM);

  • Компоненты пользовательского интерфейса, использующие платформо-зависимые реализации иногда называют «тяжеловесными компонентами» (heavy weight components);

    • В реализации пакета awt компонент java имеет внутри реализации соответствующую ему java-обертку (ComponentPeer), обеспечивающую делегирование к соответствующему native-компоненту; например, java.awt.Button имеет при работе под MS Windows WButtonPeer, который обеспечивает работу Button’а средствами Windows;
    • В реализации для другой платформы имеется другая реализация такого peer (т.е. - эквивалента Button’а).

Graphical User Interface – light weight components

  • Платформенно-ориетированая реализация хороша для простых приложений (интерфейсов);

  • При этом крайне сложно создавать сложные GUI, которые не зависят от платформы:

    • Сходные элементы GUI на разных платформах ведут себя по-разному;
    • Не все платформы имеют полный/эквивалентный набор графических элементов;
    • В реализациях AWT на разных платформах обнаруживались разные ошибки;
  • В 1996 г. Netscape выпустила библиотеку IFC (Internet Foundation Classes), которая сама организовывала элементы GUI внутри окон, и только окна изображались платформо-зависимым способом;

  • Такие компоненты GUI получили название light weight components; развитие этого подхода в Sun – библиотека Swing (пакет javax.swing)


AWT и Swing

  • Библиотека Swing не заменяет полностью AWT:

    • Swing обеспечивает набор платформо-независимых light-weight компонент;
    • AWT обеспечивает платормо-зависимую работу с окнами.
  • Некоторые компоненты Swing могут отображаться чуть медленнее, чем heavy-weigh компоненты AWT (на современных машинах разница не заметна);

  • Преимущества Swing:

    • Более богатый и расширяемый набор элементов GUI;
    • Нет платформо-зависимых ошибок;
    • Однотипные средства на всех платформах (в том числе - визуальные).
  • GUI и MS Java – «причина раздора»: MS WFC for Java (СOM)



Swing и другие GUI - иструменты

  • В настоящее время большинство java-приложений имеют Swing GUI (за исключением разработок, ориентириолванных на IDE Eclipse, где есть своя heavy weight библиотека - SWT);

  • В библиотеке Swing есть средства обеспечения «Look and Feel», которые позволяют создавать изобразительное впечатление, соответсвующее native-средствам GUI для разных платформ.

  • В «java-cообществе» и Java IDE(s) имеются различные инструменты для создания GUI, однако, мы рассмотрим далее принципиальные основы работы GUI, пока не опираясь на предоставляемые этими инструментами возможности.


Frames

  • Окно верхнего уровня (не содержащееся внутри другого окна) называется фреймом (Frame);

    • В AWT этому соответствует класс java.awt.Frame;
    • В Swing это понятие описывает класс javax.swing.JFrame (extends java.awt.Frame);
  • Имена компонент Swing начинаются с J… (JFrame, JButon, …); в AWT есть аналоги (Frame, Button, …). Смешивать их можно, но не рекомендуется: это обычно приводит к несогласованному поведению и внешнему виду;

  • Как видно из примера (следующий слайд), заголовок и пиктограммы изменений размеров окна изображаются «операционной системой» (платформой), а не java-программой:


Пример простейшего фрейма



JFrame Class Diagram



JFrame API

  • По умолчанию, фрейм имеет бессмысленный размер (0,0) и располагается в «начале» экрана (точке 0,0 – левый верхний угол).

  • Основные методы для работы с фреймом находятся в его суперклассах Component и Window (см. диаграмму наследования), но не только...; надо знать методы суперклассов (занятия, практика);

  • Координаты фрейма, задаваемые методами setLocation() и setBounds(), вычисляются относительно экрана; координаты других компонентов внутри контейнера определяются относительно этого контейнера;

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



Пример позиционирования фрейма на экране





Внутреннее устройство JFrame’а


Панели (JPanel)

  • Панели (JPanel) обладают следующими свойствами:

    • Позволяют рисовать на их поверхности;
    • Сами являются контейнерами (на них можно размещать любые элементы GUI) .
  • Чтобы рисовать на панели, надо:

    • Определить класс, расширяющий JPanel;
    • Переопределить метод paintComponent(Graphics g)
      • Это – метод класса JComponent.
  • Все рисование в Java осуществляется с помощью объектов класса java.awt.Graphics;

  • Метод paintComponent(Graphics g) вызывается автоматически всякий раз, когда надо [пере]рисовать компонент. Его никогда не следует вызывать самостоятельно.

  • Если надо перерисовать экран принудительно, надо вызывать метод repaint(), что потом приведет к вызовам методов paintComponent()…


Объекты Graphics

  • Размер объекта типа Graphics задается в пикселях, координата (0,0) соответствует левому верхнему углу компонента, на котором выполняется рисование;

  • Отображение текста на экране – это разновидность рисования:

    • Объекты типа Graphics имеют метод drawString(String text, int x, int y);
      • text – «рисуемая» строка,
      • x , y – координаты начала строки (примерно, y – для «базовой линии» строки


Рисование двухмерных фигур

  • Graphics – абстрактный класс, содержит методы для рисования линий, прямоугольников, эллипсов и т.п., но – с ограниченными возможностями (начиная с java 1.0);

  • Начиная с Java 2.0, имеется библиотека Java2D с большим набором графических возможностей;

    • Для ее использования надо иметь объект Graphics2D (подкласс Graphics);
    • При использовании JDK с Java2D автоматически вызываемые методы уже получают параметром объект Graphics2D;
    • При этом достаточно сделать приведение типов:
      • public void paintComponent (Graphics g) {
      • Graphics2D g2d = (Graphics2D)g; // ... далее можно использовать g2d…
      • }
      • (в русском переводе Cornell & Horstmann может быть ошибка – проверьте)

В отличие от Graphics, где имеются методы рисования разных фигур, библиотека Java2D устроена объектно-ориентированным образом:

  • В отличие от Graphics, где имеются методы рисования разных фигур, библиотека Java2D устроена объектно-ориентированным образом:

    • Чтобы нарисовать фигуру, надо создать объект некоторого класса, реализующего интерфейс Shape, а потом вызвать метод draw() класса Graphics2D; например:
      • Rectangle2D rect = …;
      • g2d.draw(rect);
  • В отличие от Graphics, где применяются целочисленные координаты в пикселях, библиотека Java2D использует координаты, представленные числами с плавающей запятой (размеры фигур задаются «естественными» единицами измерения – например, миллиметрами и т.п.); при этом есть два варианта указания координат:

    • С использованием float (Float);
    • С использованием double (Double).


Отношения классов, реализующих Shape-интерфейс



Работа с цветом

  • Класс Graphics2D имеет метод setPaint(Paint p), позволяющий, в частности, устанавливать цвет для рисования;

    • Заметим, что Graphics (старый) не имеет этого метода (ошибка в книге Cornell&Horsman’а), там есть метод setColor(Color c);
    • Paint – это интерфейс, реализуемый, в частности, классом java.awt.Color (и др.);
  • Чтобы рисовать многоцветные рисунки, надо выбрать/задать цвет, нарисовать фигуру, выбрать другой цвет, нарисовать..., и т.д., например:

    • g2d.setPaint(Color.RED);
      • g2d.srawString(“Warning!”, 100, 100);
  • Цвет определяется классом java.awt.Color;

    • Там есть предопределенные цвета
    • Можно делать свои - конструктором: Color(int redness, int greenness, int blueness) // задает rgb тремя байтами (0...255)...


Любой java.awt.Component (и наследники) имеет методы

  • Любой java.awt.Component (и наследники) имеет методы

    • setBackground(Color c),
    • setForeground(Color c) и соответствующие getter’ы...;
    • Например:
    • MyPanel p = new MyPanel();
    • p.setBackground(Color.PINK);
  • Имеется подкласс SystemColor (extends Color), где определены цвета для системных компонент GUI, например:

    • frame.setBackground(SystemColor.WINDOW);

Заполнение фигур

  • Внутренность замкнутых фигур (прямоугольников, эллипсов, ...) можно заполнять цветом (закрашивать);

  • Для этого вместо метода draw() надо вызвать fill():

      • Rectangle2D rect = …;
      • g2d.setPaint(Color.RED);
      • g2d.fill(rect); // закрашивает объект красным цветом.


Использование шрифтов при выводе текста

  • В примере про drawString() шрифт выбирался по умолчанию;

  • Часто надо изображать текст разными шрифтами (начертаниями символов);

  • Шрифт определяется именем семейства (например, Helvetica) и необязательного суффикса (например, Bold);

  • Чтобы узнать, какие шрифты доступны на компьютере, надо вызвать метод getAvailableFontFamilyNames() класса GraphicsEnvironment, экземпляр которого добывается статическим методом getLocalGraphicsEnvironment():

  • String[ ] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();



Нет стандартного способа узнать, есть ли на машине шрифт, имеющий требуемый вид;

  • Нет стандартного способа узнать, есть ли на машине шрифт, имеющий требуемый вид;

    • Имена шрифтов – это торговые марки;
    • Шрифты защизаются авторскими правами;
    • Часто бывают довольно дорогими (и имеют имитации/подделки);
      • Например, имитация шрифта Helvetica распространяется вместе с Windows под именем Arial
  • Чтобы была некоторая система, в AWT приняты пять логических названий шрифтов:

    • SansSerif
    • Serif
    • Monospaced
    • Dialog
    • DialogInput

Эти имена всегда соответствуют шрифтам, фактически имеющимся на компьютере; например, в Windows шрифт SansSerif отображается в шрифт Arial;

  • Эти имена всегда соответствуют шрифтам, фактически имеющимся на компьютере; например, в Windows шрифт SansSerif отображается в шрифт Arial;

  • Информация о соответствии шрифтов хранится в специяльрном файле fontconfig.properties.

  • Чтобы изобразить букву с помощью заданного шрифта, надо создать объект класса Font, указав название шрифта, его стиль и размер символов, например:

    • Font sansSerifBold14 = new Font (“SansSerif”, Font.BOLD, 14);
    • Размер (14) – указывается в типографских «точках» (их 72 на дюйм)
  • Теперь им можно воспользоваться (более подробный пример рассмотрим на практических занятиях):

    • g2d.setFont(sansSerifBold14);
    • g2d.drawString(“Hello, World!”, 75, 100);


Можно подгружать и использовать шрифты TrueType (векторная графика). Разработка шрифтов – «художественное» дело, этим занималась(ется?) компания ParaType («дочка» компанииParagraph):

  • Можно подгружать и использовать шрифты TrueType (векторная графика). Разработка шрифтов – «художественное» дело, этим занималась(ется?) компания ParaType («дочка» компанииParagraph):

    • URL url = new URL(“http://www.fonts.com/Wingbats.ttf”);
    • InpurStream in = url.openStream();
    • Font f = Font.createFont(Font.TRUETYPE_FONT, in);
    • - размер фонта можно потом менять методом f deriveFont (…).
  • Чтобы узнать “bound box” строки, рисуемой фонтом, надо сделать:

    • FontRenderContext contect = g2d.getFontRenderContext();
    • Rectangle2D bounds = f.getStringBounds(message, context);
    • - После этого можно расположить строку, например, в нужном месте панели... (обычно проще использовать специальный компонент, в котором рисуется текст, и располагать не сам текст (строку), а этот компонент).


Работа с изображениями (начальные сведения)

  • Простые изображения можно «нарисовать» линиями и фигурами;

  • Более сложные изображения можно сделать «заранее» и взять готовыми из файла, например так:

    • Image image = ImageIO.read(new File (“imageFileName”)); или
    • Image image = ImageIO.read(new URL(“urlString”));
    • ….
    • g.drawImage (image, x, y, null); - рисует image на component’е.
    • Кроме того, есть средства отображения изображений, генерируемых программно в памяти – в байтовом массиве (об этом – в следующих лекциях).

Примеры возможностей Java GUI

  • При установке Java (JDK) приходят демонстрации

    • См. например, C:\Program Files\Java\jdk1.6.0_13\demo\jfc\
    • Это демонстрации Java Foundation Classes (JFC), где показаны основные (не все!) возможности GUI...
    • В частности, есть демонстрации Swing и Java2D в виде апплетов и/или исполняемых jar-файлов, либо – приложений, запускаемых через java web start…


Q & A

  • Средства программирования GUI, имеющиеся в самой java (JDK), не являются единственными:

  • - существуют разные библиотеки и тулы, конкурирующие с ними.

  • Одним из интересных примеров является продукт Thinlet

  • (см. www.thinlet.com)