目录结构
在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自适应显示流程
- 设置ImageView初始宽高(全局变量)
- HBox整行内容宽高改变后,使用监听器修改初始宽高
- 图片替换时,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>
<!–设置权限–>
<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
来源:oschina
链接:https://my.oschina.net/odetteisgorgeous/blog/4282426