Разработка собственных объектов.

В большинстве случаев, при разработки приложений, необходимо создавать собственные объекты. Это обусловлено тем, что язык Java является объектно-ориентированным и вся обработка информации происходит на уровне объекта. В общем случае описание объекта имеет следующий вид:

package имя пакета;

// Подключение библиотек, используемых новым компонентом

class имя компонента extends имя базового компонента

{

// свойства и методы нового компонента

};

Объекты могут быть визуальными, то есть видимыми на форма и невидимыми, то есть хранящиеся в только в памяти.

Рассмотри построение собственного визуального компонента на примере объекта вывода графика функции. В качестве базового компонента будем использовать класс JPanel.

package имя пакета;

// Библиотека базового класса нашего компонента

import javax.swing.JPanel;

// Библиотека класса графических примитивов

import java.awt.Graphics;

// Библиотека сервисных функций шрифтов

import java.awt.FontMetrics;

// Библиотека палитры.

import java.awt.Color;

// Библиотека математических функций

import java.lang.Math;

// Создаем компонент.

class имя компонента extends JPanel

{

// Определение переменных

// Определяем массив для хранения значений оси X.

private double val_x[]=null;

// Определяем массив для хранения значений оси Y.

private double val_y[]=null;

// Определяем переменные ограничивающие размеры графика

// по оси X и Y.

private double Xmin=0;

private double Xmax=0;

private double Ymin=0;

private double Ymax=0;

};

// Конструктор класса

public имя компонента() {

// Устанавливаем цвет фона данного компонента

this.setBackground(Color.white);

}

// Установка и первичная обработка данных

// для построения графика

void setDataGraph(double _val_x[],double _val_y[])

{

// Устанавливаем значения массивов

val_x=_val_x;

val_y=_val_y;

// Вычисляем диапазон по оси X

if(vay_x!=null)

{

Xmin=val_x[0];

Xmax=val_x[0];

For(int i=0;i<val_x.length;i++)

{

if(Xmin>val_x[i])Xmin=val_x[i];

if(Xmax<val_x[i])Xmax=val_x[i];

}

}

else

{

Xmin=0;

Xmax=0;

}

// Вычисляем диапазон по оси Y

if(val_y!=null)

{

Ymin=val_y[0];

Ymax=val_y[0];

for(int i=1;i<val_y.length;i++)

{

if(Ymin>val_y[i])Ymin=val_y[i];

if(Ymax<val_y[i])Ymax=val_y[i];

}

}

else

{

Ymin=0;

Ymax=0;

}

// Увиличиваем диапазон, для предотвращения выхода

// за пределы окна по оси X

double delta=Math.abs(Xmax-Xmin)*0.05;

Xmin-=delta;

Xmax+=delta;

// Увиличиваем диапазон, для предотвращения выхода

// за пределы окна по оси Y

delta=Math.abs(Ymax-Ymin)*0.05;

Ymin-=delta;

Ymax+=delta;

// Вызываем перерисовку, для отображения полученных результатов

this.repaint();

}

// В большинстве случаем при построении каких либо графиков или диаграмм

// необходимо преобразовывать (приводить) исходные данные к пространству

// компонентов. Для этого необходимо вычислить коэффициенты

// масштабирования (множители) приведения и положение нулевой точки

// координат.

// По оси X коэффициент приведения вычисляется как отношение ширины

// компонента к диапазону X, а по оси Y как отношение высоты компонента

// к диапазону по оси Y

// Определение коэффициента масштабирования

// по оси X

private double GetKmX()

{

double space_x=Xmax-Xmin;

if(space_x==0)return 0;

return (double)this.getWidth()/space_x;

}

// Определение коэффициента масштабирования

// по оси Y

private double GetKmY()

{

double space_y=Ymax-Ymin;

if(space_y==0)return 0;

return (double)this.getHeight()/space_y;

}

// Определение положения нулевой точки

// по оси X

private int GetCenterX()

{

double tmp=0;

if(Xmin<0 && Xmax>0)tmp=-Xmin*GetKmX();

else if(Xmax<0)tmp=(double)this.getWidth();

return (int)tmp;

}

// Определение положения нулевой точки

// по оси Y

private int GetCenterY()

{

double tmp=0;

if(Ymin<0 && Ymax>0)tmp=this.getHeight()-(-Ymin*GetKmY());

else if(Ymax<0)tmp=(double)this.getHeight();

return (int)tmp;

}

// Далее идет описание функций определения положения точки

