Swing

Swing


Фреймы

Окно верхнего уровня (т.е. такое окно, которое не содержится внутри другого окна) в Java называется фреймом.  А в библиотеке Swing его аналогом является класс JFrame. Класс JFrame расширяет класс Frame и представляет собой один из немногих компонентов библиотеки Swing, которые не воспроизводятся на холсте. 

public class Main {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            SimpleFrame frame = new SimpleFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //что произойдет, если пользователь закроет фрейм
            frame.setVisible(true);
            });
    }

    static class SimpleFrame extends JFrame {
        private static final int DEFAULT_WIDTH = 300;
        private static final int DEFAULT_HEIGHT = 200;

        public SimpleFrame() {
            setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
        }
    }

}

• Методы setLocation () и setBounds (), устанавливающие положение фрейма.
• Метод dispose (), закрывающий окно и освобождающий все системные ресурсы, использованные при его создании.
• Метод setlconlmage (), сообщающий оконной системе, какая именно пиктограмма должна отображаться в строке заголовка, окне переключателя задач и т.п.
• Метод setTitle (), позволяющий изменить текст в строке заголовка.
• Метод setResizable (), получающий в качестве параметра логическое значение и определяющий, имеет ли пользователь право изменять размеры фрейма.

static class SimpleFrame extends JFrame {
    private static final int DEFAULT_WIDTH = 400;
    private static final int DEFAULT_HEIGHT = 400;

    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    public int locationX = (screenSize.width - DEFAULT_WIDTH) / 2;
    public int locationY = (screenSize.height - DEFAULT_HEIGHT) / 2;
    public SimpleFrame() {
        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
        setResizable(false);
        setBounds(locationX, locationY, DEFAULT_WIDTH, DEFAULT_HEIGHT);
    }
}

Чтобы определить размеры экрана, необходимо выполнить следующие действия. Сначала вызывается статический метод getDefaultToolkit () из класса Toolkit, который возвращает объект типа Toolkit. (Класс Toolkit содержит много методов, предназначенных для взаимодействия с оконной системой конкретной платформы.) Затем вызывается метод getScreenSize (), который возвращает размеры экрана в виде объекта типа Dimension. Этот объект содержит ширину и высоту в открытых (!) переменных width и height соответственно.

Изменить иконку :

setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("icon.png")));

Ниже дается ряд дополнительных рекомендаций по поводу обращения с фреймами.
• Если фрейм содержит только стандартные компоненты вроде кнопок и текстовых полей, вызовите метод pack (), чтобы установить размеры фрейма. Фрейм будет установлен с минимальными размерами, достаточными для размещения всех его компонентов. Зачастую главный фрейм программы приходится устанавливать с максимальными размерами. Фрейм можно развернуть до максимума, сделав следующий вызов:
frame.setExtendedState(Frame.MAXIMIZED_BOTH); .
• Целесообразно также запоминать расположение и размеры фрейма, заданные пользователем, чтобы восстановить эти значения при очередном запуске приложения. В главе 13 будет показано, как пользоваться для этой цели прикладным программным интерфейсом Preferences API.
• Если вы разрабатываете приложение, в котором выгодно используются преимущества многоэкранного дисплея, применяйте классы GraphicsEnvironment и GraphicsDevice для определения размеров отдельных экранов.
• Класс GraphicsDevice позволяет также выполнять приложение в полноэкранном режиме. 

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

При оформлении фрейма его компоненты добавляются на панели содержимого с помощью следующего кода:
Container contentPane = frame.getContentPane();
Component c = . ..;
contentPane.add(c) ;

В данном случае требуется добавить во фрейм единственный компонент, где будет выводиться сообщение. Чтобы отобразить компонент, следует сначала определить класс, расширяющий класс JComponent, а затем переопределить метод paintComponent () этого класса. Метод paintComponent () получает в качестве параметра объект типа Graphics, который содержит набор установок для отображения рисунков и текста. В нем, например, задается шрифт и цвет текста. Все операции рисования графики в Java выполняются с помощью объектов класса Graphics. В этом классе предусмотрены методы для рисования узоров, графических изображений и текста.

В приведенном ниже фрагменте кода показано в общих чертах, каким образом создается компонент для рисования графики.

class MyComponent extends JComponent {
    public void paintComponent(Graphics g) {
        код для рисования
    }
}

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

package com.company;
import java.awt.*;
import javax.swing.*;

public class Main {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            SimpleFrame frame = new SimpleFrame();
            frame.setTitle("Hello world!");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        });

    }

    static class SimpleFrame extends JFrame {


        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        private int frameHeight = screenSize.height / 10 * 4;
        private int frameWidth = screenSize.width / 10 * 4;
        public int locationX = (screenSize.width - frameWidth) / 2;
        public int locationY = (screenSize.height - frameHeight) / 2;

        public SimpleFrame() {
            setSize(frameWidth, frameHeight);
            setResizable(false);
            setBounds(locationX, locationY, frameWidth, frameHeight);
//            Image img = new ImageIcon("qwe.png").getImage();
//            setIconImage(img);
            setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("icon.png")));
            add(new NotHelloWorldComponent());
            pack();
        }


    }

    static class NotHelloWorldComponent extends JComponent {
        public static final int MESSAGE_X = 75;
        public static final int MESSAGE_Y = 100;

        private static final int DEFAULT_WIDTH = 300;
        private static final int DEFAULT_HEIGHT = 200;

        public void paintComponent(Graphics g) {
            g.drawString("Not a Hello, World program", MESSAGE_X, MESSAGE_Y);
        }

        public Dimension getPreferredSize() {
            return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
        }
    }
}

