JavaFX2.0开发桌面应用

跟風遠走 提交于 2020-08-13 23:00:49

目录结构

在JavaFX引用中,启动类、fxml和Controller类一一对应.Main作为登录页的启动类,Index则作为首页的启动类。fxml的元素使用fx:id=“”后,在Controller中通过@FXML注解获取该对象。

启动类包含登录和主页,共用一个stage,通过切换scene方式实现页面跳转。同时,通过把Main的引用传递给其他Controller,实现启动类和Controller的数据交互。

package com.test;

import com.bohhom.temperature.controller.IndexController;
import com.bohhom.temperature.controller.LoginController;
import com.bohhom.temperature.model.ClientLoginResultDTO;
import com.bohhom.temperature.model.ImagePaths;
import com.bohhom.temperature.model.ImageVideoModel;
import com.bohhom.temperature.client.Client;
import com.bohhom.temperature.model.LoginModel;
import com.bohhom.temperature.utils.PropertyUtil;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import org.apache.log4j.Logger;

import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

public class Main extends Application {

    private static final Logger logger = Logger.getLogger(Main.class);

    private Stage stage;

    private final double CLIENT_WIDTH = 1000;

    private final double CLIENT_HEIGHT = 750;

    private LoginModel loginModel;

    public static ImageVideoModel imageVideoModel;
    //缓存当前页图片
    public static List<String> imageList;

    public static ImagePaths  imagePaths = new ImagePaths();

    private ClientLoginResultDTO clientLoginResult;
    //current image
    public static String imagePath = null;

    public static ImageView videoClip;

    @Override
    public void start(Stage primaryStage) throws Exception {
        stage = primaryStage;
        //Parent root = FXMLLoader.load(getClass().getResource("com/bohhom/temperature/fxml/login.fxml"));
        stage.setTitle("ST Engineering Temperature Scanning");
        //进入登录界面
        openLogin();
        stage.show();
    }

