355 500 произведений, 25 200 авторов.

Электронная библиотека книг » Сергей Талипов » Визуальное программирование на Java Swing в NetBeans » Текст книги (страница 2)
Визуальное программирование на Java Swing в NetBeans
  • Текст добавлен: 4 июня 2021, 18:05

Текст книги "Визуальное программирование на Java Swing в NetBeans"


Автор книги: Сергей Талипов



сообщить о нарушении

Текущая страница: 2 (всего у книги 3 страниц)

1.6 Многомерные статические массивы

Многомерные статические массивы служат для хранения двухмерных таблиц с данными. Рассмотрим пример работы с двумерным статическим массивом:

package tsn01.matrix;

public class TSN01_Matrix {

public static void main(String[] args) {

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

// Создание исходных данных (элементов массива) и вывод их на экран

final int r = 4; // Количество строк

final int c = 5; // Количество столбцов

int m[][] = new int[r][c]; // Двумерный массив

int k; System.out.println("Matrix:");

for (int i = 0; i < r; i++) { // Цикл по строкам

for (int j = 0; j < c; j++) { // Цикл по колонкам

k = (int) Math.round(Math.random() * 100); // Получение случайного числа

m[i][j] = k; // Присвоение элементу массива числа

System.out.print(String.format("%5d", m[i][j])); // Вывод на экран элемента массива

} System.out.println("");

}

// Поиск минимума и максимума в массиве

int min = m[0][0], max = m[0][0], maxi = 0, maxj = 0, mini = 0, minj = 0; // Задаем начальные значения мин и макс

for (int i = 0; i < r; i++) { // Цикл по строкам

for (int j = 0; j < c; j++) { // Цикл по колонкам

k = m[i][j]; // Получаем элемент массива

if (k > max) { max = k; maxi = i; maxj = j; } // Поиск максимума

if (k < min) { min = k; mini = i; minj = j; } // Поиск минимума

}

}

// Меняем максимальный и минимальный элементы в масиве местами

k = m[maxi][maxj]; m[maxi][maxj] = m[mini][minj]; m[mini][minj] = k;

// Вывод измененного массива на экран

System.out.println("New matrix:");

for (int i = 0; i < r; i++) { // Цикл по строкам

for (int j = 0; j < c; j++) { // Цикл по колонкам

System.out.print(String.format("%5d", m[i][j])); // Вывод на экран элемента массива

} System.out.println("");

}

}

}

Результат работы программы:

Matrix:

42 83 94 96 1

2 64 27 32 10

20 86 49 14 36

12 35 14 65 97

New matrix:

42 83 94 96 97

2 64 27 32 10

20 86 49 14 36

12 35 14 65 1


1.7 Динамические массивы-списки

Динамические массивы реализованы на уровне параметризованных классов: Vector и ArrayList. Однако в качестве элементов простые типы выступать не могут, допускаются только объектные типы.

Для управления элементами эти классы используют методы интерфейсов Collection и List:

– add(E o) – добавление элемента в конец;

– add(int index, E element) – вставка элемента в указанную позицию;

– remove(int index) – удаление элемента в указанной позиции;

– remove(Object o) – удаление первого вхождения объекта в списке;

– clear() – удаление всех элементов;

– isEmpty() – определяет, содержит ли список элементы;

– size() – число элементов;

– set(int index, E element) – заменить элемент в указанной позиции новым;

– get(int index) – получить элемент по указанному индексу;

– contains(Object o) – определение, содержится ли указанный объект в списке элементов;

– lastIndexOf(Object o) – поиск последнего вхождения элемента, возвращается индекс элемента или -1;

– indexOf(Object o) – поиск первого вхождения элемента, возвращается индекс элемента или -1;

– toArray() – возвращает копию в виде статического массива;

– toArray(T[] a) – сохраняет элементы в указанный массив.

Пример работы с динамическим массивом целых чисел:

package tsn01.arraylist;

import java.util.ArrayList;

