Try English version of Quizful



Раздаем бесплатные Q! подробности в группе Quizful.Alpha-test
Топ контрибуторов
loading
loading
Знаете ли Вы, что

Вы можете подписаться на RSS ленту новых тестов сервиса Quizful, в том числе и отдельно по каждой категории

Лента обновлений
ссылка 12:31:40
Комментарий от log4456602:
Я так понял для варианта :
String a1 = "Test";
String...
ссылка 12:05:43
Добавлен вопрос в тест Базы данных (теория)
ссылка 11:22:41
Комментарий от log4456602:
Действительно!)))
ссылка 00:08:51
Добавлен вопрос в тест XML
ссылка 00:06:23
Добавлен вопрос в тест XML
Статистика

Тестов: 153, вопросов: 8597. Пройдено: 417956 / 2039339.

JavaFX. Начало.

head tail Статья
категория
Java
дата08.10.2014
авторcyber_1
голосов39
JavaFX

Это моя первая статья, и я не жду, что она вызовет ажиотаж у публики, но надеюсь, что кому-то она будет интересна. Заранее извиняюсь за некорректные формулировки некоторых определений, ибо я пишу, как понимаю. Также хочу сразу извинится за ошибки которые мог совершить во время написания, ибо не Пушкин я, и пера не имею)

В этой статье речь пойдет о JavaFX. Это очень мощный, но пока молодой продукт от всеми любимой Oracle, который может вырасти титаном разработки приятных для глаза человеческого приложений. И я говорю не про “Helloworld” в консоли, а про красочное, анимационное, кроссплатформенное приложение, которое может поставить на место многие платформы по разработке пользовательских приложений.

Немного фактов:

«JavaFX — платформа для создания RIA(RichInternetApplication), позволяет строить унифицированные приложения с насыщенным графическим интерфейсом пользователя для непосредственного запуска из-под операционных систем, работы в браузерах и на мобильных телефонах, в том числе, работающих с мультимедийным содержимым».

В общем, из определения которое взято из Википедии, можно понять, что это что-то непонятное, но крутое. Так оно и есть.

Коротко из истории:

В далеком 2007 на JavaOne компания SunMicrosystems представила миру первую версию платформы JavaFX. Для того, чтобы иметь возможность писать на этой платформе программы, вам было нужно ставить компилятор, и учить новый язык – JavaFXScript. Но все изменилось, когда Oracle купила SunMicrosystems. Компания решила прекратить развитие JavaFXScript, но сообщила, что 2 версия JavaFX будет портирована на Java. И уже 10 октября 2011 года была выпущена JavaFX версии 2.0, в виде библиотеки для Java. А с выпуском восьмой версии Java, она была добавлена в состав JDK и получила символический номер 8.

Возможности:

Среди возможностей этой платформы можно отметить: кроссплатформенность, поддержка каскадных таблицей стилей, поддержка анимации компонентов, возможность работы и отображение 3D графики, поддержка тачей и сенсоров и очень многое другое.

Чтобы лучше разобраться нужна, конечно же, практика. Давайте создадим новый проект. Что для этого нужно? Если вы уже используете Java 8, то можно выбрать вкладку JavaFX в окне File – NewProject(это для IntellijIDEA). Если же вы используете версию Java младше восьмой, вам нужно скачать библиотеку JavaFX из сайта Oracle, а потом импортировать в проект. В интернете есть полно информации как это все сделать.

Когда вы создали пустой проект, вы увидите 3 файла: Controller.java, sample.fxml, Main.java

Для начала нам не потребуется ни контроллер, ни файл з разметкой.

Начнем с простого примера.

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

Приступим. После создания проекта, ми увидим что-то следующее:



public class Main extends Application {
 