    public void openLogin() {
        try {
            LoginController login = (LoginController) replaceSceneContent("fxml/login.fxml");
            login.setApp(this);
            login.init();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void openIndex() {
        try {
            IndexController index = (IndexController) replaceSceneContent("fxml/index.fxml");
            index.setApp(this);
            index.init();
            stage.setFullScreen(true);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private Initializable replaceSceneContent(String fxml) throws Exception {
        FXMLLoader loader = new FXMLLoader();
        InputStream in = Main.class.getResourceAsStream(fxml);
        loader.setBuilderFactory(new JavaFXBuilderFactory());
        loader.setLocation(Main.class.getResource(fxml));
        AnchorPane page;
        try {
            page = (AnchorPane) loader.load(in);
        } finally {
            in.close();
        }
        Scene scene = new Scene(page, CLIENT_WIDTH, CLIENT_HEIGHT);
        stage.setScene(scene);
        stage.sizeToScene();
        return (Initializable) loader.getController();
    }

    public LoginModel getLoginModel() {
        return loginModel;
    }

    public void setLoginModel(LoginModel loginModel) {
        this.loginModel = loginModel;
    }

    public ClientLoginResultDTO getClientLoginResult() {
        return clientLoginResult;
    }

    public void setClientLoginResult(ClientLoginResultDTO clientLoginResult) {
        this.clientLoginResult = clientLoginResult;
    }

    public ImageVideoModel getImageVideoModel() {
        return imageVideoModel;
    }

    public void setImageVideoModel(ImageVideoModel imageVideoModel) {
        this.imageVideoModel = imageVideoModel;
    }

    public static String getImagePath() {
        return imagePath;
    }

    public static void setImagePath(String imagePath) {
        Main.imagePath = imagePath;
    }

    public static List<String> getImageList() {
        return imageList;
    }

    public static ImageView getVideoClip() {
        return videoClip;
    }

    public static void setVideoClip(ImageView videoClip) {
        Main.videoClip = videoClip;
    }

    public Stage getStage() {
        return stage;
    }

    public void setStage(Stage stage) {
        this.stage = stage;
    }


    public static void main(String[] args) {
        try {
            launch(args);
        } catch (Exception e) {
            logger.error(Arrays.toString(args), e);
        }

    }
}

屏幕自适应

在javaFX中,每个元素有初始宽高和坐标(layoutX,layoutY),在实际应用后,往往需要全屏显示,此时需要对布局做自适应的适配。

在javaFX中,水平的自适应可以使用HBox布局,从左到右横向布局,通过子元素的HBox.hgrow="ALWAYS"来自适应整行。

 <HBox fx:id="contentBox" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="81.0" prefWidth="1048.0" style="-fx-background-color: #000;">
         <children>
            <Label fx:id="titleLabel" maxWidth="Infinity" prefHeight="81.0" prefWidth="592.0" text="ST Engineering  Temperatur Scanning" textFill="WHITE" HBox.hgrow="ALWAYS">
               <font>
                  <Font size="28.0" />
               </font>
               <HBox.margin>
                  <Insets left="20.0" />
               </HBox.margin>
               <padding>
                  <Insets bottom="10.0" />
               </padding>
            </Label>
            <Pane fx:id="imgPane" maxWidth="Infinity" prefHeight="81.0" prefWidth="391.0" styleClass="imgBack" HBox.hgrow="ALWAYS" />
         </children>
      </HBox>

但是对于高度的自适应,以上方法就不适用了。 纵向自适应使用监听器来实现,在Controller里面增加init()方法进行初始化监听屏幕尺寸变化。首先计算出宽度和高度的比值后,将元素的宽、高、layoutX/layoutY分别乘以对应的比值,.对于Label元素,还要对字体进行放大。这样尺寸变化之后,就能以相同比例显示出来。

application.getStage().widthProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                BigDecimal b = new BigDecimal(newValue.doubleValue() / oldValue.doubleValue());
                double proportion = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                stageWidthPropertyChangeEvent(proportion);
            }
        });
        application.getStage().heightProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                BigDecimal b = new BigDecimal(newValue.doubleValue() / oldValue.doubleValue());
                double proportion = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                stageHeightPropertyChangeEvent(proportion);
            }
        });
		
		
		public void stageHeightPropertyChangeEvent(double proportion) {
        //图片轮播高度自适应
        LayoutUtil.adaptHBoxHeight(imgBox, proportion);
        LayoutUtil.adaptHBoxLayoutY(imgBox, proportion);
        LayoutUtil.adaptVBoxHeight(leftArrow, proportion);
        double adaptImageViewHeight = LayoutUtil.adaptImageViewHeight(img1, proportion);
        //更新静态常量值
        Constants.TOP_IMG_WIDTH = adaptImageViewHeight;
        double img1PrefWidth = img1.getFitWidth();
        LayoutUtil.adaptImageViewHeight(img2, proportion);
        LayoutUtil.adaptImageViewHeight(img3, proportion);
        LayoutUtil.adaptImageViewHeight(img4, proportion);
        LayoutUtil.adaptImageViewHeight(img5, proportion);
        ImageMoveUtil.updateImageArea(img1PrefWidth, adaptImageViewHeight);
        LayoutUtil.adaptVBoxHeight(rightArrow, proportion);
        //顶部标题HBox高度自适应
        LayoutUtil.adaptAnchorPaneHeight(titlePane, proportion);
        LayoutUtil.adaptAnchorPaneLayoutY(titlePane, proportion);
        LayoutUtil.adaptLabelLayoutY(title, proportion);
        LayoutUtil.adaptLabelLayoutY(username, proportion);
        //异常文字HBox高度自适应
        LayoutUtil.adaptHBoxHeight(exceptionPane, proportion);
        LayoutUtil.adaptHBoxLayoutY(exceptionPane, proportion);
        LayoutUtil.adaptLabelLayoutY(exceptionLabel, proportion);
        //直播HBox高度自适应
        LayoutUtil.adaptHBoxHeight(videoBox, proportion);
        LayoutUtil.adaptHBoxLayoutY(videoBox, proportion);
        LayoutUtil.adaptVBoxHeight(videoClipBox, proportion);
        // LayoutUtil.adaptPaneHeight(videoClipBoxPane, proportion);
        // LayoutUtil.adaptPaneLayoutY(videoClipBoxPane, proportion);
        double adaptImageViewHeight1 = LayoutUtil.adaptImageViewHeight(videoClip, proportion);
        Constants.VIDEO_CLIP_HEIGHT = (int) adaptImageViewHeight1;
        //设置选中图片宽度
        double abnormalImageHeight = LayoutUtil.adaptImageViewHeight(abnormalImage, proportion);
        Constants.SELECTED_IMG_HEIGHT = (int) abnormalImageHeight;
        //修改已有图片布局
        String imagePath = Main.getImagePath();
        if (imagePath != null && !"".equals(imagePath)) {
            Image image = new Image(imagePath, Constants.SELECTED_IMG_WIDTH, Constants.SELECTED_IMG_HEIGHT, false, false);
            abnormalImage.setImage(image);
        }
        LayoutUtil.adaptVBoxHeight(dataBox, proportion);
        LayoutUtil.adaptPaneHeight(dataPaneBox, proportion);
        LayoutUtil.adaptVBoxLayoutY(dataBox, proportion);
        LayoutUtil.adaptPaneLayoutY(dataPaneBox, proportion);
        LayoutUtil.adaptVBoxHeight(dataPaneVBox, proportion);
        LayoutUtil.adaptVBoxLayoutY(dataPaneVBox, proportion);
        LayoutUtil.adaptPaneHeight(defaultPane, proportion);
        LayoutUtil.adaptPaneHeight(fullPane, proportion);
        LayoutUtil.adaptPaneLayoutY(defaultPane, proportion);
        LayoutUtil.adaptPaneLayoutY(fullPane, proportion);
        LayoutUtil.adaptLabelLayoutY(chooseLabel, proportion);
        LayoutUtil.adaptLabelLayoutY(zoomUpLabel, proportion);
        LayoutUtil.adaptLabelLayoutY(testTep, proportion);
        LayoutUtil.adaptLabelLayoutY(testDate, proportion);
        LayoutUtil.adaptTextLayoutY(tepText, proportion);
        LayoutUtil.adaptTextLayoutY(timeText, proportion);
        LayoutUtil.adaptJFXButtonLayoutY(informButton, proportion);
        LayoutUtil.adaptJFXButtonLayoutY(getbackButton, proportion);
        LayoutUtil.adaptJFXButtonLayoutY(normalButton, proportion);

        LayoutUtil.adaptTextFieldLayoutY(otherSymptom1, proportion);
        LayoutUtil.adaptTextFieldHeight(otherSymptom1, proportion);
        LayoutUtil.adaptTextFieldLayoutY(recheckTep1, proportion);
        LayoutUtil.adaptTextFieldHeight(recheckTep1, proportion);

        LayoutUtil.adaptJFXToggleNodeLayoutY(toggleNodeDown, proportion);
        LayoutUtil.adaptChoiceBoxLayoutY(classId1, proportion);
        LayoutUtil.adaptChoiceBoxHeight(classId1, proportion);

        LayoutUtil.adaptTextFieldLayoutY(otherSymptom2, proportion);
        LayoutUtil.adaptTextFieldHeight(otherSymptom2, proportion);

        LayoutUtil.adaptTextFieldLayoutY(name2, proportion);
        LayoutUtil.adaptTextFieldHeight(name2, proportion);

        LayoutUtil.adaptTextFieldLayoutY(classNumber2, proportion);
        LayoutUtil.adaptTextFieldHeight(classNumber2, proportion);

        LayoutUtil.adaptTextFieldLayoutY(recheckTep2, proportion);
        LayoutUtil.adaptTextFieldHeight(recheckTep2, proportion);

        LayoutUtil.adaptJFXToggleNodeLayoutY(toggleNodeUp, proportion);
        LayoutUtil.adaptChoiceBoxLayoutY(classId2, proportion);
        LayoutUtil.adaptChoiceBoxHeight(classId2, proportion);

        //底部HBox高度自适应
        LayoutUtil.adaptHBoxHeight(bottomPane, proportion);
        LayoutUtil.adaptHBoxLayoutY(bottomPane, proportion);

        //底部文字
        LayoutUtil.adaptLabelLayoutY(cameraIdLabel, proportion);
        LayoutUtil.adaptLabelLayoutY(schoolNameLabel, proportion);
        LayoutUtil.adaptLabelLayoutY(cameraPositionLabel, proportion);
    }

