Microsoft Visual J++. Создание приложений и аплетов на языке Java. Часть 1© Александр Фролов, Григорий ФроловТом 30, М.: Диалог-МИФИ, 1997, 288 стр. Приложение NotebookПриложение Notebook служит в качестве более сложного примера техники работы с панелями. В окне аплета Notebook создаются три панели, расположенные в одном столбце. В верхней панели, имеющей рамку по периметру, рисуется строка текста “Смотри на шрифт, цвет фона и текста!”. Средняя панель представляет собой блокнот, предназначенный для выбора цвета фона, цвета изображения и шрифта для верхней панели. И, наконец, нижняя панель содержит кнопки, позволяющие перелистывать страницы блокнота. На рис. 7.4 показана страница, предназанченная для выбора цвета фона: Рис. 7.4. Страница, предназанченная для выбора цвета фона Нажимая кнопки Background Color, Foreground Color и Set Text Font, вы сможете выдвигать на передний план страницы блокнота, предназначенные, соответственно, для выбора цвета фона, изображения и шрифта, которым отображается текст в верхней панели. Кнопки Next и Prev работают таким же образом, что и в предыдущем приложении, а именно: если нажать на кнопку Next, произойдет пролистывание страниц в прямом направлении, а если на кнопку Prev - в обратном направлении. На рис. 7.5 изображена страница блокнота, предназначенная для выбора цвета изображения. Рис. 7.5. Страница, предназанченная для выбора цвета изображения На рис. 7.6 представлена страница, с помощью которой можно выбрать один из нескольких шрифтов для рисования текста в верхней панели. Рис. 7.6. Страница, предназанченная для выбора шрифта Рассмотрим исходные тексты приложения Notebook/ Исходные тексты приложенияИсходный текст приложения Notebook приведен в листинге 7.3. Листинг 7.3. Файл Notebook\Notebook.java // ========================================================= // Набор диалоговых панелей // // (C) Фролов А.В, 1997 // // E-mail: frolov@glas.apc.org // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // ========================================================= import java.applet.*; import java.awt.*; public class Notebook extends Applet { // Панель для размещения блокнота Panel pCardPanel; // Панель для размещения кнопок управления блокнотом Panel pButtonPanel; // Панель для рисования Panel pDraw; // Панели отдельных страниц Panel pBackgroundColor; // страница выбора цвета фона Panel pForegroundColor; // страница выбора цвета // изображения Panel pFont; // страница выбора шрифта // Кнопки выбора сраниц блокнота Button btnNext; // следующая Button btnPrev; // предыдущая Button btnBackgroundColor; // фон Button btnForegroundColor; // изображение Button btnFont; // шрифт // Создаем ссылки на объекты класса Choice Choice chBackgroundColor; // список цветов фона Choice chForegroundColor; // список цветов изображения Choice chFont; // список шрифтов // Текстовые метки списков Label tBackgroundColor; // метка списка цветов фона Label tForegroundColor; // метка списка цветов // изображения Label tFont; // метка списка шрифтов // Строка для хранения название выбранного шрифта String sFontName; // ------------------------------------------------------- // getAppletInfo // Метод, возвращающей строку информации об аплете // ------------------------------------------------------- public String getAppletInfo() { return "Name: Grid\r\n" + "Author: Alexandr Frolov\r\n" + "E-mail: frolov@glas.apc.org" + "WWW: http://www.glasnet.ru/~frolov" + "Created with Microsoft Visual J++ Version 1.1"; } // ------------------------------------------------------- // init // Метод, получающий управление при инициализации аплета // ------------------------------------------------------- public void init() { // Устанавливаем желтый цвет фона setBackground(Color.yellow); // ---------------------------------------------------- // Создаем в окне аплета две панели, разделяющие // окно по горизонтали. В верхней панели будет // находиться блокнот, в нижней - кнопки управления // блокнотом // ---------------------------------------------------- setLayout(new GridLayout(3, 1)); // Создаем панель блокнота pCardPanel = new Panel(); // ---------------------------------------------------- // Создаем панели страниц блокнота // ---------------------------------------------------- // Панель для выбора цвета фона pBackgroundColor = new Panel(); // Панель для выбора цвета изображения pForegroundColor = new Panel(); // Панель для выбора шрифта pFont = new Panel(); // ---------------------------------------------------- // Создаем списки для выбора цвета фона и // цвета изображения // ---------------------------------------------------- // Список для выбора цвета фона chBackgroundColor = new Choice(); // Список для выбора цвета изображения chForegroundColor = new Choice(); // Список для выбора шрифта chFont = new Choice(); // ---------------------------------------------------- // Создаем метки для списков // ---------------------------------------------------- // Метка для списка цвета фона tBackgroundColor = new Label("Chose Background Color:"); // Метка для списка цвета изображения tForegroundColor = new Label("Chose Foreground Color:"); // Метка для списка шрифтов tFont = new Label("Chose Font:"); // ---------------------------------------------------- // Добавляем списки и метки в панели // ---------------------------------------------------- // Список цвета фона и метка pBackgroundColor.add(tBackgroundColor); pBackgroundColor.add(chBackgroundColor); // Список цвета изображения и метка pForegroundColor.add(tForegroundColor); pForegroundColor.add(chForegroundColor); // Список шрифтов и метка pFont.add(tFont); pFont.add(chFont); // ---------------------------------------------------- // Заполняем списки // ---------------------------------------------------- // Заполняем список цвета фона chBackgroundColor.addItem("Yellow"); chBackgroundColor.addItem("Green"); chBackgroundColor.addItem("White"); // Заполняем список цвета изображения chForegroundColor.addItem("Black"); chForegroundColor.addItem("Red"); chForegroundColor.addItem("Blue"); // Заполняем список шрифтов chFont.addItem("Helvetica"); chFont.addItem("Courier"); chFont.addItem("TimesRoman"); // Создаем панель для рисования pDraw = new Panel(); // Устанавливаем режим размещения для блокнота pCardPanel.setLayout(new CardLayout(5, 5)); // ---------------------------------------------------- // Добавляем панели страниц в блокнот // ---------------------------------------------------- // Панель выбора цвета фона pCardPanel.add("BackgroundColor", pBackgroundColor); // Панель выбора цвета изображения pCardPanel.add("ForegroundColor", pForegroundColor); // Панель выбора шрифта pCardPanel.add("Font", pFont); // Добавляем панель для рисования в окно аплета add(pDraw); // Добавляем панель блокнота в окно аплета add(pCardPanel); // ---------------------------------------------------- // Создаем кнопки управления блокнотом // ---------------------------------------------------- // Кнопка просмотра следующей страницы блокнота btnNext = new Button("Next"); // Кнопка просмотра предыдущей страницы блокнота btnPrev = new Button("Prev"); // Выбор панели цвета фона btnBackgroundColor = new Button("Background Color"); // Выбор панели цвета изображения btnForegroundColor = new Button("Foreground Color"); // Выбор панели шрифтов btnFont = new Button("Set Text Font"); // Создаем панель кнопок управления блокнотом pButtonPanel = new Panel(); // Устанавливаем режим размещения для панели кнопок pButtonPanel.setLayout(new FlowLayout()); // Добавляем кнопки в панель кнопок pButtonPanel.add(btnBackgroundColor); pButtonPanel.add(btnForegroundColor); pButtonPanel.add(btnFont); pButtonPanel.add(btnNext); pButtonPanel.add(btnPrev); // Добавляем панель кнопок add(pButtonPanel); // Выбираем шрифт по умолчанию sFontName = new String("Helvetica"); // Отображаем окно аплета show(); } // ------------------------------------------------------- // action // Метод вызывается, когда пользователь выполняет // действие над компонентами // ------------------------------------------------------- public boolean action(Event evt, Object obj) { // Проверяем, что событие вызвано кнопкой, а не // другим компонентом if(evt.target instanceof Button) { // Ссылка на кнопку, от которой пришло сообщение Button btn; // Получам ссылку на кнопку, вызвавшую событие btn = (Button)evt.target; // Выполняем ветвление по кнопкам. Для каждой кнопки // записываем ее название в строку состояния // навигатора if(evt.target.equals(btnNext)) // Выбираем следующую страницу в блокноте ((CardLayout)pCardPanel.getLayout()).next(pCardPanel); else if(evt.target.equals(btnPrev)) // Выбираем предыдущую страницу в блокноте ((CardLayout)pCardPanel.getLayout()).previous(pCardPanel); else if(evt.target.equals(btnBackgroundColor)) // Выбираем страницу цвета фона ((CardLayout)pCardPanel.getLayout()).show( pCardPanel, "BackgroundColor"); else if(evt.target.equals(btnForegroundColor)) // Выбираем страницу цвета изображения ((CardLayout)pCardPanel.getLayout()).show( pCardPanel, "ForegroundColor"); else if(evt.target.equals(btnFont)) // Выбираем страницу шрифтов ((CardLayout)pCardPanel.getLayout()).show( pCardPanel, "Font"); // Если событие возникло от неизвестной кнопки, // мы его не обрабатываем, передавая методу action // родительского класса else return super.action(evt, obj); // Перерисовываем окно панели pDraw и аплета pDraw.repaint(); repaint(); // Возвращаем признак того, что мы обработали событие return true; } // Обработка событий от списков else if(evt.target instanceof Choice) { // Переменная для хранения ссылки на список, // вызвавший событие Choice ch; // Получаем ссылку на список ch = (Choice)evt.target; // Выполняем ветвление по спискам // Список цвета фона if(evt.target.equals(chBackgroundColor)) { // Получаем номер текущего элемента списка // и устанавливаем соответствующий // цвет фона if(ch.getSelectedIndex() == 0) pDraw.setBackground(Color.yellow); else if(ch.getSelectedIndex() == 1) pDraw.setBackground(Color.green); else if(ch.getSelectedIndex() == 2) pDraw.setBackground(Color.white); } // Список цвета изображения else if(evt.target.equals(chForegroundColor)) { // Получаем номер текущего элемента списка // и устанавливаем соответствующий // цвет изображения if(ch.getSelectedIndex() == 0) pDraw.setForeground(Color.black); else if(ch.getSelectedIndex() == 1) pDraw.setForeground(Color.red); else if(ch.getSelectedIndex() == 2) pDraw.setForeground(Color.blue); } // Список шрифтов else if(evt.target.equals(chFont)) { // Получаем номер текущего элемента списка // и записываем имя соответствующего шрифта // в строку sFontName if(ch.getSelectedIndex() == 0) sFontName = "Helvetica"; else if(ch.getSelectedIndex() == 1) sFontName = "Courier"; else if(ch.getSelectedIndex() == 2) sFontName = "TimesRoman"; } // Если событие возникло от неизвестного списка, // мы его не обрабатываем, передавая методу action // родительского класса else return super.action(evt, obj); // Перерисовываем панель pDraw pDraw.repaint(); // Перерисовываем окно аплета repaint(); // Возвращаем признак того, что мы обработали событие return true; } // Вызываем метод action родительского класса return super.action(evt, obj); } // ------------------------------------------------------- // paint // Метод paint, выполняющий рисование в окне аплета // ------------------------------------------------------- public void paint(Graphics g) { Graphics gpDraw; // Получаем контекст отображения для панели рисования gpDraw = pDraw.getGraphics(); // Определяем текущие размеры Dimension dimAppWndDimension = pDraw.size(); // Рисуем рамку вокруг окна аплета gpDraw.drawRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); // Устанавливаем шрифт gpDraw.setFont(new Font(sFontName, Font.PLAIN, 12)); // Рисуем строку gpDraw.drawString( "Смотри на шрифт, цвет фона и текста!", 10, 50); // Получаем контекст отображения для панели блокнота gpDraw = pCardPanel.getGraphics(); // Определяем размеры панели блокнота dimAppWndDimension = pCardPanel.size(); // Обводим блокнот рамкой gpDraw.drawRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); } } В листинге 7.4 вы найдете исходный текст документа HTML, созданного для размещения аплета. Листинг 7.4. Файл Notebook\Notebook.html <html> <head> <title>Notebook</title> </head> <body> <hr> <applet code=Notebook.class id=Notebook width=320 height=240 > </applet> <hr> <a href="Notebook.java">The source.</a> </body> </html> Описание исходного текстаВ классе Notebook определено довольно много полей и переопределено несколько методов. Поля класса NotebookВ полях pDraw, pCardPanel и pButtonPanel находятся ссылки, соответственно, на верхнюю, среднюю и нижнюю панели, предназначенные для рисования, размещения блокнота диалоговых панелей настроек и кнопок управления блокнотом. В предыдущем приложении на страницах блокнота размещались кнопки. Теперь мы решили более сложную задачу - поместили на страницы блокнота три панели, по одной на каждую страницу. Первая из этих панелей содержит список для выбора цвета фона, вторая - для выбора цвета изображения и, наконец, третья, для выбора шрифта. Поля pBackgroundColor, pForegroundColor и pFont хранят ссылки на соответствующие панели настроек. Нижняя панель содержит кнопки управления страницами блокнота. С помощью кнопок, ссылки на которые хранятся в полях btnBackgroundColor, btnForegroundColor и btnFont вы можете выбирать для отображения страницы блокнота, содержащие панели настройки цвета фона, изображения и шрифта. Таким образом, нет необходимости перебирать страницы блокнота по очереди до тех пор, пока в окне не появится нужная страница. Тем не менее, мы предусмотрели кнопки и для циклического перебора страниц блокнота. Ссылки на эти кнопки хранятся в полях btnNext и btnPrev. На каждой панели в блокноте размещается один список и одна надпись, объясняющая назначение списка. Списки создаются как объекты класса Choice, а надписи - как объекты класса Label. Поля chBackgroundColor, chForegroundColor и chFont хранят ссылки на списки, соответственно, цвета фона, цвета изображения и шрифтов. В полях tBackgroundColor, tForegroundColor и tFont хранятся ссылки надписей. Поле sFontName класса String предназначено для хранения названия текущего шрифта, с использованием которого отображается текст в верхней панели. Метод getAppletInfoМетод getAppletInfo возвращает информацию об аплете. Метод initМетод init выполняет достаточно громоздкую работу по созданию и добавлению различных панелей и других компонентов. К сожалению, приложениям Java не доступны ресурсы, аналогичные ресурсам операционной системы Microsoft Windows, поэтому формирование диалоговых панелей и других элементов пользовательского интерфейса приходится выполнять чисто программными методами на этапе выполнения приложения. Средства среды разработки приложений Java Microsoft Visual J++ версии 1.1, о которых мы уже упоминали, позволяют несколько упростить этот процесс. Свою работу метод init начинает с установки желтого цвета фона для окна аплета. Далее устанавливается режим добавления GridLayout, разделяющий окно аплета на три части по горизонтали: setLayout(new GridLayout(3, 1)); Соответствующая таблица, в которую будут добавляться компоненты, имеет три строки и один столбец. Панель блокнота создается следующим образом: pCardPanel = new Panel(); Затем создаются три панели, которые будут добавляться в панель pCardPanel: pBackgroundColor = new Panel(); pForegroundColor = new Panel(); pFont = new Panel(); Эти панели предназначены для размещения компонент, с помощью которых можно будет выбирать цвет фона и изображения, а также шрифт. На следующем этапе создаются три списка, которые будут размещаться по одному на указанных панелях: chBackgroundColor = new Choice(); chForegroundColor = new Choice(); chFont = new Choice(); Каждый такой список снабжается надписью, поясняющей его назначение. Надписи создаются следующим образом: tBackgroundColor = new Label("Chose Background Color:"); tForegroundColor = new Label("Chose Foreground Color:"); tFont = new Label("Chose Font:"); Созданные метки и списки добавляются в панели, расположенные на страницах блокнота: pBackgroundColor.add(tBackgroundColor); pBackgroundColor.add(chBackgroundColor); pForegroundColor.add(tForegroundColor); pForegroundColor.add(chForegroundColor); pFont.add(tFont); pFont.add(chFont); Вначале мы добавляем надпись, затем список. Поэтому надпись будет расположена слева от списка. Заполнение списков выполняется с помощью метода addItem, который вызывается по очереди для каждого списка и для каждого добавляемого элемента списка: chBackgroundColor.addItem("Yellow"); chBackgroundColor.addItem("Green"); chBackgroundColor.addItem("White"); chForegroundColor.addItem("Black"); chForegroundColor.addItem("Red"); chForegroundColor.addItem("Blue"); chFont.addItem("Helvetica"); chFont.addItem("Courier"); chFont.addItem("TimesRoman"); Далее метод init приступает к формированию верхенй панели, предназначенной для отображения текстовой строки. Панель создается следующим образом: pDraw = new Panel(); Затем метод init начинает наполнение страниц блокнота. Прежде всего он устанавливает режим добавления CardLayout, оставляя зазор по вертикали и горизонтали в 5 пикселов: pCardPanel.setLayout(new CardLayout(5, 5)); Панели добавляются методом add, причем мы выбрали вариант этого метода, допускающий присваивание имен добавляемым компонентам: pCardPanel.add("BackgroundColor", pBackgroundColor); pCardPanel.add("ForegroundColor", pForegroundColor); pCardPanel.add("Font", pFont); Имена, которые передаются через первый параметр, необходимы для отображения страниц блокнота с помощью кнопок btnBackgroundColor, btnForegroundColor и btnFont. После заполнения страниц блокнота метод init добавляет верхнюю и среднюю панели в окно аплета: add(pDraw); add(pCardPanel); В процессе формирования нижней панели метд init создает кнопки, предназначенные для управления блокнотом: btnNext = new Button("Next"); btnPrev = new Button("Prev"); btnBackgroundColor = new Button("Background Color"); btnForegroundColor = new Button("Foreground Color"); btnFont = new Button("Set Text Font"); pButtonPanel = new Panel(); Перед добавлением кнопок в нижней панели устанавливается режим размещения FlowLayout: pButtonPanel.setLayout(new FlowLayout()); Затем кнопки добавляются в панель вызовом метода add: pButtonPanel.add(btnBackgroundColor); pButtonPanel.add(btnForegroundColor); pButtonPanel.add(btnFont); pButtonPanel.add(btnNext); pButtonPanel.add(btnPrev); После формирования панели кнопок эта панель добавляется в окно аплета, располагаясь в его нижней части: add(pButtonPanel); В поле sFontName записывается имя шрифта, выбранного по умолчанию: sFontName = new String("Helvetica"); На завершающем этапе метод init выполняет принудительную перерисовку и отображение панелей, вызывая специально предназначенный для этого метод show: show(); Метод actionМетод action выполняет раздельную обработку событий, вызванных кнопками и списками. Если событие было вызвано кнопками, выполняется переключение страниц блокнота: if(evt.target.equals(btnNext)) ((CardLayout)pCardPanel.getLayout()).next(pCardPanel); else if(evt.target.equals(btnPrev)) ((CardLayout)pCardPanel.getLayout()).previous(pCardPanel); else if(evt.target.equals(btnBackgroundColor)) ((CardLayout)pCardPanel.getLayout()).show( pCardPanel, "BackgroundColor"); else if(evt.target.equals(btnForegroundColor)) ((CardLayout)pCardPanel.getLayout()).show( pCardPanel, "ForegroundColor"); else if(evt.target.equals(btnFont)) ((CardLayout)pCardPanel.getLayout()).show( pCardPanel, "Font"); Для выбора следующей и предыдущей страницы здесь использованы методы next и previous. Выбор конкретной страницы по ее имени осуществляется с помощью метода show. В качестве параметров этому методу передается ссылка на панель блокнота и имя страницы. Обратите также внимание на способ обработки событий, не имеющих отношения к нашим компонентам: return super.action(evt, obj); Здесь мы вызываем метод action из базового класса, который после соответствующей обработки события вернет значение true или false. Если событие вызвано кнопками управления блокнотом, мы перерисовываем окно верхней панели, окно всего аплета и затем возвращаем признак успешной обработки события: pDraw.repaint(); repaint(); return true; Как вы увидите дальше, в процессе перерисовки окна всего аплета метод paint выполнит рисование в окне верхней панели. События, связанные с выбором нового цвета фона и изображения обрабатываются следующим образом: if(evt.target.equals(chBackgroundColor)) { if(ch.getSelectedIndex() == 0) pDraw.setBackground(Color.yellow); else if(ch.getSelectedIndex() == 1) pDraw.setBackground(Color.green); else if(ch.getSelectedIndex() == 2) pDraw.setBackground(Color.white); } else if(evt.target.equals(chForegroundColor)) { if(ch.getSelectedIndex() == 0) pDraw.setForeground(Color.black); else if(ch.getSelectedIndex() == 1) pDraw.setForeground(Color.red); else if(ch.getSelectedIndex() == 2) pDraw.setForeground(Color.blue); } Здесь методы setBackground и setForeground устанавливают цвет фона и изображения для панели pDraw. Если событие вызвано списком шрифтов, то мы получаем номер элемента списка и записываем название выбранного шрифта в текстовую строку sFontName: else if(evt.target.equals(chFont)) { if(ch.getSelectedIndex() == 0) sFontName = "Helvetica"; else if(ch.getSelectedIndex() == 1) sFontName = "Courier"; else if(ch.getSelectedIndex() == 2) sFontName = "TimesRoman"; } После обработки события, вызванного списками, мы перерисовываем окно панели рисования pDraw и окно аплета: pDraw.repaint(); repaint(); Метод paintМетод paint рисует в окне панели pDraw, а не в главном окне аплета. Для этого метод paint получает контекст отображения этой панели, вызывая для этого метод getGraphics: Graphics gpDraw; gpDraw = pDraw.getGraphics(); Далее метод paint определяет размеры панели pDraw и рисует рамку вокруг окна этой панели: Dimension dimAppWndDimension = pDraw.size(); gpDraw.drawRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); После того как рамка будет нарисована, метод paint устанавливает в панели pDraw шрифт, название которого хранится в староке sFontName. Для этого используется контекст отображения gpDraw, полученный нами ранее для панели pDraw: gpDraw.setFont(new Font(sFontName, Font.PLAIN, 12)); Текстовая строка отображается с использованием текущего цвета изображения и текущего шрифта, установленного в контексте отображения gpDraw, при помощи метода drawString: gpDraw.drawString("Смотри на шрифт, цвет фона и текста!", 10, 50); Затем метод paint обводит панель блокнота рамкой. Вначале он получает контекст отображения для панели блокнота, как это показано ниже: gpDraw = pCardPanel.getGraphics(); После получения контекста отображения метод paint определяет размеры панели блокнота и рисует рамку вокруг его окна: dimAppWndDimension = pCardPanel.size(); gpDraw.drawRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); |