zoukankan      html  css  js  c++  java
  • JavaFX入门:简单Demo-学习NetBeans开发平台

    零、 最终目标

    通过两种方式(纯代码控制、FXML),实现一个简单的登录界面:

     
    Paste_Image.png

    涉及到的控件:
    文本(Text,动态显示内容)、标签(Label,显示文本)、文本域(TextField,用户交互输入)、按钮(Button,登录点击)

    一、 控件通过Code动态添加实现方法

    1、 新建项目

    新建JavaFXLoginDemo项目,具体新建方法参见前篇:
    JavaFX开发环境:NetBeans开发环境搭建

    完成项目新建后,进入开发正题。

    入口参数:

    public class JavaFXLoginDemo extends Application {
        
        @Override
        public void start(Stage primaryStage) {
        }
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    2、 布局方式

    JavaFX的UI控件均摆放在Scene上,一般通过增加控制布局的Panel,并将实际的UI摆放在布局Panel上,有点类似于Android的布局方式。Panel有多种样式,包括了行、列、栈等等,如BorderPaneGridPaneHboxVBox等等。
    本文将使用GridPane进行布局。

    GridPane grid = new GridPane();//网格式布局,由行列网格控制
    grid.setAlignment(Pos.CENTER);//对齐方式,默认靠左对齐,当前设置居中对齐
    grid.setHgap(10);//设置水平间隔
    grid.setVgap(10);//设置垂直间隔
    grid.setPadding(new Insets(25, 25, 25, 25));//设置Padding,顺序是:上、右、下、左
    
    Scene scene = new Scene(grid, 300, 275);//新建Scene,并将网格式Panel置于其中
    primaryStage.setScene(scene);//设置场景
    primaryStage.show();
    
    3、 添加控件
            Text scenetitle = new Text("欢迎标题");
            //scenetitle.setFont(Font.font("Times New Roman", FontWeight.NORMAL, 20));
            grid.add(scenetitle, 0, 0, 2, 1);
    
            //创建Label对象,放到第0列,第1行
            Label userName = new Label("用户名:");
            grid.add(userName, 0, 1);
    
            //创建文本输入框,放到第1列,第1行
            TextField userTextField = new TextField();
            grid.add(userTextField, 1, 1);
    
            Label pw = new Label("密 码:");
            grid.add(pw, 0, 2);
    
            PasswordField pwBox = new PasswordField();
            grid.add(pwBox, 1, 2);
    
            Button btn = new Button("登录");
            HBox hbBtn = new HBox(10);
            hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
            hbBtn.getChildren().add(btn);//将按钮控件作为子节点
            grid.add(hbBtn, 1, 4);//将HBox pane放到grid中的第1列,第4行
    
            final Text actiontarget = new Text();//增加用于显示信息的文本
            grid.add(actiontarget, 1, 6);
    
    4、 添加处理事件

    只有一个按钮需要事件处理:

            btn.setOnAction(new EventHandler<ActionEvent>() {//注册事件handler
                @Override
                public void handle(ActionEvent e) {
                    actiontarget.setFill(Color.FIREBRICK);//将文字颜色变成 firebrick red
                    actiontarget.setText("登录中...");
                }
            });
    
    5、 添加样式CSS

    步骤一:新建CSS文件:
    在包上右击:


     
    Paste_Image.png
     
    Paste_Image.png

    输入文件名Login.css,完成样式表文件的创建:

     
    Paste_Image.png

    样式表中定义的内容,主要用在控件的样式控制上,需要在UI中应用。样式表需要应用到Root容器中:

    scene.getStylesheets().add(JavaFXLoginDemo.class.getResource("Login.css").toExternalForm());
    

    设置后,将会在JavaFXLoginDemo.class相对路径下寻找给出的样式表Login.css,并应用到scene中。
    步骤二:添加一张背景图,到当前包路径下:

     
    Paste_Image.png

    步骤三:添加CSS样式控制

    //根元素样式布局,设置背景图
    .root {
       -fx-background-image: url("background.jpg");
    }
    
    //标签控件样式
    .label {
       -fx-font-size: 12px;
       -fx-font-weight: bold;
       -fx-text-fill: #333333;
       -fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 );
    }
    //给Button增加样式
    .button {
       -fx-text-fill: white;
       -fx-font-family: "Arial Narrow";
       -fx-font-weight: bold;
       -fx-background-color: linear-gradient(#61a2b1, #2A5058);
       -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 );
    }
    .button:hover {
       -fx-background-color: linear-gradient(#2A5058, #61a2b1);
    }
    //增加文本效果
    #welcome-text {
       -fx-font-size: 32px;
       -fx-fill: #818181;
       -fx-effect: innershadow( three-pass-box , rgba(0,0,0,0.7) , 6, 0.0 , 0 , 2 );
    }
    //登录点击事件显示效果
    #actiontarget {
       -fx-fill: FIREBRICK;
       -fx-font-weight: bold;
       -fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 );
    }
    

    注意,最后两个是采用了CSS中的ID控制样式,而非Label、Button中针对类型设置的样式,因此需要给目标控件增加ID规则:

            scenetitle.setId("welcome-text");
            actiontarget.setId("actiontarget");
    

    ☆☆☆ 中文字体库应用

    任何事情,涉及到了中文之后,字体库使用有点麻烦。
    (1)新建文件夹,在当前包下建立resources/fonts,如图所示:

     
    Paste_Image.png

    将字体库粘贴进去,一般是ttf文件,Windows常用,Mac可以用,Linux也是兼容的。我粘贴的是微软雅黑和粗体版,在Windows操作系统的系统盘下Windows/Fonts目录下。
    (2)增加fonts.mf文件
    使用“文件”选项卡查看工程:


     
    Paste_Image.png

    fonts.mf内容:

    msyh=/javafxlogindemo/resources/fonts/msyh.ttf
    msyhbd=/javafxlogindemo/resources/fonts/msyhbd.ttf
    hwxk=/javafxlogindemo/resources/fonts/STXINGKA.TTF
    hwcy=/javafxlogindemo/resources/fonts/STCAIYUN.TTF
    

    hwcy:


     
    Paste_Image.png

    hwxk:


     
    Paste_Image.png

    "="前面,是项目使用时的字体名称,即font-family,后面是字体库文件的路径。
    (3)fonts.mf需要在打包时放到jar包的META-INF目录下,因此需要配置NetBeans工程的build.xml文件内容:

    NetBeans工程使用Ant管理项目,配置的build.xml文件,根文件在工程根目录下,具体配置文件在nbproject目录下的build-impl.xml文件中。
    在build.xml中增加如下内容:

        <target name="-post-compile">
            <mkdir dir="${build.classes.dir}/META-INF"/>
            <copy todir="${build.classes.dir}/META-INF" file="fonts.mf"/>
        </target>
    

    完成之后,运行一下项目,在项目目录的dist目录下,可以看到打包的jar包,用压缩文件查看器打开(WinRAR):

     
    Paste_Image.png
     
    Paste_Image.png

    包含了配置文件和字体库文件。
    (4)code中使用:

    import javafx.scene.text.Font;
    
    Font font = Font.font("hwcy", 32);//字体,尺寸,注意不能使用加粗,即FontWeight
    
    
     
    Paste_Image.png

    (5)在CSS样式文件中使用:

    //增加文本效果
    #welcome-text {
       -fx-font-size: 32px;
       -fx-font-family: "hwcy";
       -fx-fill: #818181;
       -fx-effect: innershadow( three-pass-box , rgba(0,0,0,0.7) , 6, 0.0 , 0 , 2 );
    }
    

    注意,-fx-font-weight: bold;加粗不能一起使用,会使字体失效。

    经过上述的配置,中文字体也能够轻松走起啦。

    6、 完成编码,启动项目,运行测试。

    二、 FXML实现界面

    NetBeans实现方法
    1、 新建工程JavaFXLoginFXMLDemo:

    与前一种方法新的工程种类稍有区别,这里选择JavaFX FXML应用程序

     
    Paste_Image.png
     
    Paste_Image.png

    对比一下工程结构,FXML工程多了一些FXML文件和控制器文件:

     
    Paste_Image.png

    新建工程后,立刻运行:

     
    Paste_Image.png

    代码也稍有区别,FXML文件中定义了控件和控制器映射关系等等:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import java.lang.*?>
    <?import java.util.*?>
    <?import javafx.scene.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    
    <AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxloginfxmldemo.FXMLDocumentController">
        <children>
            <Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
            <Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
        </children>
    </AnchorPane>
    
    

    默认生成的FXML样例界面文件中,根容器是一个AnchorPane:

    AnchorPane布局面板可锚定节点于面板的顶、底、左边、右边或中间。当窗口尺寸调整时,相应节点维护它们相对于锚点的位置。节点可被锚定于多个位置,多个节点也可锚定于同一个位置。

    在后面,将要修改实际的布局容器。

    控制器Controller定义了事件处理方法:

    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    package javafxloginfxmldemo;
    
    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Label;
    
    /**
     *
     * @author guorui.he
     */
    public class FXMLDocumentController implements Initializable {
        
        @FXML
        private Label label;
        
        @FXML
        private void handleButtonAction(ActionEvent event) {
            System.out.println("You clicked me!");
            label.setText("Hello World!");
        }
        
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            // TODO
        }    
        
    }
    

    主文件内,与之前的纯代码实现基本类似,但是加载页面的机制稍有不同,这时通过FXML文件加载,搞过Android的人很熟悉:

    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    package javafxloginfxmldemo;
    
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    /**
     *
     * @author guorui.he
     */
    public class JavaFXLoginFXMLDemo extends Application {
        
        @Override
        public void start(Stage stage) throws Exception {
            //通过fxml的UI布局文件加载实际的界面内容
            Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
            
            Scene scene = new Scene(root);
            
            stage.setScene(scene);
            stage.show();
        }
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    由于默认文件名定义的比较弱,我们要自己改一下文件名,这样才能更清晰的展示:

     
    Paste_Image.png

    注意不要忘记修改控制器和FXML的映射,以及主类加载的FXML界面名称。

    2、在FXML文件中,编写界面内容:
    <?xml version="1.0" encoding="UTF-8"?>
    
    //整理引入包
    <?import java.net.*?>
    <?import javafx.geometry.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    <?import javafx.scene.text.*?>
    
    //编写界面
    <GridPane xmlns:fx="http://javafx.com/fxml" 
              fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController" 
              alignment="center" hgap="10" vgap="10">
        <padding>
            <Insets top="25" right="25" bottom="10" left="25"/>
        </padding>
        <Text text="欢迎登录FXML Demo系统"
              GridPane.columnIndex="0" GridPane.rowIndex="0"
              GridPane.columnSpan="2"/>
        <Label text="用户名:"
               GridPane.columnIndex="0" GridPane.rowIndex="1"/>
        <TextField
            GridPane.columnIndex="1" GridPane.rowIndex="1"/>
        <Label text="密  码:"
               GridPane.columnIndex="0" GridPane.rowIndex="2"/>
        <PasswordField fx:id="passwordField"
                       GridPane.columnIndex="1" GridPane.rowIndex="2"/>
        <HBox spacing="10" alignment="bottom_right"
              GridPane.columnIndex="1" GridPane.rowIndex="4">
            <Button text="登录" />
        </HBox>
    
        <Text fx:id="actiontarget"
              GridPane.columnIndex="0" GridPane.columnSpan="2"
              GridPane.halignment="RIGHT" GridPane.rowIndex="6"/>
    </GridPane>
    

    此时,没有添加事件处理,可以试运行:

     
    Paste_Image.png

    大致内容都在了,但是没有样式,没有登录按钮点击处理事件。

    3、 添加处理事件:

    方法一:使用Java处理

    //给Button增加一个事件处理
    <Button text="登录" onAction="#handleSubmitButtonAction"/>
    

    添加之后,会报错:

     
    Paste_Image.png

    需要在控制器中为其添加事件处理:

     
    Paste_Image.png

    会自动的在控制器内添加处理程序:

    package javafxloginfxmldemo;
    
    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Label;
    import javafx.scene.control.PasswordField;
    import javafx.scene.text.Text;
    
    /**
     *
     * @author guorui.he
     */
    public class FXMLLoginDemoDocumentController implements Initializable {
        private Label label;
        @FXML
        private PasswordField passwordField;
        @FXML
        private Text actiontarget;
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            // TODO
        }
        @FXML
        private void handleSubmitButtonAction(ActionEvent event) {
            actiontarget.setText("登录中...");
        }
    }
    

    @FXML注解,可以删除,最好保留,阅读方便。
    添加好处理事件后,点击登录按钮,就会有反应了:

     
    Paste_Image.png

    方法二.1:使用内置JS脚本处理
    <?xml version="1.0" encoding="UTF-8"?>
    <?language javascript?>
    

    添加脚本声明。
    修改Button的事件处理方法(局部代码)

    <GridPane xmlns:fx="http://javafx.com/fxml" 
              fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController" 
              alignment="center" hgap="10" vgap="10">
        <!-- 脚本处理代码 -->
        <fx:script>
            function handleSubmitButtonAction() {
                actiontarget.setText("Calling the JavaScript");
            }
        </fx:script>
    
        <HBox spacing="10" alignment="bottom_right"
              GridPane.columnIndex="1" GridPane.rowIndex="4">
            <Button text="登录" onAction="handleSubmitButtonAction(event);"/>
        </HBox>
    
        <Text fx:id="actiontarget"
              GridPane.columnIndex="0" GridPane.columnSpan="2"
              GridPane.halignment="RIGHT" GridPane.rowIndex="6"/>
    </GridPane>
    

    点击之后,调用脚本:

     
    Paste_Image.png

    脚本语言提供与JSR 223规范兼容的引擎即可。例如JavaScript、Groovy、Jython、Clojure。

    方法二.2:使用外置JS脚本处理
    脚本可以放在外部,正确引用即可:

     
    Paste_Image.png
     
    Paste_Image.png
     
    Paste_Image.png
    function handleSubmitButtonAction() {
        actiontarget.setText("Calling the Outline JavaScript");
    }
    

    同时,在FXML中引入脚本:

    <GridPane xmlns:fx="http://javafx.com/fxml" 
              fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController" 
              alignment="center" hgap="10" vgap="10">
    
        <fx:script source="FXMLJSLoginDemo.js"/>
    
        <HBox spacing="10" alignment="bottom_right"
              GridPane.columnIndex="1" GridPane.rowIndex="4">
            <Button text="登录" onAction="handleSubmitButtonAction(event);"/>
        </HBox>
    
        <Text fx:id="actiontarget"
              GridPane.columnIndex="0" GridPane.columnSpan="2"
              GridPane.halignment="RIGHT" GridPane.rowIndex="6"/>
    </GridPane>
    

    试运行,得到结果:

     
    Paste_Image.png
    4、 添加样式控制:

    添加样式表文件、字体库文件、背景图片,增加fonts.mf配置文件,修改build.xml等等,与前面纯代码开发基本一致,注意路径名(包名有变化)。
    在FXML中引入样式表,并给特定的控件增加id,以便于CSS样式筛选器能够正确筛选适配:

    <GridPane xmlns:fx="http://javafx.com/fxml" 
              fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController" 
              alignment="center" hgap="10" vgap="10"
              styleClass="root" >
    
        <stylesheets>
            <URL value="@Login.css" />
        </stylesheets>
        
        <Text id="welcome-text" text="欢迎登录FXML Demo系统"
              GridPane.columnIndex="0" GridPane.rowIndex="0"
              GridPane.columnSpan="2"/>
    
        <Text id="actiontarget" fx:id="actiontarget"
              GridPane.columnIndex="0" GridPane.columnSpan="2"
              GridPane.halignment="RIGHT" GridPane.rowIndex="6"/>
    </GridPane>
    
    5、 最终运行结果:
     
    Paste_Image.png

    FXML方式开发界面完成。

    JavaFX Scene Builder 2.0协助开发

    JavaFX Scene Builder 2.0下载位置
    下载完成,一路安装,开始运行:

     
    Paste_Image.png

    非常简单的一个界面,就是做做界面……
    配置一下:

     
    Paste_Image.png
     
    Paste_Image.png

    选择JavaFX Scene Builder安装主目录,即可。

    然后,双击或者右击打开FXML,则会自动使用SB编辑器打开。

    NetBeans是JavaFX的一个开发工具,比较好用。
    除此之外,e(fx)clipse也是一个不错的JavaFX开发工具,有时间可以适当查下资料,看看如何使用。



    作者:heguorui
    链接:https://www.jianshu.com/p/a80d1eedc507
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    Java集合:HashMap底层实现和原理(源码解析)
    Java获取异常堆栈信息
    win7 64位系统 PB连接oracle数据库出现“oracle library oci.dll could not be loaded”问题的解决方法
    Oralce 使用递归方式获取BOM树显示结构
    Oracle 链接数据库语句
    根据数据窗口某列的值定位行
    pb中数据窗口filter函数和retrieve函数的区别和联系
    用代码保存共享文件夹登录名和密码
    PB 组合数据窗口子窗口数据赋值方法
    PB 导出PDF
  • 原文地址:https://www.cnblogs.com/yanyouqiang/p/8424678.html
Copyright © 2011-2022 走看看