// приведенной к размерам окна и положению центра координат

// Получение значения абсциссы приведенной к размерам окна

private int GetX(int idx)

{

if(val_x==null)return 0;

int i_pos=(int)(double)(val_x[idx]*GetKmX());

return GetCenterX()+i_pos;

}

// Получение значения ординаты приведенной к размерам окна

private int GetY(int idx)

{

if(val_y==null)return 0;

int i_pos=(int)(double)(val_y[idx]*GetKmY());

return GetCenterY()-i_pos;

}

// Поскольку в языке Java пока отсутствуют функции форматированного

// ввода-вывода то необходимо описать функцию преобразования

// вещественного числа в строку по указанному формату.

// Функция преобразования вещественного числа в строку.

private String float_to_str(double val,String format)

{

int idx_dec=format.indexOf('.');

if(idx_dec==-1)return String.valueOf(val);

String dec_str=format.substring(idx_dec+1);

int cnt_dec=0;

for(int i=0;i<dec_str.length();i++)

{

if(dec_str.charAt(i)!='0')break;

cnt_dec++;

}

double prepare_f=val;

double delta=0.5;

for(int i=0;i<cnt_dec;i++)delta/=10;

prepare_f+=delta;

String fl_str=String.valueOf(prepare_f);

int idx_int=fl_str.indexOf(',');

if(idx_int==-1)idx_int=fl_str.indexOf('.');

String base=fl_str;

String expn="";

if(idx_int!=-1)base=fl_str.substring(0,idx_int);

if(idx_int!=-1)expn=fl_str.substring(idx_int+1);

while(expn.length()<cnt_dec)

{

expn+="0";

}

fl_str=base+","+expn.substring(0,cnt_dec)+dec_str.substring(cnt_dec);

return fl_str;

}

// Далее идет функция рисования координатных осей

private void draw_coord(Graphics g,int mode)

{

Color save_color=g.getColor(); // Сохраняем текущий цвет

g.setColor(Color.black); // Устанавливаем черный цвет осей

double delta_x=0;

double delta_y=0;

FontMetrics fm=g.getFontMetrics(); // Определяем параметры шрифта

if(mode==0)

{

// Рисование оси Y

g.drawLine(GetCenterX()-1,4,GetCenterX()-1,this.getHeight()-3);

g.drawLine(GetCenterX(),3,GetCenterX(),this.getHeight()-3);

g.drawLine(GetCenterX()+1,4,GetCenterX()+1,this.getHeight()-3);

g.drawLine(GetCenterX()-5,13,GetCenterX(),3);

g.drawLine(GetCenterX()+5,13,GetCenterX(),3);

// Вывод заголовка метки оси Y

g.drawString("Y",GetCenterX()+10,fm.getHeight()+3);

delta_y=Math.max(Math.abs(Ymin),Math.abs(Ymax))/10;

delta_y=Math.ceil(delta_y*10)/10;

}

else

{

// Рисование оси X

g.drawLine(3,GetCenterY()-1,this.getWidth()-4,GetCenterY()-1);

g.drawLine(3,GetCenterY(),this.getWidth()-3,GetCenterY());

g.drawLine(3,GetCenterY()+1,this.getWidth()-4,GetCenterY()+1);

g.drawLine(this.getWidth()-13,GetCenterY()-5,

this.getWidth()-3,GetCenterY());

g.drawLine(this.getWidth()-13,GetCenterY()+5,

this.getWidth()-3,GetCenterY());

// Вывод заголовка метки оси X

g.drawString("X",this.getWidth()-fm.charWidth('X')*2,

GetCenterY()+fm.getHeight());

delta_x=Math.max(Math.abs(Xmin),Math.abs(Xmax))/10;

delta_x=Math.ceil(delta_x*10)/10;

}

// Вывод масштабных линий

double tmp_x=delta_x;

double tmp_y=delta_y;

for(int i=0;i<10;i++)

{

if(delta_x!=0)

{

int i_pos=(int)((double)tmp_x*GetKmX());

String txt=float_to_str(tmp_x,"0.0");

if(tmp_x<Math.abs(Xmin))

{

g.drawLine(GetCenterX()-i_pos,GetCenterY()-5,

GetCenterX()-i_pos,GetCenterY()+5);

if((i%2)==0)

{

g.drawString("-"+txt,GetCenterX()-i_pos-

fm.stringWidth("-"+txt)/2,GetCenterY()+fm.getHeight());

}

}

if(tmp_x<Math.abs(Xmax))

{

g.drawLine(GetCenterX()+i_pos,GetCenterY()-5,

GetCenterX()+i_pos,GetCenterY()+5);

if((i%2)==0)

{

g.drawString(txt,GetCenterX()+i_pos-

fm.stringWidth(txt)/2,GetCenterY()+fm.getHeight());

}

}

}

if(delta_y!=0)

{

int i_pos=(int)((double)tmp_y*GetKmY());

String txt=float_to_str(tmp_y,"0.0");

if(tmp_y<Math.abs(Ymin))

{

g.drawLine(GetCenterX()-5,GetCenterY()+i_pos,

GetCenterX()+5,GetCenterY()+i_pos);

if((i%2)==0)

{

g.drawString("-"+txt,GetCenterX()-5-

fm.stringWidth("-"+txt),

GetCenterY()+i_pos+fm.getHeight()/2);

}

}

if(tmp_y<Math.abs(Ymax))

{

g.drawLine(GetCenterX()-5,GetCenterY()-i_pos,

GetCenterX()+5,GetCenterY()-i_pos);

if((i%2)==0)

{

g.drawString(txt,GetCenterX()-5-

fm.stringWidth(txt),

GetCenterY()-i_pos+fm.getHeight()/2);

}

}

}

tmp_x+=delta_x;

tmp_y+=delta_y;

}

g.setColor(save_color);

if(mode==0)draw_coord(g,1);

}