这里面可以单独封装一个布局工具类LayoutUtil,对常用组件进行自适应。

package com.bohhom.temperature.utils;

import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXToggleNode;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.scene.text.Font;
import javafx.scene.text.Text;

public class LayoutUtil {
    /**
     * HBox高度自适应
     *
     * @param hBox
     * @param proportion
     */
    public static void adaptHBoxHeight(HBox hBox, double proportion) {
        double prefHeight = hBox.getPrefHeight();
        hBox.prefHeightProperty().unbind();
        hBox.setPrefHeight(prefHeight * proportion);
    }

    /**
     * HBox高度自适应
     *
     * @param hBox
     * @param proportion
     */
    public static void adaptHBoxWidth(HBox hBox, double proportion) {
        double prefWidth = hBox.getPrefWidth();
        hBox.prefWidthProperty().unbind();
        hBox.setPrefWidth(prefWidth * proportion);
    }


    /**
     * HBox layoutX自适应
     *
     * @param imgBox
     * @param proportion
     */
    public static void adaptHBoxLayoutX(HBox imgBox, double proportion) {
        double layoutX = imgBox.getLayoutX();
        imgBox.layoutXProperty().unbind();
        imgBox.setLayoutX(layoutX * proportion);
    }

    /**
     * HBox layoutY自适应
     *
     * @param imgBox
     * @param proportion
     */
    public static void adaptHBoxLayoutY(HBox imgBox, double proportion) {
        double layoutY = imgBox.getLayoutY();
        imgBox.layoutYProperty().unbind();
        imgBox.setLayoutY(layoutY * proportion);
    }

