|
Вторая часть обзора изменений в Java Standard Edition 6
(Java SE 6) связанных с разработкой десктопных приложений.
В этой части рассказывается о:
Табличная сортировка и фильтрация.
Выборка из статьи "Sorting and Filtering Tables" автор John O'Conner.
В платформу Java SE 6 добавлены некоторые новые возможности, позволяющие существенное упростить реализацию сортировки и фильтрации данных в классе JTable пакета javax.swing.
Большинство современных приложений, использующих таблицы позволяют пользователю упорядочивать содержимое колонок посредством нажатия клавиши мыши на заголовке таблицы. Данную функциональность можно реализовать средствами платформы Java более ранних версий, чем версия 6. Однако, это требует однотипных изменений в реализации каждой таблицы, которой требуется данное свойство. Начиная с версии JavaSE 6, требуется гораздо меньше усилий для реализации аналогичной функциональности. Фильтрация – это другая возможность, которая может быть добавлена к пользовательскому интерфейсу. Фильтрация позволяет пользователю отображать только те ряды таблицы, которые удовлетворяют заданным пользователем критериям. Начиная с версии Java SE 6, подключить фильтрацию к таблице JTable стало гораздо легче.
Сортировка строк таблицы
Основным элементом, необходимым для реализации упорядочивания и фильтрации в JavaSE 6 является абстрактный класс RowSorter. Данный класс осуществляет две основные функции: связывание содержимого таблицы с моделью данных и наоборот – связывание модели данных с содержимым таблицы. Это позволяет разработчику осуществлять упорядочивание и фильтрацию. Данный класс достаточно универсален и может использоваться в связке с классами TableModel и ListModel. Однако, в состав библиотек Java SE 6 включен только класс TableRowSorter, предназначенный для работы с классом JTable.
В простейшем случае можно передать экземпляр класса TableModel в конструктор класса TableRowSorter и затем полученный объект RowSorter в метод JTable.setRowSorter(). Следующий пример демонстрирует данный способ:
import javax.swing.*; import java.awt.*;
import javax.swing.table.*;
public class SortTable {
public static void main(String[] args) {
Runnable runner = new Runnable() {
public void run() {
JFrame frame = new JFrame("Sorting JTable");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Object[][] rows = {{"AMZN", "Amazon", 41.28}, {"EBAY", "eBay", 41.57},
{"GOOG", "Google", 388.33}, {"MSFT", "Microsoft", 26.56},
{"NOK", "Nokia Corp", 17.13}, {"ORCL", "Oracle Corp.",12.52},
{"SUNW", "Sun Microsystems", 3.86}, {"TWX", "Time Warner", 17.66},
{"VOD", "Vodafone Group", 26.02}, {"YHOO", "Yahoo!", 37.69}};
String[] columns = {"Symbol", "Name", "Price"};
TableModel model = new DefaultTableModel(rows, columns) {
public Class getColumnClass(int column) {
Class returnValue;
if ((column >= 0) && (column < getColumnCount())) {
returnValue = getValueAt(0, column).getClass();
} else {
returnValue = Object.class;
}
return returnValue;
}
};
JTable table = new JTable(model);
RowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
JScrollPane pane = new JScrollPane(table);
frame.add(pane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
};
EventQueue.invokeLater(runner);
}
}

Таблица без сортировки.
Если запустить этот пример и затем щелкнуть мышью на заголовке какой-то колонки, то содержимое поменяет свой порядок, как показано на следующем рисунке.

После сортировки по стоимости.
Почему бы просто не использовать DefaulTableModel вместо создания класса-наследника? Ответ состоит в том, что класс TableRowSorter описывает набор правил, по которым упорядочиваются колонки. По умолчанию колонки таблицы рассматриваются как объекты класса Object. Таким образом, упорядочивание происходит на основе значения, возвращаемого методом toString(). Если переопределить метод getColumnClass() класса DefaultTableModel, то класс RowSorter будет упорядочивать данные (они должны реализовывать интерфейс Comparable) в соответствии с новыми правилами, описанными новым классом DefaultTableModel. Также можно установить свой Comparator для колонок:
setComparator(int column, Comparator comparator)
Следующие части программы устанавливают способ упорядочивания
JTable table = new JTable(model);
RowSorter<TableModel> sorter =
new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
Первая строчка ставит в соответствие друг другу модель и таблицу. Вторая строка создает на основе модели данных объект класса RowSorter. Последняя строка связывает RowSorter с таблицей JTable. Это позволяет пользователю упорядочивать данные одной колонки нажатием одной кнопки. Повторное нажатие на той же колонке делает обратную сортировку данных.
Если необходимо добавить некоторое действие на изменение типа сортировки, то можно подключить RowSorterListener к объекту RowSorter. Данный интерфейс имеет только один метод:
void sorterChanged(RowSorterEvent e)
Указанный метод может быть использован, например, для обновления текста в строке состояния или для выполнения каких-либо дополнительных действий. Объект класса RowSorterEvent, получаемый при изменении порядка данных, позволяет определить, сколько строк было в таблице перед сортировкой.
Фильтрация строк таблицы
Существует возможность связать объекты RowFilter и TableRowSorter друг с другом и использовать их для фильтрации содержимого таблицы. Например, можно использовать RowFilter для того, чтобы таблица отображала только те строки, в которых наименование компании начинается на букву “А” или у которых стоимость акции больше 50 долларов.
Абстрактный класс RowFilter имеет только один метод, используемый для фильтрации:
boolean include(RowFilter.Entry<? extends M,? extends I> entry)
Для каждого элемента в модели данных, ассоциированной с данным классом RowSorter, этот метод определяет, нужно ли отображать данный элемент или нет. В большинстве случаев создавать новую реализацию класса RowSorter не придется, поскольку класс предоставляет шесть статических методов для создания фильтров.
public static <M,I> RowFilter<M,I>
public static RowFilter
andFilter(Iterable> filters)
public static RowFilter dateFilter(RowFilter.ComparisonType type, Date date, int... indices)
public static RowFilter notFilter(RowFilterfilter)
public static RowFilter numberFilter(RowFilter.ComparisonType type, Number number, int... indices)
public static RowFilter orFilter(Iterable> filters)
public static
RowFilter regexFilter(String regex, int... indices)
Фабричные методы dateFilter, numberFilter и regexFilter, имеющие своими параметрами индексы, будут затрагивать только те колонки, которые указаны в параметрах. Если индексов не задано, то программа будет использовать все колонки.
Класс dateFilter позволяет проверять соотвествие дат. Класс numberFilter проверяет соотвествие чисел. Класс notFilter используется для отмены другого фильтра. То есть он включает те элементы, которые были отфильтрованы другим фильтром, который передается в качестве параметра. Этот фильтр можно использовать для поиска тех элементов, над которыми не было выполнено какое-либо действие. Классы andFilter and orFilter предназначены для логических комбинаций фильтров. Класс regexFilter использует регулярное выражение для осуществления фильтрации. Следующая программа использует метод regexFilter для фильтрации содержимого таблицы.
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import java.util.regex.*;
public class FilterTable {
public static void main(String[] args) {
Runnable runner = new Runnable() {
public void run() {
JFrame frame = new JFrame("Sorting JTable");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Object[][] rows = {{"AMZN", "Amazon", 41.28}, {"EBAY", "eBay", 41.57},
{"GOOG", "Google", 388.33}, {"MSFT", "Microsoft", 26.56}, {"NOK", "Nokia Corp", 17.13},
{"ORCL", "Oracle Corp.", 12.52}, {"SUNW", "Sun Microsystems", 3.86},
{"TWX", "Time Warner", 17.66}, {"VOD", "Vodafone Group", 26.02},
{"YHOO", "Yahoo!", 37.69}};
Object[] columns = {"Symbol", "Name", "Price"};
TableModel model = new DefaultTableModel(rows, columns) {
public Class getColumnClass(int column) {
Class returnValue;
if ((column >= 0) && (column < getColumnCount())) {
returnValue = getValueAt(0, column).getClass();
} else {
returnValue = Object.class;
}
return returnValue;
}
};
JTable table = new JTable(model);
final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
JScrollPane pane = new JScrollPane(table);
frame.add(pane, BorderLayout.CENTER);
JPanel panel = new JPanel(new BorderLayout());
JLabel label = new JLabel("Filter");
panel.add(label, BorderLayout.WEST);
final JTextField filterText = new JTextField("SUN");
panel.add(filterText, BorderLayout.CENTER);
frame.add(panel, BorderLayout.NORTH);
JButton button = new JButton("Filter");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String text = filterText.getText();
if (text.length() == 0) {
sorter.setRowFilter(null);
} else {
try {
sorter.setRowFilter(RowFilter.regexFilter(text));
} catch (PatternSyntaxException pse) {
System.err.println("Bad regex pattern");
}
}
}
});
frame.add(button, BorderLayout.SOUTH);
frame.setSize(300, 250);
frame.setVisible(true);
}
};
EventQueue.invokeLater(runner);
}
}
На экране устанавливается фильтр на все элементы, которые содержат строку “SUN” внутри себя. В регулярных выражениях можно использовать символы ^ и $ для проверки находжения символов в начале или в конце строки соответственно.

