- 浏览: 183493 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
Brooke:
啥时候分享一下源码呗 学习一下
基于eclipse RCP的文件夹管理工具 -
红耳飞鹏:
貌似懂了之后才能看的懂,个人看法
刷新 javaFX2.0 数据视图(TableView/ListView/TreeView) -
leaow567:
这个要支持啊
基于eclipse RCP的文件夹管理工具--FileTools -
yunchow:
luoyu-ds 写道我是来看博主的头像的+1
eclipse RCP 模仿win7资源管理器地址栏功能 -
luoyu-ds:
我是来看博主的头像的
eclipse RCP 模仿win7资源管理器地址栏功能
译自: http://java.dzone.com/articles/javafx-numbertextfield-and
作者: Thomas Bolz
我最近花了一些时间学习javaFX, 要更深入地理解新GUI包, 自定义控制器可能是一个比较好的方法. 由于我是开发财务软件的, 所以我当然希望javaFX中也有类似JFormattedTextField和JSpinner的控件. 这对我来说确实是个不错的选择.
这是我的控制器:
- 数字文本框(NumberTextField): 可以配置任意格式的数字;
- 微调控制器( NumberSpinner ): 可以使用键盘方向键或箭头按钮来控制数值;它也是控制器的一部分;
控制器及其示例可以在这里下载(可直接导入到netbeans,见附件). 示例中还包含一个css样式文件, 它用于控制Spinner的风格是直角或圆角.
NumberTextField
NumberTextField 的实现很容易,以致我认为这算不上自定义控制器, 而仅仅是改变一个已存在的控制器的一些行为而已. NumberTextField 扩展自JFX中的文本框(TextField), 添加一个使用BigDecimal(由于财务软件需要精确的类型)的NumberProperty作为模型, 并做一些格式化和解析处理. 就这样, 不复杂.
package de.thomasbolz.javafx; import java.math.BigDecimal; import java.text.NumberFormat; import java.text.ParseException; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.control.TextField; /** * Textfield implementation that accepts formatted number and stores them in a * BigDecimal property The user input is formatted when the focus is lost or the * user hits RETURN. * * @author Thomas Bolz */ public class NumberTextField extends TextField { private final NumberFormat nf; private ObjectProperty<BigDecimal> number = new SimpleObjectProperty<>(); public final BigDecimal getNumber() { return number.get(); } public final void setNumber(BigDecimal value) { number.set(value); } public ObjectProperty<BigDecimal> numberProperty() { return number; } public NumberTextField() { this(BigDecimal.ZERO); } public NumberTextField(BigDecimal value) { this(value, NumberFormat.getInstance()); } public NumberTextField(BigDecimal value, NumberFormat nf) { super(); this.nf = nf; initHandlers(); setNumber(value); } private void initHandlers() { // try to parse when focus is lost or RETURN is hit setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent arg0) { parseAndFormatInput(); } }); focusedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { if (!newValue.booleanValue()) { parseAndFormatInput(); } } }); // Set text in field if BigDecimal property is changed from outside. numberProperty().addListener(new ChangeListener<BigDecimal>() { @Override public void changed(ObservableValue<? extends BigDecimal> obserable, BigDecimal oldValue, BigDecimal newValue) { setText(nf.format(newValue)); } }); } /** * Tries to parse the user input to a number according to the provided * NumberFormat */ private void parseAndFormatInput() { try { String input = getText(); if (input == null || input.length() == 0) { return; } Number parsedNumber = nf.parse(input); BigDecimal newValue = new BigDecimal(parsedNumber.toString()); setNumber(newValue); selectAll(); } catch (ParseException ex) { // If parsing fails keep old number setText(nf.format(number.get())); } } }
NumberSpinner
NumberSpinner好像复杂一点. 它构建在NumberTextField 上, 并使用递增和递减按钮来改变文本框中数字的值, 每次改变步长为stepwidth.
stepwidth和NumberFormat的初始值在构造器中指定. 文本框和按钮的大小取决于文本的大小. 文本的大小可在.css文件中设置.
package de.thomasbolz.javafx; import java.math.BigDecimal; import java.text.NumberFormat; import javafx.beans.binding.NumberBinding; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Pos; import javafx.scene.control.Button; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.shape.LineTo; import javafx.scene.shape.MoveTo; import javafx.scene.shape.Path; import javax.swing.JSpinner; /** * JavaFX Control that behaves like a {@link JSpinner} known in Swing. The * number in the textfield can be incremented or decremented by a configurable * stepWidth using the arrow buttons in the control or the up and down arrow * keys. * * @author Thomas Bolz */ public class NumberSpinner extends HBox { public static final String ARROW = "NumberSpinnerArrow"; public static final String NUMBER_FIELD = "NumberField"; public static final String NUMBER_SPINNER = "NumberSpinner"; public static final String SPINNER_BUTTON_UP = "SpinnerButtonUp"; public static final String SPINNER_BUTTON_DOWN = "SpinnerButtonDown"; private final String BUTTONS_BOX = "ButtonsBox"; private NumberTextField numberField; private ObjectProperty<BigDecimal> stepWitdhProperty = new SimpleObjectProperty<>(); private final double ARROW_SIZE = 4; private final Button incrementButton; private final Button decrementButton; private final NumberBinding buttonHeight; private final NumberBinding spacing; public NumberSpinner() { this(BigDecimal.ZERO, BigDecimal.ONE); } public NumberSpinner(BigDecimal value, BigDecimal stepWidth) { this(value, stepWidth, NumberFormat.getInstance()); } public NumberSpinner(BigDecimal value, BigDecimal stepWidth, NumberFormat nf) { super(); this.setId(NUMBER_SPINNER); this.stepWitdhProperty.set(stepWidth); // TextField numberField = new NumberTextField(value, nf); numberField.setId(NUMBER_FIELD); // Enable arrow keys for dec/inc numberField.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() { @Override public void handle(KeyEvent keyEvent) { if (keyEvent.getCode() == KeyCode.DOWN) { decrement(); keyEvent.consume(); } if (keyEvent.getCode() == KeyCode.UP) { increment(); keyEvent.consume(); } } }); // Painting the up and down arrows Path arrowUp = new Path(); arrowUp.setId(ARROW); arrowUp.getElements().addAll(new MoveTo(-ARROW_SIZE, 0), new LineTo(ARROW_SIZE, 0), new LineTo(0, -ARROW_SIZE), new LineTo(-ARROW_SIZE, 0)); // mouse clicks should be forwarded to the underlying button arrowUp.setMouseTransparent(true); Path arrowDown = new Path(); arrowDown.setId(ARROW); arrowDown.getElements().addAll(new MoveTo(-ARROW_SIZE, 0), new LineTo(ARROW_SIZE, 0), new LineTo(0, ARROW_SIZE), new LineTo(-ARROW_SIZE, 0)); arrowDown.setMouseTransparent(true); // the spinner buttons scale with the textfield size // TODO: the following approach leads to the desired result, but it is // not fully understood why and obviously it is not quite elegant buttonHeight = numberField.heightProperty().subtract(3).divide(2); // give unused space in the buttons VBox to the incrementBUtton spacing = numberField.heightProperty().subtract(2).subtract(buttonHeight.multiply(2)); // inc/dec buttons VBox buttons = new VBox(); buttons.setId(BUTTONS_BOX); incrementButton = new Button(); incrementButton.setId(SPINNER_BUTTON_UP); incrementButton.prefWidthProperty().bind(numberField.heightProperty()); incrementButton.minWidthProperty().bind(numberField.heightProperty()); incrementButton.maxHeightProperty().bind(buttonHeight.add(spacing)); incrementButton.prefHeightProperty().bind(buttonHeight.add(spacing)); incrementButton.minHeightProperty().bind(buttonHeight.add(spacing)); incrementButton.setFocusTraversable(false); incrementButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent ae) { increment(); ae.consume(); } }); // Paint arrow path on button using a StackPane StackPane incPane = new StackPane(); incPane.getChildren().addAll(incrementButton, arrowUp); incPane.setAlignment(Pos.CENTER); decrementButton = new Button(); decrementButton.setId(SPINNER_BUTTON_DOWN); decrementButton.prefWidthProperty().bind(numberField.heightProperty()); decrementButton.minWidthProperty().bind(numberField.heightProperty()); decrementButton.maxHeightProperty().bind(buttonHeight); decrementButton.prefHeightProperty().bind(buttonHeight); decrementButton.minHeightProperty().bind(buttonHeight); decrementButton.setFocusTraversable(false); decrementButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent ae) { decrement(); ae.consume(); } }); StackPane decPane = new StackPane(); decPane.getChildren().addAll(decrementButton, arrowDown); decPane.setAlignment(Pos.CENTER); buttons.getChildren().addAll(incPane, decPane); this.getChildren().addAll(numberField, buttons); } /** * increment number value by stepWidth */ private void increment() { BigDecimal value = numberField.getNumber(); value = value.add(stepWitdhProperty.get()); numberField.setNumber(value); } /** * decrement number value by stepWidth */ private void decrement() { BigDecimal value = numberField.getNumber(); value = value.subtract(stepWitdhProperty.get()); numberField.setNumber(value); } public final void setNumber(BigDecimal value) { numberField.setNumber(value); } public ObjectProperty<BigDecimal> numberProperty() { return numberField.numberProperty(); } public final BigDecimal getNumber() { return numberField.getNumber(); } // debugging layout bounds public void dumpSizes() { System.out.println("numberField (layout)=" + numberField.getLayoutBounds()); System.out.println("buttonInc (layout)=" + incrementButton.getLayoutBounds()); System.out.println("buttonDec (layout)=" + decrementButton.getLayoutBounds()); System.out.println("binding=" + buttonHeight.toString()); System.out.println("spacing=" + spacing.toString()); } }
number_spinner.css
最后, 控制器的样式可在css文件中设置. 我实现了圆角和直角两种风格(见上文截图). 你可以通过修改 #NumberField, #ButtonBox, #SpinnerButtonUp 和#SpinnerButtonDown 中的border/background-radiuses来切换不同的风格.
.root{ -fx-font-size: 24pt; /* -fx-base: rgb(255,0,0);*/ /* -fx-background: rgb(50,50,50);*/ } #NumberField { -fx-border-width: 1; -fx-border-color: lightgray; -fx-background-insets:1; -fx-border-radius:3 0 0 3; /* -fx-border-radius:0 0 0 0;*/ } #NumberSpinnerArrow { -fx-fill: gray; -fx-stroke: gray; /* -fx-effect: innershadow( gaussian , black , 2 , 0.6 , 1 , 1 )*/ } #ButtonsBox { -fx-border-color:lightgray; -fx-border-width: 1 1 1 0; -fx-border-radius: 0 3 3 0; /* -fx-border-radius: 0 0 0 0;*/ } #SpinnerButtonUp { -fx-background-insets: 0; -fx-background-radius:0 3 0 0; /* -fx-background-radius:0;*/ } #SpinnerButtonDown { -fx-background-insets: 0; -fx-background-radius:0 0 3 0; /* -fx-background-radius:0;*/ }
结论
从上面的例子可以看出在javaFx中自定义控制器并不困难. JavaFX自2.0版本以后作为一个纯粹的java API, 其比以前的任何版本更好地整合诸如groovy(BigDecimal的乐土)的语言. 这将是财务桌面应用的黄金组合.
- JavaFXSpinner_1.zip (24.5 KB)
- 下载次数: 51
发表评论
-
eclipse RCP 模仿win7资源管理器地址栏功能
2013-04-23 15:25 3023本文实现效果及其工具下载地址:http://sourcef ... -
[EasyTao(道)系列文章之一]太极之道
2012-07-22 10:05 1479综述 周易是中国传统文化的基石. 涵盖了包括哲学在内的 ... -
基于eclipse RCP的文件夹管理工具
2012-07-14 00:45 3367总的来说, Windows7的文件夹浏览器已经提供了很好 ... -
基于eclipse RCP的文件夹管理工具
2012-07-13 23:36 4闲来无事, 做个文件夹浏览器玩玩----基于eclipse R ... -
基于eclipse RCP的文件夹管理工具
2012-07-13 23:34 3闲来无事, 做个文件夹浏览器玩玩 -
基于eclipse RCP的文件夹管理工具
2012-07-13 23:34 3闲来无事, 做个文件夹浏览器玩玩 -
javafx2.0 初体验之 处方管理系统
2012-02-16 00:15 2780总体感觉 JFX2 应用起来比swing方便;其效果类似于f ... -
javafx2.0 修改控件默认鼠标键盘监听
2012-02-04 10:57 6635JFX为所有空间提供了默认的鼠标键盘监听,以符合一般使用 ... -
javafx2.0 在表格(TableView)中显示选择按钮(CheckBox)
2012-02-03 22:23 10723要在JFX的表格中显示自定义的单元(TableCe ... -
刷新 javaFX2.0 数据视图(TableView/ListView/TreeView)
2012-02-02 20:49 8858数据视图(TableView/ListView/T ... -
javafx2.0 获取TableView 正在编辑的单元TableCell
2012-02-02 19:52 8052JFX使用CellFactory(Callback)来获取每个 ... -
javafx2.0 资源
2012-02-02 13:27 1963教程: 官方教程. 下载地址:http:/ ... -
JavaFX的2.0常见问题合集
2012-02-02 13:19 2409JavaFX的2.0常见问题 1。 在JavaFX ... -
javafx2.0 监听树和表的选择变化
2012-01-13 22:47 6103Swing中的组件都有对应的选择模型(SelectionMod ... -
开源地图编辑器 mepper
2011-09-30 17:09 3087Mepper 这是我在2009年参与的项目中开 ... -
[转]AOP在大规模软件开发项目中应用的尝试与思考
2011-08-08 12:31 1510珉 李 (minli@cn ... -
单例模式和软引用[Soft Singleton Idiom]
2011-05-22 15:35 1773原文出自:http://www.javaworld.com/c ... -
【草稿 勿看】伟大的重构
2011-04-08 00:18 69一句话:进行大规模重构时,不要一下子就删掉原来的东西。先把新的 ... -
Java7异常新特性之mutilcatch
2011-03-25 14:36 2179历经4年,Java7终于和大家见面。关于Java7的新特性, ...
相关推荐
Javafx 2.0: Introduction by Example
JavaFX 使用指南 JavaFX 是一个基于 Java 语言的软件平台,用于开发桌面应用程序、移动应用程序和网络应用程序。它提供了一个统一的编程模型,可以跨平台运行,具有高清晰度的图形用户界面和多媒体支持。 JavaFX ...
Use the JavaFX platform to create rich-client Java applications and discover how you can use this powerful Java-based UI platform, which is capable of handling large-scale data-driven business ...
在JavaFX中,开发者可以使用丰富的图形用户界面(GUI)组件库,如按钮、文本框、标签、表格和图表等,来设计和构建用户友好的界面。对于“WorldCupHANDBOOK”,可能包含了各种与足球比赛相关的控件,比如显示各国...
在JavaFX中,实现百度文本框的下拉提示功能,主要涉及到的是文本输入与实时匹配的概念,这在很多用户界面中都有广泛的应用,如搜索引擎、输入法等。这个功能能够提高用户体验,帮助用户快速找到他们可能正在寻找的...
在本文中,我们将深入探讨如何使用JavaFX技术来模拟电子琴的弹奏效果,并结合具体的音效资源实现一个简易的电子琴应用。JavaFX是一个强大的Java库,用于创建桌面、移动和Web应用程序,其丰富的图形和媒体功能非常...
2. **JavaFX**: - JavaFX是Java的一个模块,用于创建丰富的图形用户界面(GUI)。它提供了丰富的组件库,如按钮、文本框、标签等,以及强大的样式和皮肤支持,便于构建美观的应用程序。 - JavaFX支持FXML(FXML ...
In Pro JavaFX 2: A Definitive Guide to Rich Clients with Java Technology, Jim Weaver, Weiqi Gao, Stephen Chin, Dean Iverson, and Johan Vos show you how you can use the JavaFX platform to create rich-...
- **丰富的 UI 控件库**:内置了一系列常用控件,如按钮、文本框等,同时也支持自定义控件的开发。 - **脚本支持**:允许使用 JavaScript 进行脚本编程,方便进行快速原型开发或实现简单的动态效果。 - **多平台支持...
1. **准备教程**:确保使用的是支持JavaFX 2.0的NetBeans IDE。 2. **设置项目**:创建一个新的JavaFX FXML Application项目。 3. **设定应用基础**:初始化必要的类和文件结构。 4. **创建属性文件**:用于存储界面...
根据给定文件的信息,我们可以提炼出关于JavaFX 2.0的重要知识点,这些知识点涵盖了JavaFX的基本概念、架构策略、发展历程以及其在图形用户界面(GUI)开发中的应用。 ### JavaFX 2.0:下一代GUI工具包 JavaFX 2.0...
JavaFx2:创建一个表单
JavaFX 官方教程:RIA 应用开发
- **第2章:使用JavaFX进行图形设计**:深入探讨了如何使用JavaFX创建各种类型的图形元素和动画效果,帮助读者理解如何构建美观且互动性强的用户界面。 - **第3章:使用JavaFX处理多媒体**:讲解了如何利用JavaFX...
此外,JavaFX还与JavaFX FXML紧密结合,这是一种基于XML的声明式语言,专门用于描述JavaFX应用程序的界面布局和控制器关联。使用FXML可以将界面设计与业务逻辑分离,提高代码的可读性和可维护性。 总的来说,JavaFX...
2. **CSS样式和皮肤化**:JavaFX允许使用CSS来样式化和布局控件,这与Web开发中的CSS语法非常相似,降低了学习曲线,同时提高了应用程序的外观一致性。 3. **动态性和响应性**:JavaFX支持数据绑定和反应式编程,...
在本例"spinner使用2"中,我们将深入探讨Spinner的使用方法,以及如何在实际项目中有效地集成这个控件。 首先,Spinner的基本使用步骤包括以下几个方面: 1. **添加Spinner到布局文件**:在XML布局文件中,我们...
### JavaFX 2:关键技术与应用开发概览 #### 章节1:JavaFX快速入门 本章节作为《Pro JavaFX 2》一书的开篇,旨在为读者提供一个快速进入JavaFX世界的机会。JavaFX是Sun Microsystems在2007年的JavaOne大会上宣布...
JavaFX 2.0 Introduction by Example.zip是javafx2.0的最新书籍《[JavaFX.2.0:Introduction.by.Example].Carl.Dea》上的源码!大家可以下载本书和源码一起看!我都上传了!