javafx自动补全
public boolean showUpload2HomeDialog(final OperationInfo initDataInfo) {
boolean result = false;
try {
// Load the fxml file and create a new stage for the popup dialog.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getClassLoader().getResource("fxml/UploadHomeView.fxml"));
AnchorPane updateDatasetDialogView = (AnchorPane) loader.load();
// update the dialog Stage.
Stage dialogStage = new Stage();
dialogStage.setTitle("Upload To Home");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
AlertDialogUtil.modifyDialogPosition(dialogStage, primaryStage);
Scene scene = new Scene(updateDatasetDialogView);
dialogStage.setScene(scene);
Upload2HomeController controller = loader.getController();
controller.setDialogStage(dialogStage);
controller.setInitInput(initDataInfo.getLocalPath());
controller.setMainApp(this);
// Show the dialog and wait until the user closes it
dialogStage.showAndWait();
// update updateDataInfo to get datasetName and localPath
controller.updateInfo(initDataInfo);
result = controller.isOkClicked();
} catch (IOException | DMGUIException e) {
logger.error(e.getLocalizedMessage(), e);
}
return result;
}
package cn.com.xxx.project.controller; import java.io.File;
import java.util.ArrayList;
import java.util.List; import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPFileFilter; import cn.com.xxx.project.core.DMGUIException;
import cn.com.xxx.project.core.FTPFileManagerWrapper;
import cn.com.xxx.project.model.GlobalConfig;
import cn.com.xxx.project.model.OperationInfo;
import cn.com.xxx.project.util.AlertDialogUtil;
import cn.com.xxx.project.util.PathUtil;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage; interface ItemFilter {
boolean matches(String inputStr, String optionalStr);
} public class Upload2HomeController {
@FXML private TextField inputPathField;
@FXML private ComboBox<String> remotePathComboBox; private Main mainApp;
private Stage dialogStage;
private boolean okClicked = false; //下拉条目查找器
private FTPFileManagerWrapper ftpFileMng; private final ObservableList<String> itemList = FXCollections.observableArrayList();
private boolean isFilterNotRequired = true;
private final ObservableList<String> filteredItemList = FXCollections.observableArrayList();
private final FTPFileFilter ftpFilter = file -> file.isDirectory() && ! file.getName().startsWith(".");
private final ItemFilter filter = (inputStr, optionalStr) -> optionalStr.startsWith(inputStr);
private String tempRemotePath = null;
private String oldRemotePath = null; private static final int MAX_VISIBLE_ROW_COUNT = 5; /**
* 属性初始化
*/
public void setMainApp(final Main mainApp) throws DMGUIException {
this.mainApp = mainApp;
initFTPFileMng();
mainApp.getRemoteDatasetsController().selectHomeTab(); Platform.runLater(()->{
String remotePath = mainApp.getRemoteDatasetController().getRemotePath(); remotePathComboBox.setItems(itemList);
remotePathComboBox.setVisibleRowCount(MAX_VISIBLE_ROW_COUNT); itemList.addAll(listAbsDirPath(remotePath));
setText(remotePath);
oldRemotePath = remotePath; setFocusedPropertyListener();
setKeyListener();
});
} private List<String> listAbsDirPath(String path){
List<FTPFile> files = ftpFileMng.list(path, ftpFilter); List<String> absDirPaths = new ArrayList<String>();
path = path.endsWith("/") ? path : path + "/";
for (FTPFile file: files) {
absDirPaths.add(path + file.getName());
}
return absDirPaths;
} public void initFTPFileMng() throws DMGUIException{
ftpFileMng = new FTPFileManagerWrapper();
ftpFileMng.setWorkPath(GlobalConfig.getInstance().getHomePath());
} private void setFocusedPropertyListener() {
remotePathComboBox.getEditor().focusedProperty().addListener(
(observable, oldValue, newValue) -> {
if (observable.getValue()){
remotePathComboBox.show();
String test = getText();
if (test != null){
Platform.runLater(()->{remotePathComboBox.getEditor().positionCaret(test.length());});
}
}
}
);
} private void setKeyListener() {
remotePathComboBox.addEventHandler(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {//NOPMD
if (event.getCode() == KeyCode.UP || event.getCode() == KeyCode.DOWN) {
show();
moveCaret();
return;
} if (isIgnoredKey(event.getCode())) {
return;
} reviseText(); refreshItems();
refreshFilteredItems();
resetComboBoxItemsAndDisplay();
oldRemotePath = getText();
}
});
} private boolean isIgnoredKey(final KeyCode keyCode) {
// BACK_SPACE/DELETE不做特殊处理
return keyCode.equals(KeyCode.SHIFT)
|| keyCode.equals(KeyCode.CONTROL)
|| keyCode.equals(KeyCode.LEFT)
|| keyCode.equals(KeyCode.RIGHT)
|| keyCode.equals(KeyCode.HOME)
|| keyCode.equals(KeyCode.END)
|| keyCode.equals(KeyCode.TAB)
|| keyCode.equals(KeyCode.ENTER);
} private void refreshItems() {
if (isRequiredRefresh()) {
itemList.setAll(listAbsDirPath(getDirPath(getText())));
}
} private String getDirPath(final String path){
int lastSlashCharIndex = path.lastIndexOf("/");
if (lastSlashCharIndex == -1) {
lastSlashCharIndex = path.length();
}else if(lastSlashCharIndex == 0){
lastSlashCharIndex = 1;
}
return path.substring(0, lastSlashCharIndex);
} /**
* 待优化,考虑角度:字符在末尾增减,在中间增减,增减单字符,增减多字符
*/
private boolean isRequiredRefresh(){
boolean isRequied = false;
final int changedPathLen = getText().length() - oldRemotePath.length(); if (changedPathLen>0) {
isRequied = getText().endsWith("/") && filteredItemList.size() > 0;//条件:斜杠前面的路径有效
// && filteredItemList.size() == 1
// && filteredItemList.get(0).equals(oldRemotePath);
isFilterNotRequired = isRequied;
}else if (changedPathLen < 0){
isRequied = oldRemotePath.endsWith("/");
}
return isRequied;
} private void refreshFilteredItems() {
tempRemotePath = getText(); if (isFilterNotRequired){
filteredItemList.setAll(itemList);
isFilterNotRequired = false;
}else{
filteredItemList.clear();//路径文本也会被刷掉
for (String aData : itemList) {
if (aData != null && tempRemotePath != null
&& filter.matches(tempRemotePath, aData)) {
filteredItemList.add(aData);
}
}
}
} private void setTextAndMoveCaret(final String text) {
setText(text);
moveCaret();
} private void setText(final String text) {
remotePathComboBox.getEditor().setText(text);
} private String getText() {
return remotePathComboBox.getEditor().getText();
} /**
* FTPClient#listFiles()无法准确处理路径末尾多斜杠问题,需要强制修正
*/
private void reviseText(){
setText(PathUtil.filterExtraSlash(getText()));
}
private void resetComboBoxItemsAndDisplay() {
remotePathComboBox.setItems(filteredItemList); remotePathComboBox.getSelectionModel().clearSelection();
remotePathComboBox.setVisibleRowCount(filteredItemList.size() < MAX_VISIBLE_ROW_COUNT ?
filteredItemList.size() : MAX_VISIBLE_ROW_COUNT);
// 调用了总开关,重置显示下拉布局;可以优化,只重置具体的下拉布局属性。
remotePathComboBox.hide();
remotePathComboBox.show(); setTextAndMoveCaret(tempRemotePath);
} private void show() {
if (!remotePathComboBox.getItems().isEmpty() && !remotePathComboBox.isShowing()) {
remotePathComboBox.show();
}
} private void moveCaret() {
String test = getText();
if (test != null) {
moveCaret(test.length());
}
} private void moveCaret(final int pos) {
remotePathComboBox.getEditor().positionCaret(pos);
}
public void setDialogStage(final Stage dialogStage) {
this.dialogStage = dialogStage;
} public void setInitInput(final String localPath) {
inputPathField.setText(localPath);
} public boolean isOkClicked() {
return okClicked;
} public void updateInfo(final OperationInfo updateInfo) {
updateInfo.setLocalPath(inputPathField.getText());
updateInfo.setRemotePath(
PathUtil.splicePath(GlobalConfig.getInstance().getHomePath(), getText()));
} @FXML
private void handleOk() { //NOPMD
try {
checkInput(); okClicked = true;
dialogStage.close();
} catch (DMGUIException e) {
AlertDialogUtil.createLazyAlertDialog(e.getMessage(), "输入错误!");
}
} @FXML
private void handleCancel() { //NOPMD
dialogStage.close();
} @FXML
private void handleBrowseDir() { //NOPMD
DirectoryChooser dirChooser = new DirectoryChooser();
dirChooser.setInitialDirectory(new File("."));
File file = dirChooser.showDialog(mainApp.getPrimaryStage()); if (file != null) {
inputPathField.setText(file.getPath().toString());
}
} @FXML
private void handleBrowseFile() { //NOPMD
// Open a directory selecting dialog
FileChooser fileChooser = new FileChooser();;
fileChooser.setInitialDirectory(new File("."));
fileChooser.getExtensionFilters().addAll(
new ExtensionFilter("All Files", "*.*"),
new ExtensionFilter("Text Files", "*.txt"),
new ExtensionFilter("CSV Files", "*.csv"),
new ExtensionFilter("Image Files", "*.png", "*.jpg", "*.gif"),
new ExtensionFilter("Audio Files", "*.wav", "*.mp3", "*.aac"),
new ExtensionFilter("XML files", "*.xml"));
File file = fileChooser.showOpenDialog(mainApp.getPrimaryStage()); if (file != null) {
inputPathField.setText(file.getPath().toString());
}
} private void checkInput() throws DMGUIException{
final StringBuilder errMsg = new StringBuilder();
checkInputLocalPath(errMsg);
checkInputRemotePath(errMsg); if(errMsg.length() != 0){
throw new DMGUIException(errMsg.toString());
}
} private void checkInputLocalPath(final StringBuilder errMsg){
if (this.inputPathField.getText() == null
|| this.inputPathField.getText().length() == 0) {
errMsg.append("本地路径为空,请重新输入!\n");
} else {
final File file = new File(inputPathField.getText());
if (!file.exists()) { // NOPMD
errMsg.append("本地路径不存在,请重新输入!\n");
}
} if(errMsg.length() == 0){
this.inputPathField.setStyle("-fx-border-color: null");
}else{
this.inputPathField.setStyle("-fx-border-color: red");
}
} private void checkInputRemotePath(final StringBuilder errMsg){
String inputRemotePath = getText();
boolean isExist = ftpFileMng.isDirExist(inputRemotePath); if (isExist){
remotePathComboBox.setStyle("-fx-border-color: null");
}else{
errMsg.append("远端路径不存在,请重新输入!\n");
remotePathComboBox.setStyle("-fx-border-color: red");
}
}
}
public static List<String> filterExtraSubPath(final String[] fileNameArr){
List<String> newFileNameList = new ArrayList<>();
for(String fileName: fileNameArr){
if( ! fileName.equals(".") && ! fileName.equals("")){
newFileNameList.add(fileName);
}
}
return newFileNameList;
}
public static String filterExtraSlash(final String path){
if (null == path){
return null;//NOPMD
}
String[] fileNameArr = path.split("/");
List<String> subPathList = filterExtraSubPath(fileNameArr);
return "/" + String.join("/", subPathList) + (path.endsWith("/") && !path.equals("/")?"/":"");
}
pathutil.java
javafx自动补全的更多相关文章
- jQuery 邮箱下拉列表自动补全
综述 我想大家一定见到过,在某个网站填写邮箱的时候,还没有填写完,就会出现一系列下拉列表,帮你自动补全邮箱的功能.现在我们就用jQuery来实现一下. 博主原创代码,如有代码写的不完善的地方还望大家多 ...
- eclipse自动补全的设置
eclipse自动补全的设置 如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的 ...
- vim 添加php自动补全 并格式化代码
自动补全,修改/etc/vimrc的配置 vim /etc/vimrc 添加: filetype plugin on autocmd FileType php set omnifunc=phpcomp ...
- Eclipse自动补全设置
如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为ecl ...
- Autocomplete 自动补全(Webform实战篇)
开篇语 因为项目中需要用到一个自动补全的功能,功能描述: 需求一:新增收件人的时候,自动下拉显示出数据库中所有的收件人信息(显示的信息包括:姓名-收件地址-联系方式) 需求二:选中一个值得时候,分别赋 ...
- eclipse自动补全的设置(自动提示)
如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为e ...
- jQuery AutoComplete 自动补全
jQuery.AutoComplete是一个基于jQuery的自动补全插件.借助于jQuery优秀的跨浏览器特性,可以兼容Chrome/IE/Firefox/Opera/Safari等多种浏览器. 特 ...
- Vim自动补全神器–YouCompleteMe
一.简介 YouCompleteMe是Vim的自动补全插件,与同类插件相比,具有如下优势 1.基于语义补全 2.整合实现了多种插件 clang_complete.AutoComplPop .Super ...
- 通过trie树单词自动补全(二)
经常使用iciba进行单词查询, 关于他的搜索建议是通过单词前缀做的索引, 所以自己想动手实现下, 当然如果借助mysql的话,一条sql语句就能实现, 网上查询了下trie正适合做这个,所以通过C语 ...
随机推荐
- 银行卡所属公司判断 参考自https://blog.csdn.net/well2049/article/details/79429130
在网上找到了一个银行卡的验证,通过阿里的支付宝接口进行校验,能够准确识别是否存在,归属行,卡号类型是储蓄卡(DC)还是信用卡(CC). 接口api:需要传入的2个参数,卡号cardNo和cardBin ...
- Excel技巧--漏斗图让转化率直观明了
当要实现如上图那样表现转化率等漏斗形图表时,可以这么做: 1.选择表格,点击“插入”-->“二维条形图”-->堆积条形图类型: 2.点击选中图表,点击”设计“-->“选择数据”: 将 ...
- Delphi实现软件中登录用户的操作权限
数据库结构:包括两张表BaseData和UserRightData,BaseData中是一张基本表,里面不区分用户,UserRightData是用户权限表,结构和BaseData一样,只是多了用户字段 ...
- SVN怎么触发Jenkins自动构建
通常,有几种方式可以在SVN仓库发生改变时触发Jenkins进行构建.第一种是,Jenkins主动轮询SVN仓库:第二种是,在SVN客户端(如TortoiseSVN)创建客户端hooks来触发构建:第 ...
- NSIS 制作简单安装包
;replace NSIS/Contrib/zip2exe/Modern.nsh;NSI format: Asni;http://nsis.sourceforge.net/ ;UAC级别Request ...
- 黄聪:PHP调试显示所有错误信息
ini_set('display_errors',1); //错误信息 ini_set('display_startup_errors',1); //php启动错误信息 error_reporting ...
- 从源代码更新glibc
先看下INSTALL/README: mkdir一个目录专用于build: ../configure --prefix=/usr: make之后make check: 进入single user mo ...
- 【git】之push异常
Push rejected: Push to origin/master was rejected 打开git shell面板 $ git pull origin master --allow-unr ...
- 使用keytool 生成数字keystore
生成本地证书 在密钥库中生成本地数字证书:需要提供身份.加密算法.有效期等信息: keytool指令如下,产生的本地证书后缀名为:*.keystore keytool -genkeypair -key ...
- P2412高精度减法
传送门 因为忘了带书回家,所以因为这道题我卡了半小时所以写篇博客“纪念”下 高精度减法中,如果被减数比减数小,就要用减数减去被减数.接下来的判断就是本题的核心.直接用strcmp是不行的,例如100与 ...