Цвет:

Имеется возможность указать произвольный цвет по его красной, зеленой и синей составляющим, создав объект класса Color. В конструкторе класса Color составляющие цветов задаются целыми значениями в пределах от 0 до 255 (т.е. одним байтом) следующим образом:
Color(int redness, int greenness, int blueness)

Ниже приведен пример установки специального цвета. 
g2.setPaint(new Color(0, 128, 128)); // скучный сине-зеленый цвет g2.drawstring("Welcome!", 75, 125); 

Чтобы установить цвет фона, следует вызвать метод setBackground () из класса Component, предшественника класса Jpanel:
MyComponent р = new MyComponent();
р.setBackground(Color.PINK);

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

р .setBackground(SystemColor.window) 

Font sansboldl4 = new Font("SansSerif", Font.BOLD, 14);
//задается шрифт, стиль, и размер для sansbold14
g.setFont(sansboldl4);
//применяется к тексту
String message = "Hello, World!";
g.drawString(message, 75, 100);

Процесс выравнивания зависит от следующих факторов.
• Используемый шрифт (в данном случае полужирный шрифт sans serif размером 14 пунктов).
• Символы строки (в данном случае "Hello, World! ”).
• Устройство, на котором будет воспроизводиться строка (в данном случае экран монитора пользователя). 

Чтобы получить объект, представляющий характеристики устройства вывода, следует вызвать метод getFontRenderContext () из класса Graphics2D. Он возвращает объект класса FontRende г Context. Этот объект нужно передать методу getStringBounds () из класса Font, как показано ниже. А метод getStringBounds () возвращает прямоугольник, ограничивающий текстовую строку.

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

Ширина прямоугольника, возвращаемого методом getStringBounds(), задает протяженность строки по горизонтали. Высота прямоугольника равна сумме спуска, подъема и интерлиньяжа. Начало отсчета прямоугольника находится на базовой линии строки. Координата у отсчитывается от базовой линии. Для верхней части прямоугольника она является отрицательной.

Таким образом, ширину, высоту и подъем строки можно вычислить следующим образом:

double stringWidth = bounds.getWidth();
double stringHeight = bounds.getHeight();
double ascent = -bounds.getY();

Если же требуется выяснить, чему равен интерлиньяж или спуск, то следует вызвать метод getLineMetrics() из класса Font, как показано ниже. Этот метод возвращает объект класса LineMetrics, где имеются методы для определения указанных выше типографских характеристик. 

LineMetrics metrics = f.getLineMetrics(message, context);
float descent = metrics.getDescent();
float leading = metrics.getLeading();
package com.company;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import javax.swing.*;

public class Main {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            FontFrame frame = new FontFrame();
            frame.setTitle("Hello world!");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        });

    }

    /**
     * Фрейм с компонентом текстового сообщения
     */
    static class FontFrame extends JFrame {
        public FontFrame() {
            add(new FontComponent());
            pack();
        }
    }

    /**
     * Компонент, отображающий текстовое сообщение,
     * выровненное по центру в прямоугольной рамке
     */
    static class FontComponent extends JComponent {
        private static final int DEFAULT_WIDTH = 300;
        private static final int DEFAULT_HEIGHT = 200;
        public void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;

            String message = "Hello, World!";

            Font f = new Font("Serif", Font.BOLD, 36);
            g2.setFont(f);

            // определить размеры текстового сообщения

            FontRenderContext context = g2.getFontRenderContext();
            Rectangle2D bounds = f.getStringBounds(message, context);

            // определить координаты (x, у) верхнего левого угла текста

            double x = (getWidth() - bounds.getWidth()) / 2;
            double doubleY = (getHeight() - bounds.getHeight()) / 2;
            // сложить подъем с координатой у , чтобы достичь базовой линии

            double ascent = -bounds.getY();
            double baseY = doubleY + ascent;
            // воспроизвести текстовое сообщение

            g2.drawString(message, (int) x, (int) baseY);

            g2.setPaint(Color.LIGHT_GRAY);

            // нарисовать базовую линию

            g2.draw(new Line2D.Double(x,baseY,x+bounds.getWidth(),baseY));
            //Double(х, baseY,x + bounds.getWidth(), baseY));

            // нарисовать ограничивающий прямоугольник

            Rectangle2D rect = new Rectangle2D.Double(x , doubleY , bounds.getWidth(),bounds.getHeight());
                    //Rectangle2D.Double(x,y, bounds.getWidth(), bounds.getHeight());
            g2.draw(rect);
        }

        public Dimension getPreferredSize() {
            return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
        }
    }
}

Чтобы нарисовать двухмерную форму средствами библиотеки Java 2D, нужно создать объект класса Graphics2D. Это подкласс, производный от класса Graphics. Начиная с версии Java SE 2, такие методы, как paintComponent (), автоматически получают объекты класса Graphics 2d. Нужно лишь произвести соответствующее приведение типов, как показано ниже.

public void paintComponent(Graphics g){
    Graphics2D g2 = (Graphics2D) g;
}

Файлы со шрифтами можно вводить в формате TrueType, ОрепТуре или PostScript Туре 1. С этой целью следует создать отдельный поток ввода конкретного шрифта — обычно из файла на диске или веб-сайта по указанному адресу (потоки ввода-вывода будут подробнее рассматриваться в главе 1 второго тома настоящего издания). Затем нужно вызвать статический метод Font. CreateFont (): 



Report Page