public class TSN01_ArrayList {

public static void main(String[] args) {

// Работа с динамическим массивом чисел

ArrayList i = new ArrayList<>(); // Создание динамического массива целых чисел

i.add(3); // Добавление значения

i.add(new Integer(3)); // Добавление значения

if (i.get(0)==i.get(1)) { System.out.println("Эта строчка не напечатается…"); }

if (i.get(0).equals(i.get(1))) { System.out.println("3=3"); }

i.add(12+5); // Добавление значения

System.out.println("Размер массива: " + i.size());

System.out.println("Элементы массива: " + i.get(0).intValue() + ", " + i.get(1)+ ", " + i.get(2));

}

}

Результат работы программы:

3=3

Размер массива: 3

Элементы массива: 3, 3, 17

Пример работы с динамическим массивом строк:

package tsn01.arraylist;

import java.util.ArrayList;

public class TSN01_ArrayList {

public static void main(String[] args) {

// Работа с динамическим массивом строк

ArrayList pozdr = new ArrayList<>(); // Массив пожеланий

ArrayList fam = new ArrayList<>(); // Массив фамилий

// Добавление поздравления в массив

pozdr.add("Удачи"); pozdr.add("Здоровья"); pozdr.add("Денег");

// добавление фамилии в массив

fam.add("Петров"); fam.add("Сидоров"); fam.add("Иванов");

// Проверка количества поздравлений

if (fam.size() > pozdr.size()) { return; }

for (int i = 0; i < fam.size(); i++) {

// Генерируем случайное число в диапазоне от 0 до длины массива поздравлений

int p = (int) Math.floor(Math.random() * pozdr.size());

// Генерация поздравления

System.out.println("Уважаемый " + fam.get(i)

+ "! Поздравляем Вас с этим прекрасным праздником, и желаем Вам "

+ pozdr.get(p).toString().toLowerCase() + "!");

pozdr.remove(p); // Удаляем элемент с индексом р из массива поздравлений

} }

}


1.8 Работа со строками

В Java имеется три типа строк: String, StringBuilder и StringBuffer. Статические строки «String» – обычные строки в Java, в которых нельзя изменить символы и их количество после создания строки.

Динамические строки «StringBuilder» – изменяемые строки для использования в однопоточных программах. В однопоточном использовании StringBuilder практически всегда в 1.2-1.5 раза быстрее, чем StringBuffer.

Динамические строки StringBuffer – изменяемые строки для использования в многопоточных программах. Самый медленный тип, но потокобезопасный.

Переменные типа динамических строк могут менять свои значения и длину во время выполнения программы.

Статические строки. Обычные строки в Java описываются классом String и являются статическими, т.е. в существующей строке нельзя изменить символы и их количество.

Кроме стандартного создания оператором new, строки могут быть созданы напрямую из строковой литералы. При этом в целях оптимизации, объекты созданные таким образом дополнительно сохраняются в отдельной области – строковый пул.

String s1 = "d" // строка будет сохранена в пуле

// строка не будет сохранена в пуле и будет уничтожена сборщиком мусора

String s2 = new String("a");

Один из плюсов разделения строк на статические и динамические – это повышение безопасности там, где строки используются в качестве аргументов (например, открытие баз данных, интернет соединений, механизм загрузки классов).

Операция сцепления. Для строк доступна операция +, позволяющая соединить несколько строк в одну. Если один из операндов не строка, то он автоматически преобразуется в строку. Для объектов в этих целях используется метод toString.

При каждой операции внутренне используется объект динамической строки StringBuilder или StringBuffer. Поэтому для собирания строки из нескольких все равно оптимальней использовать сразу один StringBuilder/StringBuffer.

Выделение подстроки. Есть замечание относительно метода substring – возвращаемая строка использует тот же байтовый массив, что и исходная. Например, вы загрузили строку А из файла в 1мб. Что-то там нашли и выделили в отдельную строку Б длиной в 3 символа. Строка Б в реальности тоже занимает те же 1мб.

String s ="very .... long string from file";

String sub1 = s.substring(2,4); // совместно использует ту же память что и s

String sub2 = new String(s.substring(2,4)); // этот объект использует отдельный массив на 4 символа



Основные методы. Рассмотрим основные методы String:

– equals(Object anObject) – проверяет, идентична ли строка указанному объекту;

– compareTo(String anotherString) – лексиграфическое сравнение строк;