    /**
     * VBox高度自适应
     *
     * @param vBox
     * @param proportion
     */
    public static void adaptVBoxHeight(VBox vBox, double proportion) {
        double prefHeight = vBox.getPrefHeight();
        vBox.prefHeightProperty().unbind();
        vBox.setPrefHeight(prefHeight * proportion);
    }

    /**
     * VBox宽度自适应
     *
     * @param vBox
     * @param proportion
     */
    public static void adaptVBoxWidth(VBox vBox, double proportion) {
        double prefWidth = vBox.getPrefWidth();
        vBox.prefWidthProperty().unbind();
        vBox.setPrefWidth(prefWidth * proportion);
    }

    /**
     * VBox layoutY自适应
     *
     * @param imgBox
     * @param proportion
     */
    public static void adaptVBoxLayoutY(VBox imgBox, double proportion) {
        double layoutY = imgBox.getLayoutY();
        imgBox.layoutYProperty().unbind();
        imgBox.setLayoutY(layoutY * proportion);
    }

    /**
     * VBox layoutY自适应
     *
     * @param imgBox
     * @param proportion
     */
    public static void adaptVBoxLayoutX(VBox imgBox, double proportion) {
        double layoutX = imgBox.getLayoutX();
        imgBox.layoutXProperty().unbind();
        imgBox.setLayoutX(layoutX * proportion);
    }

    /**
     * ImageView高度自适应
     *
     * @param imgView
     * @param proportion
     */
    public static double adaptImageViewHeight(ImageView imgView, double proportion) {
        double img1PrefHeight = imgView.getFitHeight();
        imgView.fitHeightProperty().unbind();
        imgView.setFitHeight(img1PrefHeight * proportion);
        return img1PrefHeight * proportion;
    }

    /**
     * ImageView宽度自适应
     *
     * @param imgView
     * @param proportion
     */
    public static double adaptImageViewWidth(ImageView imgView, double proportion) {
        double img1PrefWidth = imgView.getFitWidth();
        imgView.fitWidthProperty().unbind();
        imgView.setFitWidth(img1PrefWidth * proportion);
        return img1PrefWidth * proportion;
    }