    @Override
    public void start(Stage primaryStage) throws Exception{
        primaryStage.setTitle("Simple Application");
        primaryStage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
}

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

В методе main, где находится точка входа в программу, вызывается метод launch(), он в свою очередь, является точкой входа в FXприложение. Метод start() вызывается при создании потока приложения, в его параметрах можно увидеть объект класса Scene. Этот класс связан с экземпляром окна, которое будет видеть пользователь. Stageимеет большой набор методов, которые очень облегчают жизнь. Если знаете английский язык, то вы будете понимать интуитивно, что делает большинство методов.

Идем дальше, метод setScene(Scene), что он делает? Чтобы ответить на этот вопрос, нужно понять, что такое Scene. А Scene – это хранилище контента окна.

Начинаем писать. Напишем метод, который будет создавать сцену.


private int windowWidth = 600; 
private int windowHeight = 600;
   
. . .
   
private Scene createScene(){
        Group root = new Group();
        Scene scene = new Scene(root, windowWidth, windowHeight);
        
        return scene;
   
}

Для того, чтобы создать сцену, нужно указать главного родителя(root), куда можно будет добавлять элементы.

Итак, у нас это экземпляр класса Group, он наследуется от класса Parent, поэтому может содержать в себе другие элементы.

Он представляет собой NullLayoutиз Swing, то есть, какие координаты мы зададим элементу, то там он и будет рисоваться. Еще есть много контейнеров, некоторые представлены ниже.