– compareToIgnoreCase(String str) – лексиграфическое сравнение строк без учета регистра символов;

– concat(String str) – возвращает соединение двух строк;

– contains(CharSequence s) – проверяет, входит ли указанная последовательность символов в строку;

– isEmpty() – возвращает true, если длина строки равна 0;

– indexOf(String str) – поиск первого вхождения указанной подстроки;

– replace(CharSequence target, CharSequence replacement) – замена одной подстроки другой;

– substring(int beginIndex, int endIndex) – возвратить подстроку как строку;

– toLowerCase() – преобразовать строку в нижний регистр;

– toUpperCase() – преобразовать строку в верхний регистр;

– trim() – отсечь на концах строки пустые символы;

– length() – определение длины строки;

– valueOf(a) – статические методы преобразования различных типов в строку;

– charAt(int index) – возвращает символ по указанному индексу;

– regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) – тест на идентичность участков строк, можно указать учет регистра символов;

– regionMatches(int toffset, String other, int ooffset, int len) – тест на идентичность участков строк;

– endsWith(String suffix) – проверяет, завершается ли строка указанным суффиксом;

– startsWith(String prefix) – проверяет, начинается ли строка с указанного префикса;

– startsWith(String prefix, int toffset) – проверяет, начинается ли строка в указанной позиции с указанного префикса;

– getBytes() – возвращает байтовое представление строки;

– getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) – возвращает символьное представление участка строки;

– hashCode() – хеш код строки;

– indexOf(int ch) – поиск первого вхождения символа в строке;

– indexOf(int ch, int fromIndex) – поиск первого вхождения символа в строке с указанной позиции;

– indexOf(String str, int fromIndex) – поиск первого вхождения указанной подстроки с указанной позиции;

– lastIndexOf(int ch) – поиск последнего вхождения символа;

– lastIndexOf(int ch, int fromIndex) – поиск последнего вхождения символа с указанной позиции;

– lastIndexOf(String str) – поиск последнего вхождения строки;

– lastIndexOf(String str, int fromIndex) – поиск последнего вхождения строки с указанной позиции;

– replace(char oldChar, char newChar) – замена в строке одного символа на другой;

– toUpperCase(Locale locale) – преобразовать строку в верхний регистр, используя указанную локализацию;

– toLowerCase(Locale locale) – преобразовать строку в нижний регистр, используя указанную локализацию;

Методы поиска возвращают индекс вхождения или -1, если искомое не найдено. Методы преобразования (как replace) не изменяют саму строку, а возвращают соответствующий новый объект строки.

Особенности String. Неправильное использование типа String приводит к засорению оперативной памяти и как следствие к медленной работе программы. Рассмотрим пример:

public static void main(String[] args) {

String s = "a";

for (int i = 0; i < 100; i++) {

s += 'a';

}

System.out.println(s); // Распечатается строка из 100 символов «a»

}

Этот код создаст 100 разных строк, которые будут храниться в памяти, пока сборщик мусора Java не удалит их после завершения программы. В результате работы программы переменная «s» будет содержать строку из 100 символов «a», но 99 ранее созданных строк остались «мусором» в памяти без возможности обращения к ним.

Поэтому для изменения строки следует использовать класс обертку StringBuilder. Предыдущий пример нужно переписать следующим образом:

public static void main(String[] args) {

StringBuilder s = new StringBuilder("a");

for (int i = 0; i < 100; i++) {

s.append('a');

}

System.out.println(s); // Распечатается строка из 100 символов «a»

}

Динамические строки. Динамические строки описываются классами StringBuilder и StringBuffer. StringBuffer более медленный, но потокобезопасный. Переменные типа динамических строк могут менять свои значения и длину во время выполнения программы.

Основные методы динамических строк:

– append(A) – преобразовать A в строку и добавить в конец;

– insert(int offset, A) – преобразовать A в строку и вставить ее в указанную позицию;

– delete(int start, int end) – удалить символы с указанной начальной позиции по указанную конечную позицию;

– reverse() – расположить символы в обратном порядке;

– setCharAt(int index, char ch) – заменить символ в указанной позиции;

– setLength(int newLength) – установить новый размер строки;