До применения фильтра
Фильтр будет автоматически использовать метод Matcher.find() для включения данных как только пользователь нажмет на кнопку внизу окна.

Фильтрованные данные
Изменение значения строки в текстовом поле влияет на отображаемые данные. Если необходимо отменить фильтрацию, то можно очистить текстовое поле.
Улучшения в библиотеке Image I/O
Из блога '400 Horsepower: Image I/O Improvements in JDK 6' автор Chris Campbell
В JDK версии 5.0 наша команда улучшила производительность классов, предназначенных для работы с вводом-выводом картинок. Например, мы полностью избавились от финализации объектов в классе com.sun.imageio.plugins.jpeg.JPEGImageReader, что дает огромный выигрыш в масштабируемости и производительности чтения изображений в формате JPEG. Кроме того, несколько недель были потрачены на то, чтобы улучшить производительность в подсистеме Image I/O в целом.
Наша команда исправила следующие дефекты, затрагивающие Image I/O:
* 6347575: FileImageInputStream.readInt() and similar methods are inefficient.
* 6348744: PNGImageReader should skip metadata if ignore Metadata=true.
* 6354056: JPEGImageReader could be optimized.
* 6299405: ImageInputStreamImpl still uses a finalize(), which causes java.lang.OutOfMemoryError.
* 6354112: Increase compiler optimization level for libjpeg to improve runtime performance
Улучшение производительности в Java SE 6
Обратите внимание, что данные тестирования на платформе JDK1.4.2 для изображения формата 20x20 – это не ошибка. Это на самом деле так. Также заметьте, что данный график представляет результаты для небольших изображений, но сравнимые улучшения также присущи и большим. Например, было замечено 53 процентное ускорение чтения изображения в формате JPEG размером 4000х4000 в версии JDK 6 по сравнению с версией JDK 5.0.
Модальность: новая модель
Из статьи "The New Modality API in Java SE 6" авторы Artem Ananiev и Dana Nourie
Диалоговое окно (диалог) представляет из себя окно, имеющее название и декорации. Диалог обычно используются для ввода данных пользователем.
В версии JDK 5.0 и более ранних у диалога обязательно должен был быть владелец, в роли которого могло выступать любое другое окно (либо диалоговое, либо декорированное окно, либо недекорированное окно). Даже если диалог был невидимым, всегда нужна была ссылка на другое владеющее им окно.
Если пользователь сворачивал окно-владельца какого-либо диалога, то диалог автоматически сворачивался. И наоборот, диалог появлялся снова, если это окно разворачивалось.
Диалог может быть либо обычным, либо модальным. Модальным называется диалог, который блокирует пользовательский ввод в другие окна приложения за исключением окон, для которых данный диалог является главным.
Модальный диалог активен до тех пор, пока он не будет закрыт, как правило, в результате нажатия на какую-либо кнопку внутри него. Обычный же диалог просто находится на экране и позволяет изменять свои свойства даже если активно другое окно. Последнее часто используется для реализации панелей инструментов. Например, в редакторе изображений.
Данной модели были присущи и некоторые другие проблемы. Возможно, самой известной из них была проблема, связанная с окнами, используемыми библиотекой JavaTool.
JavaHelp – это библиотека для отображения вспомогательной информации в программах, написанных на языке Java. Данная библиотека открывает самостоятельное окно, которое и отображает всю необходимую информацию. Однако, если в приложении открываетcя модальный диалог (например, обычный “Сохранить как”), то он блокирует все приложение, включая те окна, которые используются библиотекой JavaTool для отображения вспомогательной информации.
В версии платформы Java SE 6 эта и некоторые другие проблемы были разрешены за счет введения новой модели модальности в пакет java.awt (AWT, Abstract Window Toolkit).
Данная новая модель предоставляет разработчику управлять блокированием модальности в соответствии с выбранным типом. Кроме того, существует возможность не указывать главное окно для диалога, передав в качестве параметра конструктору значение null.
Платформа Java SE 6 поддерживает четыре вида модальности:
* Отсутствие модальности (Modeless). Обычный диалог - не блокирует другие окна, даже если он отображен на экране.
* Модальность на уровне документа (Document-modal). В данном контексте “документ” - это иерархия окон (декорированные, недекорированные окна и диалоги), которые имеют одного предка. Данный общий предок называется корнем документа (document root) и является ближайшим окном, у которого отсутствует владелец. Данный вид модальности блокирует все окна одного документа за исключением тех, которые являются дочерними по отношению в данному модальному диалогу.
* Модальность на уровне приложения (Application-modal). Данный вид модальности блокирует все окна одного приложения за исключением тех, которые являются дочерними по отношению в данному модальному диалогу. Если в браузере запущено несколько аплетов, то браузер может рассматривать их как принадлежащие к одному приложению или к разным. В данном случае поведение зависит от реализации браузера.
* Модальность на уровне среды исполнения (Toolkit-modal). Данный вид модальности блокирует все окна запущенные в рамках одной исполняемой среды за исключением тех, которые являются дочерними по отношению в данному модальному диалогу. Если в браузере запущено несколько аплетов, то все они работают в одной исполняемой среде, предоставляемой браузером. Таким образом, модальные диалоги этого типа, могут воздействовать друг на друга и на все окна, принадлежащие браузеру, которые использует среду исполнения Java (Java Runtime Environment, JRE).
Как и в предыдущих версиях JDK, по умолчанию диалог не является модальным. Но если сконструировать модальный диалог, то по умолчанию он будет использовать модель модальности на уровне приложения. Кроме того, поведение всех диалогов (модальных и немодальных) изменилось так, что теперь все они отображаются в первый раз поверх своих окон-предков.
“Сила”, с которой блокируются другие окна определяет приоритет модальности для той или иной модели. Приоритет модальности необходим в ситуациях, когда два диалога становятся видимыми и блокируют друг друга. Приоритет (в порядке увеличения) следующий: обычный диалог, модальность на уровне документа, модальность на уровне приложения, модальность на уровне среды исполнения. Такой порядок естественным образом отражает область, которую диалог блокирует. Обычный диалог ничего не блокирует. В некоторых случаях диалог, модальный на уровне документа может блокировать все приложение целиком. Наконец, все приложения работают в одной и той же среде исполнения.
Обратите внимание, что новая модель модальности не реализует модальность на уровне системы, которая бы блокировала все приложения, отображенные на экране, независимо от того, приложение ли это на языке Java или нет.
Реализация возможности создания окон без предков с сохранением обратной совместимости была крайне сложной задачей для группы AWT. В JDK версии 5.0 и более ранних была возможность передать значение null в качестве предка для классов JDialog и JWindow. Это означало, что некоторое невидимое окно становилось предком данного диалога или окна. Этот механизм был специально создан для того, чтобы создать иллюзию того, что у некоторого диалога предок отсутствует. Все было замечательно до JavaSE 6, когда стали доступны диалоги с модальностью на уровне документа.
Как было сказано выше, если окно или диалог является предком другого диалога, то говорят, что этот предок владеет своим наследником. Отметим несколько моментов, на которые стоит обращать внимание при работе с новой модальностью:
* Создание диалога с модальностью на уровне документа без указания предка. В этом случае, ввиду того, что класс Dialog является наследником класса Window, Dialog автоматически становится корнем документа. Таким образом, если диалог модален на уровне документа, его область блокирования пуста и он ведет себя точно так же как и обычный диалог.
Таким образом, система считала, что такие диалоги и окна на самом деле не имеют пустого предка. В Java SE 6 по-прежнему есть возможность передавать null в качестве предка для конструкторов классов JDialog и JWindow. Этим достигается тот же самый результат: некоторое невидимое окно становится предком этим окон с тем чтобы сохранить обратную совместимость. Однако теперь появилась возможность передавать значение null в конструкторы классов Dialog и Window, точно так же как и для конструкторов классов JDialog и JWindow.
Вот некоторые из конструкторов:
* JDialog(Dialog owner)
Создает обычный диалог без названия и с указанием диалога в качестве владельца.
* JDialog(Dialog owner, boolean modal)
Создает диалог с указанием диалога в качестве владельца и флага модальности.
* JDialog(Dialog owner, String title)
Создает диалог с указанием диалога-владельца и названия.
* JDialog(Dialog owner, String title, boolean modal)
Создает диалог с указанием диалога-владельца, названия и флага модальности.
* JDialog(Dialog owner, String title, boolean modal, GraphicsConfiguration gc)
Создает диалог с указанием диалога-владельца, названия, флага модальности и графических настроек.
* JDialog(Frame owner)
Создает обычный диалог без названия и с указанием декорированного окна в качестве владельца.
* JDialog(Window owner, String title, Dialog.ModalityType modalityType)
Создает диалог с указанием окна-владельца, названия и типа модальности.
Как было сказано выше, если окно или диалог является предком другого диалога, то говорят, что этот предок владеет своим наследником. Отметим несколько моментов, на которые стоит обращать внимание при работе с новой модальностью:
* Создание диалога с модальностью на уровне документа без указания предка. В этом случае, ввиду того, что класс Dialog является наследником класса Window, Dialog автоматически становится корнем документа. Таким образом, если диалог модален на уровне документа, его область блокирования пуста и он ведет себя точно так же как и обычный диалог.
* Создание диалога с модальностью на уровне приложения или на уровне среды исполнения с указанием владельца. Область блокирования в данном случае, в отличие от модальности на уровне документа, не зависит от владельца диалога. В этом случае, единственное, что затрагивается – это относительный друг относительно друга порядок окон (так называемый Z-order). Данный порядок нужен для отслеживания того, какое окно находится выше других (перекрывает другие окна). Как правило, самое верхнее окно является активным. Смежное понятие этому – свойство окна все время находиться поверх других окон. Модальный диалог все время находится поверх своего владельца.
* Изменение типа модальности во время работы программы. Изменение типа модальности для видимого диалога может не иметь никакого эффекта до тех пор, пока диплог не будет спрятан и затем показан снова.
Диалог, который использует DOCUMENT_MODAL модель, блокирует все окна одного документа за исключением тех, которые являются дочерними по отношению в данному модальному диалогу. Документом является окно, не имеющее владельца. Оно может содержать другие окна, которые являются тем же документом, что и владелец. Поскольку каждое окно обязано принадлежать одному и тому же документу, их корнем будет являться ближайший владелец, у которого в свою очередь владелец не указан.
d22.setBounds(sw - 500 + 32, 232, 300, 200);
d22.addWindowListener(closeWindow);
d22.setLayout(new BorderLayout());
l = new Label("DOCUMENT_MODAL");
l.setBackground(Color.BLUE);
l.setAlignment(Label.CENTER);
l.setFont(labelFont);
d22.add(l, BorderLayout.CENTER);
// Third document
f3 = new Frame("Excluded Frame");
f3.setModalExclusionType(
Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
Диалог, который использует APPLICATION_MODAL модель, блокирует все окна одного приложения за исключением тех, которые являются дочерними по отношению в данному модальному диалогу. Если в браузере запущено несколько аплетов, то браузер может рассматривать их как принадлежащие к одному приложению или к разным. В данном случае поведение зависит от реализации браузера.
Обратите внимание, что здесь окно f3 не будет блокировано диалогами, использующими APPLICATION_MODAL и DOCUMENT_MODAL модели:
f3.setBounds(32, sh - 200 + 32, 300, 200);
f3.addWindowListener(closeWindow);
f3.setLayout(new BorderLayout());
l = new Label("EXCLUDED FRAME");
l.setBackground(Color.GREEN);
l.setAlignment(Label.CENTER);
l.setFont(labelFont);
f3.add(l, BorderLayout.CENTER);
b = new Button("I'm alive!");
f3.add(b, BorderLayout.SOUTH);
f3.setVisible(true);
// Fourth document
f4 = new Frame("Parent Frame");
f4.setBounds(sw - 300 + 32, sh - 200 + 32, 300, 200);
f4.addWindowListener(closeWindow);
f4.setLayout(new BorderLayout());
l = new Label("FRAME");
l.setBackground(Color.GRAY);
l.setAlignment(Label.CENTER);
l.setFont(labelFont);
b = new Button("Show file dialog");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fd4.setVisible(true);
}
});
f4.add(b, BorderLayout.SOUTH);
f4.setVisible(true);
fd4 = new FileDialog(f4, "File Dialog", FileDialog.LOAD);
fd4.setBounds(sw - 400 + 32, sh - 300 + 32, 300, 200);
}
Файловые диалоги используют модель APPLICATION_MODAL по умолчанию для сохранения обратной совместимости.
Программный интерфейс доступа к рабочему столу (Desktop API)
Из статьи "Using the Desktop API in Java SE 6" John O'Conner
Java SE 6 включает в свой состав так называемый DesktopAPI. Этот программный интерфейс позволяет Java приложениям взаимодействовать с приложениями, которые по умолчанию ассоциированы с определенными файлами на данной платформе. В частности, данный интерфейс позволяет:
* Запускать браузер по умолчанию с указанием ресурса (Uniform Resource Identifier, URI), который необходимо открыть
* Запускать почтового клиента, установленного по умолчанию
* Запускать приложения для открытия, редактирования и печати файлов с помощью
Данный API использует системные файловые ассоциации для запуска приложений с конкретным файлом. Например, если файлы с расширением .odt (OpenDocument Text) ассоциированы с приложением Writer из пакета OpenOffice, то Ваша Java программа сможет запустить приложение Writer для открытия, редактирования и даже для печати файлов с таким расширением. В зависимости от платформы, различные приложения могут быть использованы для различных действий.
Для определения того, доступен ли данный интерфейс на данной платформе, можно использовать метод Desktop.isDesktopSupported().
В операционной системе Solaris и на платформе Linux данный интерфейс зависит от библиотек Gnome. В том случае, если эти библиотеки недоступны, указанный метод вернет значение false. Как только выяснилось, что данный интерфейс поддерживается (метод isDesktopSupported() вернул значение true), программа может получить экземпляр класса Desktop, вызвав статический метод getDesktop():
Desktop desktop = null;
// Before more Desktop API is used, first check
// whether the API is supported by this particular
// virtual machine (VM) on this particular host.
if (Desktop.isDesktopSupported()) {
desktop = Desktop.getDesktop();
...
Если Ваше приложение не проверяет, поддерживается ли данный интерфейс, прежде чем вызывать метод getDesktop(), оно должно быть готово обработать исключительную ситуацию UnsupportedOperationException, которая генерируется если программа пытается создать класс Desktop на платформе, которая не поддерживает этой возможности. Кроме того, если Ваше приложение работает в среде, где отсутствует мышь, клавиатура или монитор (т.н. Headless окружение), метод getDesktop() генерирует исключение java.awt.HeadlessException.
Экземпляр класса позволяет Вашему приложению запускать браузер, почту, открывать, редактировать и печатать документы, но только в том случае, если данный экземпляр поддерживает указанные действия. Каждое из этих действий представлено в переменной перечислимого типа Desktop.Action:
* BROWSE. Представляет действие по открытию браузера по умолчанию
* MAIL. Представляет действие по открытию почтового клиента по умолчанию
* OPEN. Представляет действие по открытию файла определенного типа с помощью приложения по умолчанию
* EDIT. Представляет действие по редактированию файла определенного типа с помощью приложения по умолчанию
* PRINT. Представляет действие по печати содержимого файла определенного типа с помощью приложения по умолчанию
Прежде чем вызвать одну из перечисленных функций, приложение должно определить, поддерживает ли их данная платформа. Это отличается от определения того, доступен ли экземпляр класса Desktop. Метод Desktop.isDesktopSupported() определяет может ли быть создан экземпляр класса или нет. Если такой класс уже создан, можно узнать, какие действия поддерживаются.
Например, вызов следующего метода откроет браузер, установленный по умолчанию:
public void browse(URI uri) throws IOException
public static RowFilterandFilter(Iterable> filters)
public static RowFilter dateFilter(RowFilter.ComparisonType type, Date date, int... indices)
public static RowFilternotFilter(RowFilterfilter)
public static RowFilter numberFilter(RowFilter.ComparisonType type, Number number, int... indices)
public static RowFilter orFilter(Iterable> filters)
public static RowFilter regexFilter(String regex, int... indices)
Приложения могут запускать почтовый клиент если данное действие доступно посредством вызова следующего метода:
public void mail(URI uri) throws IOException
Аналогичным образом приложения Java могут открывать, редактировать и печатать файлы посредством ассоциированных с данным типом файлов приложений с помощью следующих методов класса Desktop соответственно : open(), edit() и print().
Интересно, что с различными действиями могут быть ассоциированы различные приложения даже для файлов одного типа. Например, браузер Mozilla Firefox может запускаться для открытия, Emacs – для редактирования, и какое-либо другое приложение для печати файла. Настройки Вашей системы будут использованы для того, чтобы определить, какое приложение нужно запустить. JDK 6 не позволяет разработчику изменять файловые ассоциации. В настоящее время такие настройки могут быть изменены с помощью платформозависимых инструментов.
Заключение
Последний выпуск Java SE 6 включает в себя несколько новых возможностей, которые позволят разработчикам создавать приложения более эффективно. Скачивайте Java SE 6, чтобы упростить свою разработку.
Дополнительная информация
Java Platform, Standard Edition 6 (Java SE 6)
* New and Updated Desktop Features in Java SE 6, Part 1
* Update: Desktop Java Features in Java SE 6 (Январь 2006)
Сортировка JTable
* Документаци для классов RowSorter, TableRowSorter и RowFilter
Desktop API
* Desktop API
* Скачайте приложение DesktopDemo
Перевод Дмитриев Андрей 27.11.2007
|