Spec-Zone .ru
спецификации, руководства, описания, API
|
Создание пользовательского стили, или изменение существующего, могут быть грандиозной задачей. javax.swing.plaf.synth
пакет может использоваться, чтобы создать пользовательский стиль с намного меньшим усилием. Можно создать стиль Синтезатора или programatically или с помощью внешнего XML-файла. Обсуждение ниже посвящается созданию стили Синтезатора, используя внешний XML-файл. Создавая Синтезатор c programatically обсуждается в документации API.
Со стилем Синтезатора Вы обеспечиваете "взгляд". Сам синтезатор обеспечивает "чувство". Таким образом можно думать о Синтезаторе L&F как "кожа".
Вспомните из предыдущей темы, что это - ответственность каждого L&F, чтобы обеспечить конкретную реализацию для каждого из многих ComponentUI
подклассы определяются Swing. Синтезатор L&F заботится об этом для Вас. Чтобы использовать Синтезатор, Вы не должны создать никого ComponentUI
s — скорее Вы должны только определить, как каждый компонент красится, наряду с различными свойствами, которые производят расположение и размер.
Синтезатор работает на более гранулированном уровне чем компонент — этот гранулированный уровень вызывают "областью". У каждого компонента есть одна или более областей. У многих компонентов есть только одна область, такой как JButton
. У других есть многократные области, такой как JScrollBar
. Каждый из ComponentUIs
если Синтезатором связывает a SynthStyle
с каждой из областей, определенных ComponentUI
. Например, Синтезатор определяет три области для JScrollBar
: дорожка, ползунок и полоса прокрутки непосредственно. ScrollBarUI
( ComponentUI
подкласс, определенный для JScrollBar
) реализация для Синтезатора связывает a SynthStyle
с каждой из этих областей.
SynthStyle
предоставляет информацию о стиле, используемую Синтезатором ComponentUI
реализация. Например, SynthStyle
определяет цвет переднего плана и цвет фона, информацию о шрифте, и т.д. Кроме того, каждый SynthStyle
имеет a SynthPainter
это используется, чтобы нарисовать область. Например, SynthPainter
определяет эти два метода paintScrollBarThumbBackground
и paintScrollBarThumbBorder
, которые используются, чтобы нарисовать области ползунка полосы прокрутки.
Каждый из ComponentUIs
в Синтезаторе получают SynthStyles
использование a SynthStyleFactory
. Есть два способа определить a SynthStyleFactory
: через XML-файл Синтезатора, или programatically. Следующие шоу кода, как загрузить XML-файл, диктующий вид Синтезатора — ниже покрытий, это создает a SynthStyleFactory
реализация, заполненная с SynthStyles
от XML-файла:
SynthLookAndFeel laf = new SynthLookAndFeel(); laf.load(MyClass.class.getResourceAsStream("laf.xml"), MyClass.class); UIManager.setLookAndFeel(laf);
Программируемый маршрут включает создание реализации SynthStyleFactory
это возвращается SynthStyles
. Следующий код создает пользовательское SynthStyleFactory
это возвращается отличный SynthStyles
для кнопок и деревьев:
class MyStyleFactory extends SynthStyleFactory { public SynthStyle getStyle(JComponent c, Region id) { if (id == Region.BUTTON) { return buttonStyle; } else if (id == Region.TREE) { return treeStyle; } return defaultStyle; } } SynthLookAndFeel laf = new SynthLookAndFeel(); UIManager.setLookAndFeel(laf); SynthLookAndFeel.setStyleFactory(new MyStyleFactory());
Choosing a Synth look and feel for your application is simple. This code loads the XML file into Synth from an input stream and then sets the current look and feel to Synth:
SynthLookAndFeel laf = new SynthLookAndFeel(); laf.load(MyApp.class.getResourceAsStream("synth_def.xml"), MyApp.class); UIManager.setLookAndFeel(laf);
The Synth feel (or, "skin"), is defined in the external file, synth_def.xml
, which must be loaded
as shown. The second parameter in the load()
method defines the path to the XML file and any images used,
indicating that they are
to be found with the same path as the MyApp.class
file.
SynthLookAndFeel laf = new SynthLookAndFeel(); laf.load(new URL("file:///C:/java/synth/laf/synth_def.xml")); UIManager.setLookAndFeel(laf);
The load()
method throws a checked exception, ParseException
, so the
laf.load(MyApp.class.getResourceAsStream("synth_def.xml"), MyApp.class);
statement should be in a try
block. A more robust example is this initLookAndFeel()
method in the MyApp
class that will override the default look and feel to
create a Synth look and feel from the external XML file.:
private static void initLookAndFeel() { SynthLookAndFeel laf = new SynthLookAndFeel(); try { laf.load(MyApp.class.getResourceAsStream("synth_def.xml"), MyApp.class); UIManager.setLookAndFeel(laf); } catch (ParseException e) { System.err.println("Couldn't get specified look and feel (" + lookAndFeel + "), for some reason."); System.err.println("Using the default look and feel."); e.printStackTrace(); } }
Объяснение DTD для XML-файла Синтезатора может быть найдено в javax.swing.plaf.synth/doc-files/synthFileFormat.html
.
Когда Вы загружаете стиль Синтезатора, только те компоненты GUI (или области), для которого есть определение ("стиль", связанный с областью, как обсуждено ниже) представляются. Нет никакого поведения значения по умолчанию ни для каких компонентов — без определений стиля в XML-файле Синтезатора, GUI является пустым холстом.
Чтобы определить рендеринг компонента (или область), Ваш XML-файл должен содержать <стиль> элемент, который тогда связывается с областью, используя <связывать> элемент. Как пример, давайте определим стиль, который включает шрифт, цвет переднего плана, и цвет фона, и затем свяжите тот стиль со всеми компонентами. Это - хорошая идея включать такой элемент в Ваш XML-файл Синтезатора, в то время как Вы разрабатываете это — тогда, у любых компонентов, которые Вы еще не определили, по крайней мере, будут цвета и шрифт:
<synth> <style id="basicStyle"> <font name="Verdana" size="16"/> <state> <color value="WHITE" type="BACKGROUND"/> <color value="BLACK" type="FOREGROUND"/> </state> </style> <bind style="basicStyle" type="region" key=".*"/> </synth>
Давайте проанализируем это определение стиля:
<Стиль> элемент является основой XML-файла Синтезатора. Это содержит всю информацию, должен был описать рендеринг области. <Стиль> элемент может описать больше чем одну область, как делается здесь. Вообще, тем не менее, лучше создавать <стиль> элемент для каждого компонента или области. Отметьте, что <стиль> элементу дают идентификатор, строка "basicStyle". Этот идентификатор будет использоваться позже в <связывать> элементе.
<Шрифт> элемент <стиль> элемент устанавливает шрифт в Verdana, размер 16.
<Состояние> элемент <стиль> элемент будет обсужден ниже. <Состояние> элемент области может иметь один, или смесь, семи возможных значений. Когда значение не определяется, определение применяется ко всем состояниям, который является намерением здесь. Поэтому, цвета фона и цвета переднего плана "для всех состояний" определяются в этом элементе.
Наконец, <стиль> элемент с идентификатором "basicStyle", который был только что определен, связывается со всеми областями. <Связывать> элемент связывает "basicStyle" с типами "области". Какой тип области или типы, которым применяется к привязка, даются "ключевым" атрибутом, который является ". *" в этом случае, регулярное выражение для "всех".
Давайте смотреть на части XML-файла Синтезатора прежде, чем создать некоторые рабочие примеры. Мы запустим со <связывать> элемента, показывая, как данный <разрабатывает>, применяется к компоненту или области.
Всякий раз, когда <стиль> элемент определяется, это должно быть связано с одним или более компонентами или областями прежде, чем это будет иметь эффект. <Связывать> элемент используется с этой целью. Требуется три атрибута:
style
уникальный идентификатор ранее определенного стиля.
type
или "имя" или "область". Если type
имя, получите имя с component.getName()
метод. Если type
область, используйте соответствующую константу, определенную в Region
class в javax.swing.plaf.synth
пакет.
key
регулярное выражение, используемое, чтобы определить, с какими компонентами или областями стиль связывается.
Область является способом идентифицировать компонент или часть компонента. Области основаны на константах в Region
Например, чтобы идентифицировать область SPLIT_PANE Вы использовали бы РАЗДЕЛЕННУЮ ОБЛАСТЬ, разделенную область, или (нечувствительный к регистру) SplitPane.
Когда Вы свяжете стиль с областью, тот стиль применится ко всем компонентам с той областью. Можно связать стиль больше чем с одной областью, и можно связать больше чем один стиль с областью. Например,
<style id="styleOne"> <!-- styleOne definition goes here --> </style> <style id="styleTwo"> <!-- styleTwo definition goes here --> </style> <bind style="styleOne" type="region" key="Button"/> <bind style="styleOne" type="region" key="RadioButton"/> <bind style="styleOne" type="region" key="ArrowButton"/> <bind style="styleTwo" type="region" key="ArrowButton"/>
Можно связать с отдельными, именованными компонентами, связываются ли они также как области. Например, предположите, что Вы хотите иметь кнопки "OK" и "Cancel" в своем GUI, обработанном по-другому чем все другие кнопки. Во-первых, Вы дали бы OK и имена кнопок Cancel, используя component.setName()
метод. Затем, Вы определили бы три стиля: один для кнопок вообще (область = "Кнопка"), один для кнопки OK (называют = "OK"), и один для кнопки Cancel (имя = "Отмена"). Наконец, Вы связали бы эти стили как это:
<bind style="styleButton" type="region" key="Button"> <bind style="styleOK" type="name" key="OK"> <bind style="styleCancel" type="name" key="Cancel">
В результате кнопка "OK" связывается и с "styleButton" и с "styleOK", в то время как кнопка "Cancel" связывается и с "styleButton" и с "styleCancel".
Когда компонент или область связываются больше чем с одним стилем, стили объединяются
Так же, как стиль может быть связан с многократными областями или именами, многократные стили могут быть связаны с областью или именем. Эти многократные стили объединяются для области или имени. Приоритет дается стилям, определенным позже в файле.
<Состояние> элемент позволяет Вам определять взгляд для области, которая зависит от ее "состояния". Например, Вы будете обычно хотеть кнопку, которая была PRESSED
выглядеть по-другому чем кнопка в ENABLED
состояние. Есть семь возможных значений для <состояния>, которые определяются в DTD XML Синтезатора. Они:
Вы можете также иметь составные состояния, разделенные 'и' — например, ВКЛЮЧЕННЫЙ, и ФОКУСИРОВАЛИСЬ. Если Вы не определите значение, то определенный взгляд применится ко всем состояниям.
Как пример, вот стиль, который определяет живописцев на состояние. Все кнопки красятся определенный путь, если состояние не "НАЖИМАЕТСЯ", когда они красятся по-другому:
<style id="buttonStyle"> <property key="Button.textShiftOffset" type="integer" value="1"/> <insets top="10" left="10" right="10" bottom="10"/> <state> <imagePainter method="buttonBackground" path="images/button.png" sourceInsets="10 10 10 10"/> </state> <state value="PRESSED"> <color value="#9BC3B1" type="BACKGROUND"/> <imagePainter method="buttonBackground" path="images/button2.png" sourceInsets="10 10 10 10"/> </state> </style> <bind style="buttonStyle" type="region" key="Button"/>
Игнорируя <свойство> и <вставки> элементы в настоящий момент, можно видеть, что нажатая кнопка красится по-другому чем ненажатая кнопка.
<Состояние> значение, которое используется, является определенным состоянием, которое наиболее близко соответствует состояние области. Соответствие определяется числом значений, которые соответствуют состояние области. Если ни одно из состояния не оценивает соответствие, то состояние без значения используется. Если будут соответствия, то состояние с большинством отдельных соответствий будет выбрано. Например, следующий код определяет три состояния:
<state id="zero"> <color value="RED" type="BACKGROUND"/> </state> <state value="SELECTED and PRESSED" id="one"> <color value="RED" type="BACKGROUND"/> </state> <state value="SELECTED" id="two"> <color value="BLUE" type="BACKGROUND"/> </state>
Если состояние области содержит, по крайней мере, ВЫБРАННЫЙ и НАЖАТЫЙ, утвердите, что каждый будет выбран. Если состояние будет содержать ВЫБРАННЫЙ, но не не будет содержать НАЖАТЫЙ, то утверждает два будет использоваться. Если состояние не будет содержать ни ВЫБРАННЫЙ, ни НАЖАТЫЙ, то нуль состояния будет использоваться.
Когда текущее состояние соответствует то же самое число значений для определений с двумя состояниями, тот, который используется, является первым, определенным в стиле. Например, MOUSE_OVER
состояние всегда верно для a PRESSED
кнопка (невозможно нажать кнопку, если мышь не по ней). Так, если MOUSE_OVER
состояние объявляется сначала, оно будет всегда выбираться PRESSED
, и любое рисование, определенное для PRESSED
не будет сделан.
<state value="PRESSED"> <imagePainter method="buttonBackground" path="images/button_press.png" sourceInsets="9 10 9 10" /> <color type="TEXT_FOREGROUND" value="#FFFFFF"/> </state> <state value="MOUSE_OVER"> <imagePainter method="buttonBackground" path="images/button_on.png" sourceInsets="10 10 10 10" /> <color type="TEXT_FOREGROUND" value="#FFFFFF"/> </state>
Код выше будет работать должным образом. Однако, если Вы инвертируете порядок MOUSE_OVER
и PRESSED
состояния в файле, PRESSED
состояние никогда не будет использоваться. Это - то, потому что любое состояние, которое является PRESSED
состояние также a MOUSE_OVER
состояние. Начиная с MOUSE_OVER
состояние было определено сначала, это - то, которое будет использоваться.
<Цветной> элемент требует двух атрибутов:
value
может быть любой из java.awt.Color
константы, такой как КРАСНЫЙ, БЕЛЫЙ, ЧЕРНЫЙ, СИНИЙ, и т.д. Это может также быть шестнадцатеричное представление значений RGB, такой как #FF00FF или #326A3B.
type
описывает, где цвет применяется — это может быть ФОН, ПЕРЕДНИЙ ПЛАН, ФОКУС, TEXT_BACKGROUND, ИЛИ TEXT_FOREGROUND.
Например:
<style id="basicStyle"> <state> <color value="WHITE" type="BACKGROUND"/> <color value="BLACK" type="FOREGROUND"/> </state> </style>
<Шрифт> у элемента есть три атрибута:
name
— имя шрифта. Например, Arial или Verdana.
size
— размер шрифта в пикселях.
style
(дополнительный) — ПОЛУЖИРНЫЙ, КУРСИВ, ИЛИ ПОЛУЖИРНЫЙ КУРСИВ. Если опущено, Вы получаете нормальный шрифт.
Например:
<style id="basicStyle"> <font name="Verdana" size="16"/> </style>
У каждого <цветного> элемента и <шрифт> элемент есть альтернативное использование. Каждый может иметь id
атрибут или idref
атрибут. Используя id
атрибут, можно определить цвет, который можно снова использовать позже при использовании idref
атрибут. Например,
<color id="backColor" value="WHITE" type="BACKGROUND"/> <font id="textFont" name="Verdana" size="16"/> ... ... ... <color idref="backColor"/> <font idref="textFont"/>
insets
добавьте к размеру компонента, поскольку он оттягивается. Например, без вставок, кнопки с заголовком Cancel
будет только достаточно большим, чтобы содержать заголовок в выбранном шрифте. Со <вставки> элемент как это
<insets top="15" left="20" right="20" bottom="15"/>,
кнопка будет сделана больше 15 пикселями выше и ниже заголовка и 20 пикселей налево и права на заголовок.
Формат файла синтезатора позволяет настраивать рисование посредством изображений. Живописец изображения синтезатора повреждает изображение в девять отличных областей: главный, верхний правый, правильный, нижний правый, нижняя часть, нижняя левая, оставленная, верхняя левая, и центральный. Каждая из этих областей красится в место назначения. Вершина, оставленная, нижняя часть, и правые края, размещается рядом или расширяется, в то время как угловые части (sourceInsets
) останьтесь фиксированными.
Нет никакого отношения между <вставки> элемент и sourceInsets
атрибут. <Вставки> элемент определяет пространство, приведенное в рабочее состояние областью, в то время как sourceInsets
атрибуты определяют, как нарисовать изображение. <Вставки> и sourceInsets
часто будет подобно, но они не должны быть.
Можно определить, должна ли центральная область быть нарисована paintCenter
атрибут. Следующее изображение показывает эти девять областей:
Давайте создадим кнопку как пример. Чтобы сделать это, мы можем использовать следующее изображение (показанный больше чем его фактический размер):
Красное поле в левом верхнем углу является 10 пиксельными квадратами (включая границу поля) — это показывает угловую область, которая не должна быть расширена, крася. Достигнуть этого, вершины и оставленный sourceInsets
должен быть установлен в 10. Мы будем использовать следующий стиль и привязку:
<style id="buttonStyle"> <insets top="15" left="20" right="20" bottom="15"/> <state> <imagePainter method="buttonBackground" path="images/button.png" sourceInsets="10 10 10 10"/> </state> </style> <bind style="buttonStyle" type="region" key="button"/>
Строки в <состояние>, элемент определяет, что фон кнопок должен быть нарисован, используя изображение images/button.png
. Тот путь относительно Класса, который передают в метод загрузки SynthLookAndFeel. sourceInsets
атрибут определяет области изображения, которые не должны быть расширены. В этом случае вершина, оставленная, нижняя часть, и правильные вставки, является каждым 10. Это заставит живописца не расширять 10 x 10 пиксельных областей в каждом углу изображения.
<Связывание> связывает buttonStyle
ко всем кнопкам.
<imagePainter> элемент предоставляет всю информацию, должен был представить часть области. Требуется только несколько атрибутов:
метод — это определяет который из методов в javax.swing.plaf.synth.SynthPainter
class должен использоваться для рисования. SynthPainter
class содержит приблизительно 100 методов, которые начинаются paint
. Когда Вы определяете, в каком Вы нуждаетесь, Вы удаляете paint
префикс, измените остающуюся первую букву на нижний регистр, и используйте результат в качестве method
атрибут. Например, SynthPainter
метод paintButtonBackground
становится атрибутом buttonBackground
.
путь — путь к изображению, которое будет использоваться, относительно Класса, который передают в метод загрузки SynthLookAndFeel.
sourceInsets — вставки в пикселях, представляя width и height угловых областей, которые не должны быть расширены, Они отображаются на вершину, оставленную, нижняя часть, и право, в том порядке.
(дополнительный) paintCenter: Этот атрибут позволяет Вам сохранять центр изображения или избавляться от этого (в текстовом поле, например, таким образом, текст может быть оттянут).
Упоминающие ниже шоу XML кодируют для того, чтобы загрузить различные изображения в зависимости от <состояние> кнопки
<style id="buttonStyle"> <property key="Button.textShiftOffset" type="integer" value="1"/> <insets top="15" left="20" right="20" bottom="15"/> <state> <imagePainter method="buttonBackground" path="images/button.png" sourceInsets="10 10 10 10"/> </state> <state value="PRESSED"> <imagePainter method="buttonBackground" path="images/button2.png" sourceInsets="10 10 10 10"/> </state> </style> <bind style="buttonStyle" type="region" key="button"/>
button2.png показывает подавленную версию button.png, смещал один пиксель направо. Строка
<property key="Button.textShiftOffset" type="integer" value="1"/>
смещает текст кнопки соответственно, как обсуждено в следующем разделе.
<свойство> элементы используется, чтобы добавить пар значения ключа к <стиль> элемент. Много компонентов используют пар значения ключа для того, чтобы сконфигурировать их визуальное появление.
<Свойство> элемент имеет три атрибута:
key
— имя свойства.
type
— тип данных свойства.
value
— значение свойства.
Есть таблица свойства (componentProperties.html
) это перечисляет свойства, которые поддерживает каждый компонент: javax/swing/plaf/synth/doc-files/componentProperties.html
Начиная с button2.png смещений изображения визуальная кнопка один пиксель, когда это подавляется, мы должны также сместить текст кнопки. Есть свойство кнопки, которое делает это:
<property key="Button.textShiftOffset" type="integer" value="1"/>
Вот пример, используя стиль кнопки, определенный выше. Стиль кнопки, плюс "отступающий стиль" с определениями шрифта и цветов, которые связываются со всеми областями (подобный "basicStyle", показанному в разделе, названном "XML-файл," выше) объединяются в
Вот перечисление buttonSkin.xml
buttonSkin.xml
:
<!-- Synth skin that includes an image for buttons --> <synth> <!-- Style that all regions will use --> <style id="backingStyle"> <!-- Make all the regions that use this skin opaque--> <opaque value="TRUE"/> <font name="Dialog" size="12"/> <state> <!-- Provide default colors --> <color value="#9BC3B1" type="BACKGROUND"/> <color value="RED" type="FOREGROUND"/> </state> </style> <bind style="backingStyle" type="region" key=".*"/> <style id="buttonStyle"> <!-- Shift the text one pixel when pressed --> <property key="Button.textShiftOffset" type="integer" value="1"/> <insets top="15" left="20" right="20" bottom="15"/> <state> <imagePainter method="buttonBackground" path="images/button.png" sourceInsets="10 10 10 10"/> </state> <state value="PRESSED"> <imagePainter method="buttonBackground" path="images/button2.png" sourceInsets="10 10 10 10"/> </state> </style> <!-- Bind buttonStyle to all JButtons --> <bind style="buttonStyle" type="region" key="button"/> </synth>
Мы можем загрузить этот XML-файл, чтобы использовать стиль Синтезатора для простого вызванного приложения SynthApplication.java
. GUI для этого приложения включает кнопку и метку. Каждый раз кнопка нажимается, инкременты метки.
Метка красится, даже при том, что buttonSkin.xml
не содержит стиль для этого. Это - то, потому что есть общий "backingStyle", который включает шрифт и цвета.
Вот перечисление
файл.SynthApplication.java
Нажмите кнопку Launch, чтобы работать, пример SynthApplication, используя Сеть Java™ Запускаются (
Переключатели и флажки обычно представляют свое состояние значками фиксированного размера. Для них можно создать значок и связать его с соответствующим свойством (обратитесь к таблице свойств, javax/swing/plaf/synth/doc-files/componentProperties.html
<style id="radioButton"> <imageIcon id="radio_off" path="images/radio_button_off.png"/> <imageIcon id="radio_on" path="images/radio_button_on.png"/> <property key="RadioButton.icon" value="radio_off"/> <state value="SELECTED"> <property key="RadioButton.icon" value="radio_on"/> </state> </style> <bind style="radioButton" type="region" key="RadioButton"/>
Формат файла синтезатора учитывает встраивание произвольных объектов посредством long-term persistence of JavaBeans components
<synth> <object id="gradient" class="GradientPainter"/> <style id="textfield"> <painter method="textFieldBackground" idref="gradient"/> </style> <bind style="textfield" type="region" key="textfield"/> </synth>
Где GradientPainter class похож на это:
public class GradientPainter extends SynthPainter { public void paintTextFieldBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { // For simplicity this always recreates the GradientPaint. In a // real app you should cache this to avoid garbage. Graphics2D g2 = (Graphics2D)g; g2.setPaint(new GradientPaint((float)x, (float)y, Color.WHITE, (float)(x + w), (float)(y + h), Color.RED)); g2.fillRect(x, y, w, h); g2.setPaint(null); } }
В этом уроке мы покрыли использование javax.swing.plaf.synth
пакет, чтобы создать пользовательский стиль. Акцент урока был на использовании внешнего XML-файла, чтобы определить стиль. Следующий урок представляет пример приложения, который создает диалоговое окно поиска, используя платформу Синтезатора с XML-файлом.