// Функция рисования графика. Функция paint является виртуальной

// функцией класса JPanel. При определении виртуальной функции, вызов

// будет происходить аналогично языку C++

public void paint(Graphics g)

{

super.paint(g);

if(val_x==null || val_y==null)return;

draw_coord(g,0);

Color save_color=g.getColor();

g.setColor(Color.red);

int save_x=GetX(0);

int save_y=GetY(0);

for(int i=1;i<val_x.length-1;i++)

{

g.drawLine(save_x,save_y,GetX(i),GetY(i));

save_x=GetX(i);

save_y=GetY(i);

}

g.setColor(save_color);

}

}

 

7.1. Объекты управления

К объектам управления в языке Java относятся все компоненты, имеющие обработчики событий. В большинстве случаев в качестве объектов управления используются кнопки, меню, панели управления. В общем случае управление поведением программы имеет структуру приведенную на рисунке 1:

Рис. 1. Структурная схема обработки событий

 

На данном рисунку К.У. – компонент управления, а О– управляемый объект. Из рисунка видно, что компонент управления передает команду форме, а форма уже распределяет эти команды в зависимости от принадлежности соответствующим компонентам.

Стандартные компоненты управления приведены в таблице 4.

Таблица 4. Стандартные компоненты управления.

Компонент Комментарии
JButton Кнопка библиотеки SWING. Событие генерируется при нажатии кнопки.
JRadioButton Кнопка выбора варианта библиотеки SWING. Событие генерируется при изменении состояния кнопки.
JCheckBox Кнопка флага библиотеки SWING. Событие генерируется при изменении состояния кнопки.
JMenuItem Строка меню SWING. Событие генерируется при выборе пункта меню.
Button Кнопка библиотеки AWT. Событие генерируется при нажатии кнопки.
RadioButton Кнопка выбора варианта библиотеки AWT. Событие генерируется при изменении состояния кнопки.
CheckBox Кнопка флага библиотеки AWT. Событие генерируется при изменении состояния кнопки.
MenuItem Строка меню AWT. Событие генерируется при выборе пункта меню.

 

В общем случае любой компонент может генерировать события, в зависимости от его назначения. Язык Java позволяет обрабатывать все события мыши и клавиатуры, в зависимости от их необходимости.

Так рассмотрим обработку событий формы на примере формы построения графика функции. Предположим, что нам задана функция:

и в результате мы хотим получить приложение выполняющее построение графика этой функции следующего вида:

Рис.2.

 

На данной форме расположены окна редактирования, в которые вводятся исходные параметры для построения графика, компонент управления (кнопка «Обработать») и управляемый объект (область построения графика). Целью формы является связь визуальных компонентов (управляющих и управляемых) между собой. Программа связи компонентов будет иметь следующий вид:

package имя пакута;

// Подключение необходимых библиотек:

// Подключаем стандартную библиотеку работы с окнами

import java.awt.*;

// Подключаем стандартную библиотеку обработки событий

// окон, она необходима для обработки системных сообщений

import java.awt.event.*;