  • HBox(горизонтальная очередь элементов)
  • VBox(вертикальная очередь элементов)
  • FlowPane(многострочная горизонтальная очередь элементов)
  • BorderPane(контейнер с 5 местами, сверху, снизу, слева, справа и по центру)
  • GridPane(сетка элементов)
  • ScrollPane(контейнер с возможностью прокрутки)

Это не все, но для начала этих хватит с головой.

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

Давайте напишем метод, который будет создавать текстовое поле в случайной точке нашего окна.


private Random random = new Random(); // нам нужен рандом!!
. . .
 
private Label createLabel(){
        Label label = LabelBuilder.create()    // создание билдера для Label
                .text("SomeText")             // текстовое значение
                .prefWidth(100)                // возможная ширина
                .prefHeight(50)                // возможная высота
                .alignment(Pos.CENTER)         // выравнивание содержимого по центру
                .layoutX(random.nextInt(windowWidth - 100)) // задание  коорд. Х
                .layoutY(random.nextInt(windowWidth - 50))  // задание  коорд. Y
                .style("-fx-background-color: orange;")  // зарисуем фон в оранжевый
                .build(); // создадим из билдера сам объект класса Label
 
        return label;
}

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

Теперь нужно добавить результат этого метода в наше приложение. Для этого нужно понимать, как устроен граф компонентов. Чтобы узнать список элементов внутри контейнера нужно обратиться к методу getChildren(), он вернет ObservableList, при изменении которого произойдет немедленная перерисовка контейнера. Поэтому, чтобы добавить

элемент в сцену, нужно его добавить в список детей одного из контейнеров.


root.getChildren().add(createLabel());

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

Теперь давайте сделаем так, чтобы мы могли перетаскивать этот текстовый блок по площади окна приложения. Для этого нужно отлавливать события. В JavaFX слушателей очень много.

Из всей этой кучи нам нужны будут только onMousePressed, onMouseReleased иonMouseDragged. Итак, первый слушатель должен оповестить нас, что пользователь нажал на нужный элемент, второй – о том, что пользователь притащил элемент на нужное место, ну и последний нужен для плавной картинки, чтобы элемент бежал за указателем мыши.

Далее представлен листинг метода, где цепляются все эти слушатели:


privateNodenode;   // ссылка на объект, который будем перетаскивать
privateVec2fdelta; // координаты указателя мыши относительно элемента 
                     // нужны для того, чтобы не было резкого рывка вначале движения
 
. . . 
private void addTranslateListener(final Node node) {
   node.setOnMousePressed(new EventHandler() {
             
   @Override
   public void handle(MouseEvent mouseEvent) {
      delta = new Vec2f((float)(mouseEvent.getSceneX() - node.getLayoutX()),
                        (float)(mouseEvent.getSceneY()- node.getLayoutY())); 
                        // вичисление координат относительно элемeнта
      Main.this.node = node;   // сохраняем ссылку на объект
    }
    });
 
   node.setOnMouseReleased(new EventHandler() {
           
   @Override
   public void handle(MouseEvent mouseEvent) {
       Main.this.node = null;  // обнулям ссылку на объект
   }
   });
 
   node.setOnMouseDragged(new EventHandler() {
           
   @Override
   public void handle(MouseEvent mouseEvent) {
      if (node != null){
// если есть что перетаскивать, перетаскиваем
        node.setLayoutX(mouseEvent.getSceneX() - delta.x); 
        node.setLayoutY(mouseEvent.getSceneY() - delta.y);
      }
   }
   });
 }

Вот и все, теперь у нас есть текстовое поле, которое можем таскать по всему окну. Ах да, только нужно вызвать этот метод для текстового поля.


private Label createLabel(){
   . . .
   addTranslateListener(label); // вот тут норм будет.
   returnlabel;
}

И как вы могли заметить, этот метод будет работать не только для текстовых полей, а и вообще для всех классов, которые пошли от Node.

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

Как вариант можно сделать так:


for(int i =0; i < 13; i++) {
    root.getChildren().add(createLabel());
  }

И в результате можно слепить что-то такое:

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

Для этого нужно немного изменить наш метод добавления слушателей:

После изменений имеем:


private void addTranslateListener(final Node node) {
         
   node.setOnMousePressed(new EventHandler() {
             
   @Override
   public void handle(MouseEvent mouseEvent) {
       delta = new Vec2f((float) (mouseEvent.getSceneX() - node.getLayoutX()),
 (float) (mouseEvent.getSceneY() - node.getLayoutY()));
       Main.this.node = node;
       if (mouseEvent.getButton() == MouseButton.SECONDARY){
           isRotate = true;
       }
   }
   });
 
   node.setOnMouseReleased(new EventHandler() {
           
   @Override
   public void handle(MouseEvent mouseEvent) {
       Main.this.node = null;
       isRotate = false;
   }
   });
 
       
   node.setOnMouseDragged(new EventHandler() {
           
   @Override
           
   public void handle(MouseEvent mouseEvent) {
      if (node != null ) {
         if (isRotate) {
 // подсчет нового угла основуется на подсчета угла между двома векторами
// это несложная математика, и поэтому тут должно быть все понятно)
           double dx1 = mouseEvent.getSceneX() - node.getLayoutX();
           double dy1 = mouseEvent.getSceneY() - node.getLayoutY();
           double l = Math.sqrt(dx1 *dx1 + dy1 *dy1);
           dx1 /= l; // нормализация
           dy1 /= l; // вектора
 
           doubleangle = PI/2; // за второй вектор было взято 
           double dx2 = sin(angle);      // единичный вектор,                          
           doubledy2 = cos(angle);      // который повернутый на 90 градусов
                                
           double cosA = dx1 * dx2 + dy1 * dy2;               
           angle = acos(cosA);
                       
      if (dy1 < 0) angle = PI - angle ;
           node.setRotate(angle / PI * 180); // из радиан в градусы
         }
 else {
           node.setLayoutX(mouseEvent.getSceneX() - delta.x);
           node.setLayoutY(mouseEvent.getSceneY() - delta.y);                   
}
     }
   }
   });
 }

Запускаем, и лепим опять, вот что я получил в этот раз. Если ты дочитал сюда, а не пошел листать дальше новостную ленту, + 100 к карме тебе, и мою благодарность.

Вот и все, надеюсь кому-то эта статья понравилась, и это будет тогда только начало)

Если Вам понравилась статья, проголосуйте за нее

Голосов: 39  loading...
profesor   Heorhi_Puhachou   StudentS   linnenson   Agaliarept   dazerty   Sergey_Lakhnov   busikpk   FLEX   Byte_Runchik   Alex_X_x   chernichenko   un1acker   kozak_dp   bohdansh   Beomage   kkooll99   marina_5   Sidoroff   RabbitInq   Venedey   infoLil   SamTan   kerradus   Dannik   IvanovKirill   dimonhome   adep7y   Metifikys   piegas   vvm64   pupsik999   Yunki   jo1nsaint   alexlevor   Ivanradist   stasyan72   RomanPolosmak   Acdem