Java. Заметка третья, часть первая

В одной заметке показать несложный GUI с кодом и комментариями несколько проблематично и поэтому я сделаю заметку из нескольких частей.

Сегодня мы напишем минимальную программу, которая будет показывать своё окошко с заданным заголовком. И эта программа будет уметь закрываться по нажатию на «крестик». 😉

Начнём с того, что вспомним о методе main. В Java, как и в С++, точкой входа является main-функция, принимающая в качестве аргументов список параметров командной строки. Имя метода и его сигнатура должны быть неизменны:

В отличие от С++, в Java-программе может быть более одной точки входа. Это означает, что мы можем написать несколько классов с main-методом и использовать ту точку входа, которая нужна в данный момент. За счёт этой особенности можно реализовать программный комплекс, состоящий из нескольких автономных блоков и некоторого механизма управления ими. Конечно, такую же архитектуру можно сделать и на С++ за счёт dll. Но, как я понимаю, в С++ такой комплекс будет работать всё же иначе (пока что внятно объяснить не могу, если честно, а потому «скромно промолчу»).

Итак, для запуска программы нам нужна основа (класс — в java всё через классы). И у этой основы должна быть дырка… тьфу, точка входа. Ну, не важно. 🙂
Листинг /com/nornad/javanootes/Note3.java

Давайте разберёмся, что здесь к чему.
В первой строке указан пакет, к которому принадлежит класс. Э… я разве ещё не говорил про пакеты? 🙂
В целом, идея пакетов родственна идее пространств имён в С++, но удобнее и мощнее, на мой взгляд. Можно, конечно, не указывать пакет. В этом случае класс будет принадлежать пакету по умолчанию (с пустым именем). В небольшом приложении, которое мы пишем для себя, это оправданно. Если же вы пишете приложение (или библиотеку), которое будете использовать совместно с другим кодом — настоятельно рекомендую раскладывать классы по пакетам. Это поможет избежать головной боли в будущем, когда после написания очередного класса произойдёт конфликт с другим классом, имеющим то же имя и написанным не обязательно вами.
Стоит заметить, что имя пакета определяет путь файла с классом на диске (относительно папки исходников).
Имя пакета Sun рекомендует выбирать на основе вашего доменного имени, поменяв домен первого и второго уровня местами. Отсюда, например, пакеты проекта apache — org.apache.*.

Далее идут строки импортирования классов. Звёздочка на конце означает, что импортироваться должны все классы пакета.

Следующая конструкция объявляет наш класс Note3, которы мы наследуем от JFrame. Я пока не буду особенно забегать вперёд и скажу лишь, что в java окна как таковые не используются. Вместо них есть фреймы, диалоги, панели и компоненты. Как они реализуются на уровне системы — нас, как программистов на java интересует редко (обычно не интересует вовсе).
Итак, мы наследовали свой класс от фрейма. Что есть фрейм? В понятиях Windows — это окно. Немодальное окно. Для модальности используются диалоги.
По уму нам вообще-то было бы лучше сделать для «лоадера», фрейма и панели по отдельному классу. Но приложение у нас будет маленьким, так что можно немного ухудшить структуру, чтобы выиграть немного места на странице. 😉

Первым методом в нашем классе мы описали статическую точку входа программы, в которой создаём фрейм и отображаем его. Если создать фрейм не удалось (например, память вдруг резко на машине закончилась, а в магазин за новой планкой бежать лень) — ругаемся на чём свет стоит. Для ругани используем стандартный диалог ругани, указав параметром «на чём свет стоит» (JOptionPane.ERROR_MESSAGE).
SwingUtilities.invokeLater() мы здесь используем на всякий пожарный. Дело в том, что программа у нас маленькая и вероятность того, что что-то не успеет инициализироваться, практически нулевая. Но лучше всегда писать запуск через отложенный вызов, чем убить неизвестное количество времени на отлов «бага».

Далее мы объявили поле главной панели программы и написали конструктор.
По уму, опять же, создавать интерфейсные вещи (компоненты и иже с ними) в конструкторе — не самая лучшая идея. Компоненту могут требоваться некоторые данные, которые могут быть на момент конструирования фрейма/панели недоступными. Причина, почему я нарушаю хороший тон, всё та же — экономия места. Хотя, умнее было бы сделать отдельно конструктор, отдельно инициализатор(ы).
Кстати, обратите внимание на сигнатуру и имя конструктора. Имя должно совпадать с именем класса. Сигнатура же необычна тем, что нет возвращаемого типа.

Первым делом в конструкторе мы вызываем конструктор родителя. Если мы собираемся его вызывать, то делать это надо первой же строкой в теле своего конструктора. Иначе никак.
Далее мы сообщаем фрейму, что располагать его будет система (если я правильно путаю :)). Затем указываем, что должно происходить при нажатии на «крестик».
Следом создаём панель и указываем ей менеджер компоновки (про это поговорим чуть позже отдельно и более подробно, ибо тема широкая). Потом создаём кнопку, добавляем слушатель, который закрывает программу и ложим кнопку на панель.
Т.к. у нас выбран BorderLayout и кнопку мы положили в центр, то её разобрало от осознания собственной важности и она заняла всё пространство панели. Хотя, если бы мы положили ещё хоть что-нибудь на панель, то кнопке пришлось бы быть несколько менее важной. 😉
Под конец мы указываем размеры и заголовок фрейма, а также устанавливаем главную панель во фрейм.

Вуаля! Программа готова. Можно компилировать и запускать. 🙂

Обратите внимание на тело слушателя кнопки. Мы написали

Если бы мы не указали имя нашего класса, то метод disprose() не был бы найден. Дело в том, что тело слушателя принадлежит создаваемому нами классу слушателя ActionListener.

P.S. Для написания кода, компиляции и запуска я рекомендую использовать IDE. Лично мне больше нравится IntelliJ IDEA, но она платная. Если хочется бесплатности, можно скачать Eclipse (он кроме java умеет работать и с C++) или NetBeans (разработка Sun).
Использование IDE избавит вас от необходимости разбираться с тем, как компилировать исходники и запускать программу вручную. Но в будущем это всё равно пригодится.
P.P.S. Если найдутся желающие собрать приведённый пример вручную, сразу предупреждаю — у вас возникнет вопрос, почему программа не запускается. Дело в том, что я кое-что умолчал, а именно то, что при запуске надо указать не просто имя класса с main, но его полное имя, включая пакет (просто, как уже говорилось, бывает пакет по умолчанию).

Leave a Reply

Ваш e-mail не будет опубликован. Обязательные поля помечены *