[Назад]   [Вперед]

Виктор Кон,   vkBook, Java-First

Главная программа

Нам осталось написать последний класс runPro. Фактически я напишу только скелет этого класса, так так здесь как раз возможны варианты. Сколько вы захотите написать программ, столько и будет вариантов. Лично я для себя люблю писать только одну программу, которая делает все на свете. Но если будете делать программу на заказ, то что попросят, то и напишете. Я опять ставлю самый простой случай, хотя можно и сложнее. Например, можно открыть специальное внутреннее окно Terminal к нашему главному окну, в которое выдавать сообщения в процессе работы. Если программа долго работает, то это полезно. Могут быть и другие варианты. Но мы сделаем просто.

public class runPro implements Runnable {
 public runPro(){}
 public void run(){ Thread.yield();
  MyPro.isn = new MainPro().execalc(); 
 }
}
Что здесь важно. Так как объект класса запускается внутри нити Thread, то он обязан поддерживать интерфейс Runnable. Согласно этому интерфейсу, когда нить стартует, то есть выполняется метод start(), у объекта ее класса автоматически запускается функция run(). По этой причине конструктор не имеет большого значения, но может быть и не пустым как у нас. В нем можно делать кое-какую работу. У нас он пустой. А вот функция run() никак не может быть пустой. Ее надо наполнить содержанием. Первая команда этой функции вызывает статический метод yield() нашей нити, который останавливает нить до тех пор, пока не будут выполнены все процессы на других траекториях. Это полезно делать всегда, даже если процессов и нет. Если очередь пустая, то эта функция ничего не делает. А дальше объявляется объект нового класса MainPro без имени, у которого сразу вызывается метод execalc(), который возвращает число в переменную MyPro.isn. Это один из фокусов Java. То же самое можно было бы написать и более длинно, например так:
MainPro mp = new MainPro(); MyPro.isn = mp.execalc();
Опять повторяю - совсем не обязательно так делать. Но я не люблю писать программу внутри функции run(). Поэтому я хочу писать программу в отдельном классе с названием MainPro. Давайте его сразу и писать. Вот здесь уже море вариантов. Я напишу программу, в которой будет один обязательный элемент и один показательный пример. Остальное уже на вашу инициативу. Впрочем мы написали только первый шаблон программы. Будут и другие.

class MainPro{
 Frame parent;

 public MainPro(){parent=MyPro.parent();}

 public int execalc(){
  int i,id; id=-1;
  if( MyPro.isn == 2 ){System.exit(0);}
  else 
  if( MyPro.isn == 5 ){String tit = "image"; 
   imagFrame imf = new imagFrame(tit,"icon.png");
   MainForm d = new MainForm(); JDesktopPane deskt = d.getDesktop(); deskt.add(imf);
   try{Thread.sleep(2000);}catch(InterruptedException ex){}
   JInternalFrame[] frames = deskt.getAllFrames();
   int im = frames.length;
   for( i=0; i < im; i++ ){ String ti = frames[i].getTitle();
    if( ti.equals(tit) ){ if( !frames[i].isClosed() ){
     try {frames[i].setClosed(true);} catch(java.beans.PropertyVetoException e){} }
   }} Thread.yield();
  }
  else
  if( MyPro.isn > 0 ){
   String mess = "Вы выбрали раздел меню номер "+MyPro.isn;
   JOptionPane.showMessageDialog(parent, mess, "Результат", JOptionPane.INFORMATION_MESSAGE);
   Thread.yield(); id=1;
  }
  return id;
 }
}
Здесь вам многое уже знакомо. Что нового. Функция showMessageDialog(), показывающая сообщение - это диалог. И она имеет первым аргументом как раз то окно, к которому его надо приклеить. Раньше в классе MainForm в качестве первого аргумента стояло this, то есть это окно. Теперь мы уже так написать не можем, так как мы совсем в другом классе. По этой причине нужно найти наше окно, что и делает функция MyPro.parent(). Кстати, в нашем случае ее сразу же можно было и поставить. Указанная сложная конструкция написана на будущее, когда ваша программа будет намного сложнее.

Мы в явном виде обработали только два раздела меню: второй и пятый. Название второго раздела "Exit" предполагает, что мы закрываем программу. При закрытии программы можно сделать сохранение необходимых параметров для последующей работы, уничтожить кое-какие временные файлы и еще много разных дел. Мы этого не делаем, а делаем только самое необходимое. Используем функцию exit() класса System, которая как раз и закрывает программу, причем с кодом выхода 0. Этот код можно использовать в командных файлах.

