前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaFX里如何自定义Dialog

JavaFX里如何自定义Dialog

作者头像
扶墙老师
发布2023-10-25 19:24:14
4180
发布2023-10-25 19:24:14
举报
文章被收录于专栏:扶墙集扶墙集

这是福强的第215篇原创

原文链接 🖖 https://afoo.me

当然,主要的可选项依然是两个:

  1. 基于javafx.stage.Stage
  2. 基于javafx.scene.control.Dialog

第一种很简单,就是以写一个JavaFX应用那样的”套路”新开一个窗口而已,所以,不做赘述,毕竟,写JavaFX首先就得先会写一个应用不是?

重点是第二种方式,即基于javafx.scene.control.Dialog进行自定义Dialog的设计和实现。

javafx.scene.control.Dialog是个范型类:Class Dialog<R>

这个R代表Dialog返回结果的类型,也就是对话框关闭之后返回的结果类型,如果我们要把Dialog中各个组件的数据返回给调用程序使用,那么,就要以R类型的形式返回,最简单的就是返回一个String,复杂点儿的就是把多个组件的数据打包成一个类型,比如scala里的case class或者kotlin里的data class, java里当然就是javabeans ;)

那如何打包数据让它们以R类型的形式返回给调用者呢?这就得用到一个概念,叫resultConverter,在Dialog里有个属性叫resultConverterProperty,保存的就是相应的resultConverter,不过, resultConverter是概念,它对应的类型是Callback<ButtonType,R>, 其实就是一个函数,接收ButtonType类型数据作为参数,然后返回R类型的数据作为结果,用函数来描述就是ButtonType => R, 绝大多数情况下(只要我们希望Dialog关闭后给调用者返回数据),resultConverter是必须设置的。

一个常见的resultConverter实现逻辑类似于:

代码语言:javascript
复制
setResultConverter((buttonType) => if (buttonType == ButtonType.OK) Some(passwordF.getText) else None)

这里,我们只处理特定button类型对应的返回结果, 因为我们声明了一个简单的Dialog,返回值类型是Option[String],所以,我们在用户点击OK按钮之后,通过Some封装对话框里text field组件的值作为结果返回,其它情况下,都返回None。

这样,当调用者获得对话框返回结果之后,就可以进行类似如下的处理:

代码语言:javascript
复制
代码语言:javascript
复制
val dlg = new CustomDialog[Option[String]]()
dlg.showAndWait().ifPresent(result => 
    result.foreach(password => {
        settings.updateAdminPassword(password)
    })
)
代码语言:javascript
复制

ifPresent是检查用户是点了OK还是Cancel,决定是否有返回结果,如果有返回结果(也就是result),那么,我们再根据返回结果类型对数据进行处理,因为这里我们的结果类型是Option[String],所以,我们通过foreach(也可以通过判断或者pattern matching)对结果进行了处理。

以上是数据交换的逻辑,即对话框与调用者之间数据交换的逻辑,下面我们再来看UI逻辑。

Dialog的UI主要通过设置Dialog对应的DialogPane的内容来实现,而DialogPane则通过调用Dialog的getDialogPane()获得引用,之后就可以向其中追加UI布局和组件了。

定制Dialog的UI主要是两种思路:

  1. 沿用Dialog的布局,做最简单的设置,比如直接setTitle,setContentText等等,然后再通过getDialogPane.setExpandableContent(myLayout)添加附加内容;
  2. 直接结果Dialog的布局和内容,通过getDialogPane.setContent(myLayout)最大限度接管UI的布局和组件。;

除此之外,最后一个要定制的就是要显示什么按钮以及显示几个按钮,这是通过getDialogPane.getButtonTypes.addAll(ButtonType.OK, ButtonType.CANCEL,...)来实现的,如果要对具体哪个按钮进行进一步的设置,则需要先取得这个按钮对应的组件,然后再进行设置:

代码语言:javascript
复制
代码语言:javascript
复制
val okButton = getDialogPane.lookupButton(ButtonType.OK)
okButton.disableProperty().bind(Bindings.createBooleanBinding(() => StringUtils.isEmpty(passwordF.textProperty().get()), passwordF.textProperty()))
代码语言:javascript
复制

至此,基本上一个自定义Dialog就完成了。

小结一下就是:

  1. 通过设置resultConverter对返回数据进行采集、转换和返回;
  2. 通过getDialogPane()取得Dialog对应的DialogPane做UI定制;
  3. 按钮按需添加、按需查找、按需设置;

就酱紫。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福强 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档