– substring(int start) – вернуть подстроку с указанной позиции и до конца как строку;

– substring(int start, int end) – вернуть подстроку как строку;

– deleteCharAt(int index) – удалить символ в указанной позиции;

– getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) – сохранить последовательность символов в массив;

– indexOf(String str) – поиск первого вхождения подстроки;

– indexOf(String str, int fromIndex) – поиск первого вхождения подстроки с указанной позиции;

– lastIndexOf(String str) – поиск последнего вхождения подстроки;

– lastIndexOf(String str, int fromIndex) – поиск последнего вхождения подстроки с указанной позиции;

– replace(int start, int end, String str) – замена участка строки указанной строкой.

Пример преобразования строк. В этом примере массив символов и целое число преобразуются в объекты типа String с использованием методов этого класса:

package tsn01.string;

public class TSN01_String {

public static void main(String[] args) {

char s[] = {'J', 'a', 'v', 'a'}; // Массив символов

String str = new String(s); // str="Java"

if (!str.isEmpty()) {

int i = str.length(); // i=4

str = str.toUpperCase(); // str="JAVA"

String num = String.valueOf(6); // num="6"

num = str.concat("-" + num); // num="JAVA-6"

char ch = str.charAt(2); // ch='V'

i = str.lastIndexOf('A'); // i=3 (-1 если нет)

num = num.replace("6", "SE"); // num="JAVA-SE"

str.substring(0, 4).toLowerCase(); // java

str = num + "-6";// str="JAVA-SE-6"

String[] arr = str.split("-");

for (String ss : arr) { // В результате будет выведен массив строк (в 3 строчки): JAVA SE 6

System.out.println(ss);

}

} else { System.out.println("String is empty!"); }

}

}

Пример сравнение строк. В этом примере рассмотрены особенности хранения и идентификации объектов на примере вызова метода equals(), сравнивающего строку String с указанным объектом и метода hashCode(), который вычисляет хэш-код объекта (hashCode – это цифра, которая формируется для объекта по какому то правилу, например для объекта класса String по такой формуле: s[0]*31^(n-1) s[1]*31^(n-2) … s[n-1]):

package tsn01.string;

public class TSN01_String {

public static void main(String[] args) {

String s1 = "Java";

String s2 = "Java";

String s3 = new String("Java");

System.out.println(s1 + "==" + s2 + " : " + (s1 == s2)); // true

System.out.println(s1 + "==" + s3 + " : " + (s1 == s3)); // false

System.out.println(s1 + " equals " + s2 + " : " + s1.equals(s2)); // true

System.out.println(s1 + " equals " + s3 + " : " + s1.equals(s3)); // true

System.out.println(s1.hashCode());

System.out.println(s2.hashCode());

System.out.println(s3.hashCode());

}

}

В результате на экран будет выведено:

Java==Java : true

Java==Java : false

Java equals Java : true

Java equals Java : true

2301506

2301506

2301506

Пример сортировки массива строк методом перебора:

package tsn01.string;

public class TSN01_String {

public static void main(String[] args) {

String a[] = {" Alena", "Alice ", " alina", " albina", " Anastasya",

" ALLA ", "AnnA "}; // Массив строк

for (int j = 0; j < a.length; j++) { // Цикл по массиву строк

// Удаляем пробелы с концов строк и приводим к верхнему регистру

a[j] = a[j].trim().toLowerCase();

}

// Сортировка строк методом пузырька

for (int j = 0; j < a.length – 1; j++) { // Цикл по массиву строк

for (int i = j + 1; i < a.length; i++) { // Цикл по массиву строк

if (a[i].compareTo(a[j]) < 0) { // Сравнение строк

String temp = a[j]; a[j] = a[i]; a[i] = temp; // Обмен значений в массиве строк

}

}

}

int i = -1;

while (++i < a.length) { System.out.print(a[i] + " "); } // Вывод массива строк на экран

}

}

В результате на экран будет выведено:

albina alena alice alina alla anastasya anna

Вызов метода trim() обеспечивает удаление всех начальных и конечных символов пробелов. Метод compareTo() выполняет лексикографическое сравнение строк между собой по правилам Unicode.