// Подключаем расширенную библиотеку работы с окнами

import javax.swing.*;

// Подключаем библиотеку позиционирования

import com.borland.jbcl.layout.*;

// Класс-оболочку для преобразования вещественных чисел

import java.lang.Double;

// Класс математических функций

import java.lang.Math;

 

// Описываем класс формы, используя базовым классом

// класс расширенной библиотеки работы с окнами.

public class имя формы extends JFrame {

JPanel contentPane; // Переменная связанная с корневой панелью формы

// Создаем объект позиционирования компонентов на форме

BorderLayout borderLayout1 = new BorderLayout();

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

JPanel tool_panel = new JPanel();

// Объект позиционирования компонентов на контейнере управления

XYLayout xYLayout1 = new XYLayout();

// Создаем метки и поля редактирования для ввода исходных данных.

JLabel a_label = new JLabel();

JTextField a_text = new JTextField();

JLabel b_label = new JLabel();

JTextField b_text = new JTextField();

JLabel c_label = new JLabel();

JTextField c_text = new JTextField();

JLabel xn_label = new JLabel();

JTextField xn_text = new JTextField();

JLabel xk_label = new JLabel();

JTextField xk_text = new JTextField();

JLabel dx_label = new JLabel();

JTextField dx_text = new JTextField();

// Создаем компонент управления

JButton update_btn = new JButton();

// Создаем объект отображения графической информации, в нашем

// случае управляемый объект описанный выше.

Имя класса graph=new Имя класса();

// Описываем переменные для ввода исходных данных

double val_x[]=null;

double val_y[]=null;

// Конструктор класса

public имя формы() {

// Устанавливаем перехватчик событий окон, в нашем случае необходим

// для обработки системной команды закрытия окна.

enableEvents(AWTEvent.WINDOW_EVENT_MASK);

try {

// Инициализируем компоненты.

jbInit();

}

catch(Exception e) {

e.printStackTrace();

}

}

// Функция инициализации компонентов

private void jbInit() throws Exception {

// Получаем корневую панель формы

contentPane = (JPanel) this.getContentPane();

// Устанавливаем способ позиционирования компонентов на форме

contentPane.setLayout(borderLayout1);

// Устанавливаем размеры окна и его заголовок

this.setSize(new Dimension(550, 400));

this.setTitle("Построение графиков функций");

// Устанавливаем параметры контейнера компонентов управления

tool_panel.setBorder(BorderFactory.createEtchedBorder());

tool_panel.setMinimumSize(new Dimension(10, 27));

tool_panel.setPreferredSize(new Dimension(10, 27));

tool_panel.setLayout(xYLayout1);

// Определяем параметры меток и полей ввода исходных данных

a_label.setText("A:");

a_text.setMinimumSize(new Dimension(35, 21));

a_text.setPreferredSize(new Dimension(35, 21));

a_text.setText("100");

b_label.setText("B:");

b_text.setText("5");

b_text.setPreferredSize(new Dimension(35, 21));

b_text.setMinimumSize(new Dimension(35, 21));

c_label.setText("C:");

c_text.setMinimumSize(new Dimension(35, 21));

c_text.setPreferredSize(new Dimension(35, 21));

c_text.setText("150");

xn_label.setText("Xнач:");

xn_text.setText("-20");

xn_text.setPreferredSize(new Dimension(35, 21));

xn_text.setMinimumSize(new Dimension(35, 21));

xk_label.setText("Xкон:");

xk_text.setMinimumSize(new Dimension(35, 21));

xk_text.setPreferredSize(new Dimension(35, 21));

xk_text.setText("30");

dx_text.setText("1");

dx_text.setPreferredSize(new Dimension(35, 21));

dx_text.setMinimumSize(new Dimension(35, 21));

dx_label.setText("DX:");

// Определяем параметры компонента управления

update_btn.setBorder(BorderFactory.createEtchedBorder());

update_btn.setMaximumSize(new Dimension(75, 23));

update_btn.setMinimumSize(new Dimension(75, 23));

update_btn.setPreferredSize(new Dimension(73, 23));

update_btn.setText("Обработать");

// Устанавливаем компоненту управления, класс обработки события нажатия

// на него.

update_btn.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(ActionEvent e) {

update_btn_actionPerformed(e);

}

});

// Закрепляем панель управления на форме

contentPane.add(tool_panel, BorderLayout.NORTH);

// Закрепляем компоненты ввода исходных данных на панели управления

tool_panel.add(a_label, new XYConstraints(2, 2, -1, -1));