Название пятого раздела "Show/Image". Код, который здесь написан имеет скорее демонстрационный характер. Но для учебы он полезен. Здесь мы открываем объект нового класса imagFrame, конструктор которого имеет два аргумента - название окна "image" и название файла "icon.png". Естественно можно использовать и другие файлы с изображениями, но в дистрибутиве нашего курса нет других файлов. Класс imagFrame мы напишем как расширение класса JInternalFrame - это внутреннее окно и оно должно добавляться к объекту класса JDesktopPane. Но наш объект этого класса надо еще найти. Тут мы как раз используем обсуждавшийся выше прием. Откроем новый объект класса MainForm то есть d. Так как его конструктор пустой это нам ничего не испортит. Хотя объект новый, но его внутренний объект deskt является статическим и мы можем получить его методом getDesktop(). Это будет точно тот объект, который нам нужен. Добавим к нему внутреннее окно. Затем функцией sleep(2000) остановим нашу нить на 2 секунды (время указывается в миллисекундах). Эта функция обрабатывается на возможную ошибку, хотя для простоты здесь никакая обработка не указана. Просто синтаксис требует. Теперь мы хотим закрыть окно. Это можно сделать сразу. Но я привожу код, который является более общим и позволяет закрыть окно из любого класса. Метод getAllFrames() нашего объекта deskt возвращает все внутренние окна, которые он содержит. А дальше мы поступаем точно так же как в случае функции MyPro.parent(), то есть перебираем все окна и сравниваем их названия с нашим окном. Если названия совпадают, проверяем не закрыто ли уже это окно. Функция isClosed(), как легко догадаться, возвращает true если окно закрыто. Но в синтаксисе Java знак ! (восклицательный знак) перед логическим выражением означает прямо противоположный результат, то есть !true == false, а !false == true. Если окно не закрыто, мы его закрываем. Но опять обрабатываем на предмет ошибки. Вернее не обрабатываем, а соблюдаем синтаксис. Чтобы процесс прошел сразу же, надо остановить нашу нить.

Еще одно замечание. Приведенный выше код нормально работает. Но тот же самый результат можно было бы получить и другим способом. А именно, не вводить функцию public getDesktop(), а сразу объявить public static deskt и затем несколько раз писать MainForm.deskt не открывая новый объект класса MainForm. Результат в обоих вариантах один и тот же.

Нам теперь надо написать класс, который мы только что открыли.

class imagFrame extends JInternalFrame {
 Container pcont; File fs; JLabel lab; BufferedImage big;

 public imagFrame(String tit, String fn){
  setTitle(tit); setResizable(false); setClosable(true);
  setLocation(100,100); fs = new File(fn); 
  if( fs.exists() ){ 
   try{big = javax.imageio.ImageIO.read(fs);}
   catch(IOException ex){ex.printStackTrace();}
   Image im = big; ImageIcon img = new ImageIcon(im); lab = new JLabel(img);
   pcont = getContentPane(); pcont.add(lab, BorderLayout.CENTER); 
   pack(); this.setVisible(true);
 }}
}
В классах библиотеки swing содержимое окон прибавляется к контейнеру, который получается методом getContentPane(). Здесь мы определили заголовок окна методом setTitle(), задали режим запрета изменения размеров окна функцией setResizable(). Менять размеры бессмысленно, так как размер нашей картинки от этого не изменится. Затем мы задали режим возможности закрыть окно крестиком. Установили позицию окна и объявили о новом объекте класса File по имени файла. Если файл существует, то считываем из него картинку в объект класса BufferedImage. Затем надо передать эту картинку объекту класса Image, и объявить новый объект класса ImageIcon, который можно поставить в объект класса JLabel. Это уже как раз фрагмент нашего окна. Объекты класса JLabel обычно описывают комментарии к окнам ввода. Они содержат либо одну строку текста, либо картинку. Этот объект уже можно поставить в окно. Такая длинная цепочка была необходима для соответствия классов в определении конструкторов. Но ее можно было бы написать и покороче. Только без отсутствия опыта это менее понятно. При добавлении объектов в окно используются различные правила компоновки, называемые Layout. Эти правила компоновки не используют абсолютные координаты, что удобно при изменении размеров окна. Их можно специально заказывать, а можно устанавливать по умолчанию, как у нас и сделано. Так как у нас всего один объект, мы его просто поместили в центр. Функция pack() заменяет функцию setSize() и устанавливает такой размер окна, чтобы в нем не оставалось пустых мест, то есть упаковывает плотно. Ну и окно надо открыть, то есть сделать видимым. В Java2 все окна рисуются в памяти и процесс рисования не показывается. Окно зажигается уже в полностью готовом виде. Так намного красивее.

Теперь надо закрыть файл, назвать его runPro, так как именно этот класс является public, поскольку он использовался в другом классе, и добавить import *;

Все необходимые файлы уже набраны и являются приложением к этим лекциям. Вам осталось только прокомпилировать программу, запустив файл compile.bat и затем запустить ее используя файл run.bat.

Как сделать jar архив программы написано в следующей лекции.


[Назад]   [Вперед]
Hosted by uCoz