Пример работы с динамическими строками. Рассмотрим пример преобразования переменной типа «StringBuilder» к «String» через метод toString:

package tsn01.string;

public class TSN01_String {

public static void main(String[] args) {

StringBuilder s = new StringBuilder("abcd");

s.append('e');//abcde

s.delete(1, 2);//acde

s.insert(1, 'b');//abcde

s.deleteCharAt(2);//abde

String ans = s.toString();

System.out.println(ans); // На экран выведется "abde"

}

}



2 Простейшие программы


2.1 Консольные программы

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

Для создания консольной программы необходимо выбрать в меню опцию «Файл» – «Создать проект»:

Выбрать категорию «Java» – «Приложение Java»:

Указать имя проекта и необходимость создать главный класс. В главном классе и будет располагаться консольная программа.

Имя проекта необходимо задать так: «FIOnn_DEMO», где FIO – инициалы автора программы, nn – номер варианта, например, «TSN01_DEMO».

Название главного класса необходимо задать так: «fionn.demo.App1», где fio – инициалы автора программы, nn – номер варианта, например «tsn01.demo.App1».

Рассмотрим пример простейшей консольной программы.

package tsn01.demo;

import java.util.Scanner;

public class App1 {

public static void main(String[] args) {

// Простейшая консольная программа

Scanner sc = new Scanner(System.in); // Подключение к консоли

System.out.print("Как вас зовут: "); // Вывод вопроса

String n = sc.next(); // Ввод с консоли строкового значения

System.out.print("Сколько вам лет: "); // Вывод вопроса

int a = sc.nextInt(); // Ввод с консоли целого значения

System.out.print("Ваш вес: "); // Вывод вопроса

float w = sc.nextFloat();// Ввод с консоли вещественного значения

System.out.println("Привет, " + n + "! Тебе " + a + " года, вес "

+ w + " кг.");

sc.close(); // Закрытие консоли

}

}

Запуск программы через командную строку Windows с поддержкой русского языка:

java -Dfile.encoding=Cp866 -jar TSN01_DEMO.jar

Рассмотрим пример консольной программы для решения квадратного уравнения.

package tsn01.demo;

import java.util.Scanner;

public class App1 {

public static void main(String[] args) {

// Вычисление квадратного уравнения

double a, b, c; // Входные переменные

double x1, x2; // Искомые значения

double d; // Дискриминант

try {

Scanner sc = new Scanner(System.in); //Создаем объект для ввода данных с консоли

System.out.println("Решение квадратного уравнения");

System.out.print("Введите a=");

a = sc.nextDouble(); // Ввод значения "a" с консоли

System.out.print("Введите b=");

b = sc.nextDouble(); // Ввод значения "b" с консоли

System.out.print("Введите c=");

c = sc.nextDouble(); // Ввод значения "c" с консоли

d = (b * b) – 4 * a * c; // Расчет дискриминанта

x1 = (-b + Math.sqrt(d)) / (2 * a); // Расчет "x1"

x2 = (-b – Math.sqrt(d)) / (2 * a); // Расчет "x2"

if (!(Double.isNaN(x1)) && (!Double.isInfinite(x1)) // Проверка существования значений

&& (!(Double.isNaN(x2)) && (!Double.isInfinite(x2)))) {

System.out.format("x1=%.3f%nx2= %.3f%n", x1, x2); // Вывод ответа

} else {

System.out.println("Нет решения!"); // Нет решения

}

sc.close(); // Закрываем ввод с консоли

} catch (Exception e) { // Ввели вместо цифр буквы

System.out.println("Неверные входные данные!");

}

}

}


2.2 Простейшая программа с графическим интерфейсом в среде NetBeans

Заходим в меню «Файл» – «Создать проект»:

Выбираем категорию «Java», тип проекта «Приложение Java»:

Указываем имя проекта. Имя проекта необходимо задать по шаблону «TSN01_LAB1», где «TSN» – инициалы автора программы большими буквами, «01» – номер варианта (2 цифры), далее идет знак «_», слово «LAB» большими буквами и номер лабораторной работы. При необходимости указываем новый каталог для расположения проекта. Нажимаем кнопку «Готово».

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

