Статьи

JavaFX Custom Control — Гнездовой термостат, часть 2

Прошло много времени с тех пор, как я начал создавать пользовательский элемент управления FX термостата Nest! Поэтому в прошлый раз, по предложению Геррита Грюнвальда, я потратил некоторое время на то, чтобы воспроизвести дизайн термостата Nest с помощью inkscape, в качестве первого шага для создания его версии на JavaFX.

Сегодня я хотел бы поделиться с вами ошибками, которые я совершил, пытаясь создать его в JavaFX, а также с конечным результатом.

Прежде всего, я начал использовать файл css для создания фона, который составлен в моей версии inkscape из трех кругов с тремя линейными градиентами и двумя мазками. Как предложил Геррит, я сделал это, используя только один Регион, и стилизовал его с помощью CSS.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
.nest{}
 
.nest .frame {
  -fx-background-radius     : 1024px;
  -fx-background-insets     : 1, 4, 20;
  -fx-background-color      : linear-gradient(from 27.1% 6.5% to 77.35% 91%, 
                                        #e8e8e8 0%,
                                        #c6c6c6 50%,
                                        #a6a6a6 100%),
                                  linear-gradient(from 27.1% 6.5% to 77.35% 91%,
                                        #fdfdfd 0%,
                    #ededed 3.552646%,
                    #d7d7d7 7.277831%,
                    #d2d2d2 11.973317%,
                    #c7c7c7 18.269639%,
                    #c1c1c1 25.449407%,
                    #b0b0b0 32.21809%,
                    #999999 37.210315%,
                    #868686 43.145844%,
                    #747474 49.577036%,
                    #5c5c5c 55.667913%,
                    #5a5a5a 61.299348%,
                    #5e5e5e 68.340749%,
                    #676767 76.115692%,
                    #706e6f 82.365692%,
                    #838383 88.148153%,
                    #959595 93.637025%,
                    #a8a8a8 100%),
                linear-gradient(from 27.1% 6.5% to 77.35% 91%,
                                        #1c1715 0%,
                                        #181818 50%,
                                        #3a3a3a 100%);
  -fx-border-radius     : 1024px;
  -fx-border-insets     : 0, 5, 20;
  -fx-border-width      : 0, 2, 1;
  -fx-border-color      : transparent,
                  linear-gradient(from 27.1% 6.5% to 77.35% 91%,
                                        #d5d5d5 0%,
                                        #747474 50%,
                                        #8f8f8f 100%),
                                  #212121;
}

Конечный результат был хорошим, но когда я изменил размер своего элемента управления, у меня был плохой результат, так как -fx-background-insets и -fx-border-width являются абсолютными значениями пикселей. Вы можете увидеть мою проблему ниже.

Гнездо-Mistake1
Мне потребовалось некоторое время, чтобы понять, как это исправить. В конце концов, единственная идея, которую я имел, состояла в том, чтобы сделать три разных региона и использовать значения пути svg. Это исправило бы значения пикселей -fx-background-вставок, но не штриховые.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
.nest{}
 
.nest .frame {
  -fx-shape         : "m 519.18435,179.4957 a 266.9594,266.9594 0 1 1 -0.72682,-2.0685";
  -fx-background-insets         : 1;
  -fx-background-color          : linear-gradient(from 27.1% 6.5% to 77.35% 91%, 
                                        #e8e8e8 0%,
                                        #c6c6c6 50%,
                                        #a6a6a6 100%);
}
 
.nest .frame1 {
  -fx-shape         : "m 514.32688,181.18013 a 261.81818,261.81818 0 1 1 -0.71283,-2.02866";
  -fx-background-color          : linear-gradient(from 27.1% 6.5% to 77.35% 91%,
                                        #fdfdfd 0%,
                    #ededed 3.552646%,
                    #d7d7d7 7.277831%,
                    #d2d2d2 11.973317%,
                    #c7c7c7 18.269639%,
                    #c1c1c1 25.449407%,
                    #b0b0b0 32.21809%,
                    #999999 37.210315%,
                    #868686 43.145844%,
                    #747474 49.577036%,
                    #5c5c5c 55.667913%,
                    #5a5a5a 61.299348%,
                    #5e5e5e 68.340749%,
                    #676767 76.115692%,
                    #706e6f 82.365692%,
                    #838383 88.148153%,
                    #959595 93.637025%,
                    #a8a8a8 100%);                             
  -fx-border-width      : 2;
  -fx-border-color      : linear-gradient(from 27.1% 6.5% to 77.35% 91%,
                                        #d5d5d5 0%,
                                        #747474 50%,
                                        #8f8f8f 100%);
}
 
.nest .frame2 {
  -fx-shape         : "m 497.45305,187.03163 a 243.95858,243.95858 0 1 1 -0.66421,-1.89028";
  -fx-background-color          : linear-gradient(from 27.1% 6.5% to 77.35% 91%,
                                        #1c1715 0%,
                                        #181818 50%,
                                        #3a3a3a 100%);
  -fx-border-width      : 1;
  -fx-border-color      : #212121;
}

nestmistake2.1

Во всяком случае, когда я попробовал это, вот результат, который я имел.

??? Что это ??? почему я вижу только один кружок … Ну, я должен сказать, что я потратил некоторое время, чтобы понять, что это атрибуты fx-scale-shape и fx-position-shape, значение по умолчанию которых равно true. Вот это определение этих двух атрибутов CSS

-fx-позиционно-форма <логическое> правда Если true, то означает, что фигура центрирована в пределах ширины и высоты области, в противном случае фигура располагается в исходной позиции. Не действует, если строка формы не указана.
-fx-масштабно-форма <логическое> правда Если истина означает, что форма масштабируется до размера области, в противном случае форма имеет исходный размер, и ее положение зависит от значения свойства position-shape. Не действует, если строка формы не указана.

Поэтому мне нужно только установить значение масштаба на false, тогда … Но когда я это сделал, форма в области не изменилась должным образом при изменении размера элемента управления … Аааааааааааааааааааааааааааааааааааааааааааааааааааа уже !!!!

nestmistake2.2

Ну, в конце концов я попытался масштабировать регион и установить его prefSize при изменении размера элемента управления. Поэтому я использовал фрагмент кода ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
private void resize() {
   size = getWidth() < getHeight() ? getWidth() : getHeight();
   final double scaleRatio = size / initialSize;
   frame.setPrefSize(size, size);
   frame.setScaleX(scaleRatio);
   frame.setScaleY(scaleRatio);
 
   frame1.setPrefSize(size, size);
   frame1.setScaleX(scaleRatio);
   frame1.setScaleY(scaleRatio);
 
   frame2.setPrefSize(size, size);
   frame2.setScaleX(scaleRatio);
   frame2.setScaleY(scaleRatio);
}

НСТ-Mistake3

Это сработало !!!

Ну, я не знаю, является ли это правильным способом сделать это, но это единственный, который я нашел до сих пор … Если вы используете другие приемы для решения проблем, которые я определил в этом посте, поделитесь им вслух в разделе комментариев !!

Тики и currentCursor и targetCursor выполняются с использованием моего RadialMenuItem от RadialFX . Пока что он не позволил мне настроить его, хотя css, но теперь, когда я начинаю понимать, как он работает, следующим шагом является улучшение RadialFx RadialMenuItem с помощью атрибутов css.

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

  • Код скоро будет доступен и на JFXtras !

Ссылка: JavaFX Custom Control — Nest Thermostat Part 2 от нашего партнера JCG Лорана Николя в блоге Mr LoNee .