    /**
     * @param anchorPane
     * @param proportion
     */
    public static void adaptAnchorPaneHeight(AnchorPane anchorPane, double proportion) {
        double prefHeight = anchorPane.getPrefHeight();
        anchorPane.prefHeightProperty().unbind();
        anchorPane.setPrefHeight(prefHeight * proportion);
    }

    /**
     * @param anchorPane
     * @param proportion
     */
    public static void adaptAnchorPaneLayoutY(AnchorPane anchorPane, double proportion) {
        double layoutY = anchorPane.getLayoutY();
        anchorPane.layoutYProperty().unbind();
        anchorPane.setLayoutY(layoutY * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptLabelHeight(Label label, double proportion) {
        double prefHeight = label.getPrefHeight();
        label.prefHeightProperty().unbind();
        label.setPrefHeight(prefHeight * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptLabelWidth(Label label, double proportion) {
        double prefWidth = label.getPrefWidth();
        label.prefWidthProperty().unbind();
        label.setPrefWidth(prefWidth * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptLabelLayoutY(Label label, double proportion) {
        double layoutY = label.getLayoutY();
        label.layoutYProperty().unbind();
        label.setLayoutY(layoutY * proportion);
        Font font = label.getFont();
        double size = font.getSize();
        Font changedFont = Font.font("System", size * proportion);
        label.setFont(changedFont);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptLabelLayoutX(Label label, double proportion) {
        double layoutX = label.getLayoutX();
        label.layoutXProperty().unbind();
        label.setLayoutX(layoutX * proportion);
    }

    /**
     * VBox宽度自适应
     *
     * @param pane
     * @param proportion
     */
    public static void adaptPaneWidth(Pane pane, double proportion) {
        double prefWidth = pane.getPrefWidth();
        pane.prefWidthProperty().unbind();
        pane.setPrefWidth(prefWidth * proportion);
    }

    /**
     * VBox宽度自适应
     *
     * @param pane
     * @param proportion
     */
    public static void adaptPaneHeight(Pane pane, double proportion) {
        double prefHeight = pane.getPrefHeight();
        pane.prefHeightProperty().unbind();
        pane.setPrefHeight(prefHeight * proportion);
    }

    /**
     * VBox layoutY自适应
     *
     * @param pane
     * @param proportion
     */
    public static void adaptPaneLayoutY(Pane pane, double proportion) {
        double layoutY = pane.getLayoutY();
        pane.layoutYProperty().unbind();
        pane.setLayoutY(layoutY * proportion);
    }

    /**
     * VBox layoutY自适应
     *
     * @param pane
     * @param proportion
     */
    public static void adaptPaneLayoutX(Pane pane, double proportion) {
        double layoutX = pane.getLayoutX();
        pane.layoutXProperty().unbind();
        pane.setLayoutX(layoutX * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptTextLayoutY(Text label, double proportion) {
        double layoutY = label.getLayoutY();
        label.layoutYProperty().unbind();
        label.setLayoutY(layoutY * proportion);
        Font font = label.getFont();
        double size = font.getSize();
        Font changedFont = Font.font("System", size * proportion);
        label.setFont(changedFont);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptTextLayoutX(Text label, double proportion) {
        double layoutX = label.getLayoutX();
        label.layoutXProperty().unbind();
        label.setLayoutX(layoutX * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptJFXButtonLayoutY(JFXButton label, double proportion) {
        double layoutY = label.getLayoutY();
        label.layoutYProperty().unbind();
        label.setLayoutY(layoutY * proportion);
        Font font = label.getFont();
        double size = font.getSize();
        Font changedFont = Font.font("System", size * proportion);
        label.setFont(changedFont);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptJFXButtonLayoutX(JFXButton label, double proportion) {
        double layoutX = label.getLayoutX();
        label.layoutXProperty().unbind();
        label.setLayoutX(layoutX * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptTextFieldLayoutY(TextField label, double proportion) {
        double layoutY = label.getLayoutY();
        label.layoutYProperty().unbind();
        label.setLayoutY(layoutY * proportion);
       /* Font font = label.getFont();
        double size = font.getSize();
        Font changedFont = Font.font("System", size * proportion);
        label.setFont(changedFont);*/
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptTextFieldLayoutX(TextField label, double proportion) {
        double layoutX = label.getLayoutX();
        label.layoutXProperty().unbind();
        label.setLayoutX(layoutX * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptJFXToggleNodeLayoutY(JFXToggleNode label, double proportion) {
        double layoutY = label.getLayoutY();
        label.layoutYProperty().unbind();
        label.setLayoutY(layoutY * proportion);
       /* Font font = label.getFont();
        double size = font.getSize();
        Font changedFont = Font.font("System", size * proportion);
        label.setFont(changedFont);*/
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptChoiceBoxLayoutX(ChoiceBox label, double proportion) {
        double layoutX = label.getLayoutX();
        label.layoutXProperty().unbind();
        label.setLayoutX(layoutX * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptChoiceBoxLayoutY(ChoiceBox label, double proportion) {
        double layoutY = label.getLayoutY();
        label.layoutYProperty().unbind();
        label.setLayoutY(layoutY * proportion);
       /* Font font = label.getFont();
        double size = font.getSize();
        Font changedFont = Font.font("System", size * proportion);
        label.setFont(changedFont);*/
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptJFXToggleNodeLayoutX(JFXToggleNode label, double proportion) {
        double layoutX = label.getLayoutX();
        label.layoutXProperty().unbind();
        label.setLayoutX(layoutX * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptTextFieldWidth(TextField label, double proportion) {
        double h = label.getPrefWidth();
        label.prefWidthProperty().unbind();
        label.setPrefWidth(h * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptTextFieldHeight(TextField label, double proportion) {
        double h = label.getPrefHeight();
        label.prefHeightProperty().unbind();
        label.setPrefHeight(h * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptChoiceBoxWidth(ChoiceBox label, double proportion) {
        double h = label.getPrefWidth();
        label.prefWidthProperty().unbind();
        label.setPrefWidth(h * proportion);
    }

    /**
     * @param label
     * @param proportion
     */
    public static void adaptChoiceBoxHeight(ChoiceBox label, double proportion) {
        double h = label.getPrefHeight();
        label.prefHeightProperty().unbind();
        label.setPrefHeight(h * proportion);
    }

    /**
     * HBox高度自适应
     *
     * @param pane
     * @param proportion
     */
    public static void adaptGridPaneHeight(GridPane pane, double proportion) {
        double prefHeight = pane.getPrefHeight();
        pane.prefHeightProperty().unbind();
        pane.setPrefHeight(prefHeight * proportion);
    }

    /**
     * HBox高度自适应
     *
     * @param pane
     * @param proportion
     */
    public static void adaptGridPaneWidth(GridPane pane, double proportion) {
        double prefWidth = pane.getPrefWidth();
        pane.prefWidthProperty().unbind();
        pane.setPrefWidth(prefWidth * proportion);
    }

    /**
     * HBox高度自适应
     *
     * @param pane
     * @param proportion
     */
    public static void adaptGridPaneLayoutY(GridPane pane, double proportion) {
        double layoutY = pane.getLayoutY();
        pane.layoutYProperty().unbind();
        pane.setLayoutX(layoutY * proportion);
    }

    /**
     * HBox高度自适应
     *
     * @param pane
     * @param proportion
     */
    public static void adaptGridPaneLayoutX(GridPane pane, double proportion) {
        double layoutX = pane.getLayoutX();
        pane.layoutXProperty().unbind();
        pane.setLayoutX(layoutX * proportion);
    }

}

ImageView结合HBox自适应显示流程

  1. 设置ImageView初始宽高(全局变量)
  2. HBox整行内容宽高改变后,使用监听器修改初始宽高
  3. 图片替换时,ImageView.setImage(new Image(url)),Image不需要设置宽高,否则会导致图片模糊

rtsp视频直播

方案一(JavaFX中不可行)

使用海康威视Java SDK进行视频预览(https://open.hikvision.com/docs/afac12355aeaa9ad944482cede1116d9)

参考代码

这里视频预览SDK本身是正常的,问题是预览的窗口必须是java.awt.Panel类或者java.awt.Canvas类等heightWeight组件。而在javaFX2.0中只可以通过SwingNode集成lightWeight组件(如javax.swing.JPanel,javax.swing.JButton等) ,无法集成java.awt.Panel这样的heightWeight组件。如果你用JPanel嵌套一个java.awt.Panel,虽然运行不报错,实际上javaFX并不会渲染java.awt.Panel的内容。原因是** The hierarchy of components contained in the JComponent instance should not contain any heavyweight components, otherwise SwingNode may fail to paint it.**

其他相关JavaFX集成java.awt.Panel的资料

https://docs.oracle.com/javase/8/javafx/api/javafx/embed/swing/SwingNode.html

https://stackoverflow.com/questions/29390902/awt-panel-not-getting-rendered-in-jfx

https://stackoverflow.com/questions/4809713/embed-hwnd-window-handle-in-a-jpanel

https://stackoverflow.com/questions/38691580/adding-swingnode-to-javafx

https://stackoverflow.com/questions/23712938/javafx-awt-canvas

https://stackoverflow.com/questions/4809713/embed-hwnd-window-handle-in-a-jpanel

方案二

在JavaFx2.0中,不支持rtsp直播,只支持MP3,HTTP等协议。所以可以换个思路,使用图片来实现直播。用javacv来对视频源进行截图,然后,循环在ImageView中渲染实时图片。可以用公网免费rtsp源进行测试(rtsp://www.mym9.com/101065?from=2019-06-28/01:12:13)

引入javacv依赖,版本1.3.1

		<dependency>
			<groupId>org.bytedeco</groupId>
			<artifactId>javacv-platform</artifactId>
			<version>1.3.1</version>
		</dependency>

rtsp视频直播通过以下工具类实现,在使用时只需要初始化首页后,开启一个线程运行即可。

   //视频截图线程池
    private ThreadPoolExecutor clippingThreadPool;
	
	 clippingThreadPool = ThreadPoolHolder.getHolder().getThreadPool();
     clippingThreadPool.execute(new FFmpegFXImageDecoder());
abnormalImage.setImage(new Image(is, Constants.VIDEO_CLIP_WIDTH, Constants.VIDEO_CLIP_HEIGHT, false, false))

javaFX中ImageView设置内容时,如果设置宽高,会导致图片模糊,这里只需要传入InputStream 一个参数就可以了。

直播代码:

核心类

辅助类

打包

打包exe格式

配置里面title不能写中文 否则打包会报错

Build-Build artifacts - rebuild

打包jar格式

assembly.xml

<assembly>
    <id>assembly</id>
    <formats>
        <format>zip</format>
    </formats>
    <includeBaseDirectory>true</includeBaseDirectory>
    <baseDirectory>client-1.0.0</baseDirectory>
    <fileSets>
        <fileSet>
            <!--源目录-->
            <directory>target</directory>
            <!--放在哪-->
            <outputDirectory>/</outputDirectory>
            <!--代码的jar包-->
            <includes>
                <!--<include>tms-device-elevator-1.0-SNAPSHOT-jar-with-dependencies.jar</include>-->
                <include>*.jar</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>bin</directory>
            <outputDirectory>bin</outputDirectory>
            <!--设置权限-->
            <fileMode>0755</fileMode>
        </fileSet>
        <!--指定需要包含的其他文件-->
        <fileSet>
            <directory>conf</directory>
            <outputDirectory>conf</outputDirectory>
            <!--设置权限-->
            <fileMode>0644</fileMode>
        </fileSet>
        <fileSet>
            <directory>pic</directory>
            <outputDirectory>pic</outputDirectory>
            <fileMode>0644</fileMode>
        </fileSet>
        <fileSet>
            <directory>lib</directory>
            <outputDirectory>lib</outputDirectory>
            <!--设置权限-->
            <fileMode>0644</fileMode>
        </fileSet>
        <!--<fileSet>
            <directory>doc</directory>
            <outputDirectory>doc</outputDirectory>
            &lt;!&ndash;设置权限&ndash;&gt;
            <fileMode>0644</fileMode>
        </fileSet>
        -->
    </fileSets>
    <!--指定把哪些依赖包放进去,如果不指定,则所有的依赖都会打入-->
    <dependencySets>
        <dependencySet>
            <outputDirectory>lib</outputDirectory>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>
</assembly>

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	
    <groupId>test</groupId>
    <artifactId>Client</artifactId>
    <version>1.0.0</version>

    <name>client</name>
    <description>客户端</description>
	<packaging>jar</packaging>
    
    <properties>
		<httpclient.version>4.5.5</httpclient.version>
		<fastjson.version>1.2.68</fastjson.version>
	</properties>

	<dependencies>
		<!-- apache httpclient组件 -->
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>${httpclient.version}</version>
		</dependency>
		<dependency>
			<groupId>org.jsoup</groupId>
			<artifactId>jsoup</artifactId>
			<version>1.11.3</version>
		</dependency>
		<dependency>
			<groupId>com.jfoenix</groupId>
			<artifactId>jfoenix</artifactId>
			<version>8.0.8</version>
		</dependency>
		<!-- 阿里JSON解析器 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>${fastjson.version}</version>
		</dependency>

		<dependency>
			<groupId>test</groupId>
			<artifactId>jna</artifactId>
			<version>1.0</version>
		</dependency>

		<dependency>
			<groupId>test</groupId>
			<artifactId>jna-examples</artifactId>
			<version>1.0</version>
		</dependency>

		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>

		<dependency>
			<groupId>org.bytedeco</groupId>
			<artifactId>javacv-platform</artifactId>
			<version>1.3.1</version>
		</dependency>



	</dependencies>

	<build>
		<resources>
			<resource>
				<directory>lib</directory>
				<targetPath>lib/</targetPath>
				<includes>
					<include>**/*.dll</include>
					<include>**/*.jar</include>
					<include>**/*.properties</include>
				</includes>
			</resource>
		</resources>
        <plugins>
			<plugin>
				<groupId>com.zenjava</groupId>
				<artifactId>javafx-maven-plugin</artifactId>
				<version>8.8.3</version>
				<configuration>
					<mainClass>com.bohhom.temperature.Main</mainClass>
				</configuration>
			</plugin>
			<!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<classesDirectory>target/classes/</classesDirectory>
					<archive>
						<manifest>
							<mainClass>com.bohhom.temperature.Main</mainClass>
							<!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
							<useUniqueVersions>false</useUniqueVersions>
							<addClasspath>true</addClasspath>
							<classpathPrefix>lib/</classpathPrefix>
						</manifest>
						<manifestEntries>
							<Class-Path>lib/jar/jna.jar</Class-Path>
						</manifestEntries>
					</archive>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-assembly-plugin</artifactId>
				<version>3.2.0</version>
				<executions>
					<execution>
						<id>make-assembly</id>
						<!-- 绑定到package生命周期 -->
						<phase>package</phase>
						<goals>
							<!-- 只运行一次 -->
							<goal>single</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<descriptors>
						<descriptor>assembly.xml</descriptor>
					</descriptors>
				</configuration>
			</plugin>
        </plugins>
    </build>


	<!--<repositories>
		<repository>
			<id>public</id>
			<name>aliyun nexus</name>
			<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>public</id>
			<name>aliyun nexus</name>
			<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>-->

</project>

windows下部署

在windows下由于系统编码不是UTF-8,javaFX2.0中的ChoiceBox显示中文乱码,所以通过在启动参数里设置编码方式UTF-8解决此问题

@echo off
echo.
echo [信息] 运行Web工程。
echo.

cd %~dp0
cd ..

set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./dump/hprof_log/heapDump.hprof -Dfile.encoding=utf-8

java -jar %JAVA_OPTS% client-1.0.0.jar

cd bin
pause

issues

swscaler deprecated pixel format

调整日志级别,阻止警告

 avutil.av_log_set_level(AV_LOG_ERROR);

参考文章

https://github.com/bytedeco/javacv/issues/1283

https://github.com/bytedeco/javacv/issues/780

https://github.com/001ItSky/videoservice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!