Устанавливаем курсор мыши на «пакет по-умолчанию», после этого нажимаем на этом пункте правую кнопку мыши. В появившемся контекстном меню выбираем «Новый» – «Форма JFrame»:

Указываем имя класса (окна). Рекомендуется имя формы задавать по шаблону «Form1», где «Form» – означает, что это форма, первая буква большая, а «1» – номер формы в программе.

Далее, необходимо указать имя пакета. Имя пакета необходимо задать по шаблону «tsn01.lab1», где «tsn» – инициалы автора программы маленькими буквами, «01» – номер варианта (2 цифры), далее идет знак «.» (точка), слово «lab» маленькими буквами и номер лабораторной работы.

Нажимаем кнопку «Готово».

Выделяем в окне «Проекты» полученную форму «Form1». Простейшая программа из пустого окна готова.

Запускаем полученную программу: «Выполнить» – «Запустить проект» (F6).

Появиться окно для указания главного класса в программе. Необходимо выбрать класс и именем формы и нажать «ОК». После этого запустится программа.

Рассмотрим пример кода для кнопки «Расчет» и интерфейс простейшей программы деления двух цифр:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

// Вычисление выражения

String a, b, c; // Строковые переменные

double z; // Вещественные переменные

double x, y; // Вещественные переменные

// int x, y; // Целочисленные переменные

a = jTextField1.getText(); // Получение значения из окошка 1

b = jTextField2.getText(); // Получение значения из окошка 2

try { // Начало защищенного блока

x = Double.parseDouble(a); // Преобразование текстового значения в вещественное

y = Double.parseDouble(b); // Преобразование текстового значения в вещественное

// x = Integer.parseInt(a); // Преобразование текстового значения в целочисленное

// y = Integer.parseInt(b); // Преобразование текстового значения в целочисленное

z = x / y; // Вычисление выражения

// z = (double)( x) / (double) (y); // Вычисление выражения

// Проверка на: 0/0, z/0

if ((Double.isNaN(z) == true) || Double.isInfinite(z) == true) {

throw new Exception("error"); // Если нет решение то генерирование ошибки

}

// Описание формата вещественного числа

DecimalFormat df = new DecimalFormat("#0.00");

c = String.valueOf(df.format(z)); // Преобразование числа в строку

jTextField3.setText(c); // Вывод ответа в окошко

// jTextField3.setText(String.valueOf(new DecimalFormat("#0.00").format(z))); // Вывод ответа в окошко

} catch (Exception ee) { // Обработчики ошибок защищенного блока

Toolkit.getDefaultToolkit ().beep (); // Звуковой сигнал

jTextField3.setText("Неверные данные!"); // Обработка ошибки ввода или вычисления

} // Конец защищенного блока

}

Рассмотрим пример кода кнопки «Решить» и «Выход» для расчета математического значения по условию:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

// Решение примера

float x, b, d, y; // Вещественные переменные

try {

x = Float.parseFloat(jTextField1.getText()); // Получение данных

b = Float.parseFloat(jTextField2.getText()); // Получение данных

d = Float.parseFloat(jTextField3.getText()); // Получение данных

} catch (Exception ex) {

Toolkit.getDefaultToolkit().beep(); // Издаем звук

// Выводим окошко с сообщением об ошибке

JOptionPane.showMessageDialog(rootPane, "Ошибка введенных данных!", "Ошибка ввода", JOptionPane.ERROR_MESSAGE);

jTextField1.requestFocus(); // Устанавливаем фокус на компонент

jLabel5.setText("В введенных значениях допущены ошибки.");

jTextField1.setText(""); // Очистка данных

jTextField2.setText(""); // Очистка данных

jTextField3.setText(""); // Очистка данных

return; // Выход из метода (процедуры)

}

if (x >= 8) { // Вычисление выражения

y = (x – 2) / (x * x);

} else {

y = b * b * d + 4 * x * x * x;

}

jLabel5.setText("ОТВЕТ: " + String.format("%.2f", y)); // Выдача ответа с двумя знаками после запятой

}

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {

// Выход из программы

System.exit(0);

}

private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {


    Ваша оценка произведения:

Популярные книги за неделю