tool_panel.add(a_text, new XYConstraints(16, 0, -1, -1));

tool_panel.add(b_label, new XYConstraints(54, 2, -1, -1));

tool_panel.add(c_text, new XYConstraints(123, 0, -1, -1));

tool_panel.add(b_text, new XYConstraints(69, 0, -1, -1));

tool_panel.add(c_label, new XYConstraints(107, 2, -1, -1));

tool_panel.add(xn_label, new XYConstraints(161, 2, -1, -1));

tool_panel.add(xn_text, new XYConstraints(195, 0, -1, -1));

tool_panel.add(xk_label, new XYConstraints(233, 2, -1, -1));

tool_panel.add(xk_text, new XYConstraints(267, 0, -1, -1));

tool_panel.add(dx_label, new XYConstraints(305, 2, -1, -1));

tool_panel.add(dx_text, new XYConstraints(328, 0, -1, -1));

// Закрепляем компонент управления на парели управления

tool_panel.add(update_btn, new XYConstraints(368, 0, -1, -1));

// Устанавливаем параметры компонента отображения информации

graph.setBorder(BorderFactory.createEtchedBorder());

// Закрепляем компонент отображения информации на форме

contentPane.add(graph, BorderLayout.CENTER);

}

// Создаем обработчик системных событий, в нашем случае для обработки

// события закрытия окна

protected void processWindowEvent(WindowEvent e) {

super.processWindowEvent(e);

if (e.getID() == WindowEvent.WINDOW_CLOSING) {

System.exit(0);

}

}

// Создаем функцию получения исходных данных в требуемом формате

private double get_float_field(JTextField fld)

{

return Double.valueOf(fld.getText()).doubleValue();

}

// Описываем реакцию на нажатие кнопки (компонента управления)

void update_btn_actionPerformed(ActionEvent e) {

// Получаем исходные данных

double a=get_float_field(a_text);

double b=get_float_field(b_text);

double c=get_float_field(c_text);

double xn=get_float_field(xn_text);

double xk=get_float_field(xk_text);

double dx=get_float_field(dx_text);

// вычисляем значения функции

if(dx==0)

{

graph.setDataGraph(null,null);

JOptionPane.showMessageDialog(this,"Интервал не может равняться нулю!",

this.getTitle(),JOptionPane.ERROR_MESSAGE);

return;

}

if((xn>xk && dx>0) || (xn<xk && dx<0))

{

graph.setDataGraph(null,null);

JOptionPane.showMessageDialog(this,"Интервал или приращение заданы неверно!"+

" Бесконечный цикл!",

this.getTitle(),JOptionPane.ERROR_MESSAGE);

return;

}

int count=(int)Math.abs((xk-xn)/dx);

val_x=new double[count];

val_y=new double[count];

if(val_x==null || val_y==null)

{

graph.setDataGraph(null,null,0,0);

JOptionPane.showMessageDialog(this,"Ошибка выделения памяти!",

this.getTitle(),JOptionPane.ERROR_MESSAGE);

return;

}

double x=xn;

if(xn>xk)

{

double tmp=xn;

xk=xn;

xn=tmp;

dx*=-1;

}

int i=0;

boolean null_flag;

while(x<=xk && i<(val_x.length-1))

{

null_flag=false;

val_x[i]=x;

if(b<15 && x!=0)val_y[i]=a-b*x;

else

{

if(b>15 && x==0)

{

if((c-b*x)==0)

{

null_flag=true;

}

else val_y[i]=a*(b+x)/(c-b*x);

}

else

{

if(c==0)

{

null_flag=true;

}

else val_y[i]=(c+x)/(-1*c);

}

}

if(null_flag)

{

JOptionPane.showMessageDialog(this,

"Функция имеет точку разрыва. Система остановлена!",

this.getTitle(),JOptionPane.ERROR_MESSAGE);

return;

}

x+=dx;

i++;

}

// передаем параметры компоненту отображения информации.

graph.setDataGraph(val_x,val_y);

}

}

 

Структурная схема работы данной формы имеет следующий вид:

Рис.3.

 

На данной схеме видно, что вся работа приложения представляет собой цикл, состоящий из четырех состояний:

ü Ожидание команды (ожидание действий пользователя, определенных в программе в нашем случае нажатия кнопки);

ü Обработка получение исходных данных;

ü Обработка исходных данных;

ü Вывод результатов.

 








Дата добавления: 2016-01-03; просмотров: 718;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.181 сек.