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语 ...
随机推荐
- http网站上传文件大小问题【没测试过】
web.config <httpRuntime maxRequestLength="" executionTimeout=""/> IIS 请求筛选 ...
- CAD中的各种Polyline
序号 类 类名 dxf代码 1 Polyline2d AcDb2dPolyline POLYLINE 2 Polyline3d AcDb3dPolyline POLYLINE 3 Polyline A ...
- LINUX 内存使用情况
# free 显示结果如下: Mem:表示物理内存统计 total 内存总数 8057964KBused 已使用的内存 7852484KBfree 空闲的内存数 205480KBshared 当前已经 ...
- awk中使用shell的环境变量
awk中使用shell的环境变量一:"'$var'"这种写法大家无需改变用'括起awk程序的习惯,是老外常用的写法.如:var="test"awk 'BEGIN ...
- python 引用计数
转载:NeilLee(有修改) 一.概述 要保持追踪内存中的对象,Python使用了引用计数这一简单的技术. sys.getrefcount(a)可以查看a对象的引用计数,但是比正常计数大1,因为 ...
- 使用jquery.mCustomScrollbar自定义滚动条(3)callback onCreate
碰到了一个问题,想简洁,所以在页面上使用 <div class="div_box mCustomScrollbar" data-mcs-theme="dark-3& ...
- 科学-天文学-天文观测站:TMT(红外天文望远镜)
ylbtech-科学-天文学-天文观测站:TMT(红外天文望远镜) 30米望远镜(Thirty Meter Telescope,TMT) 系由美国加州大学和加州理工学院负责研制的新一代地基巨型光学-红 ...
- org.apache.ibatis.binding.BindingException: Parameter 'idList' not found解决办法
https://blog.csdn.net/qq_28379809/article/details/83342196 问题描述 使用Mybatis查询数据库报错: org.apache.ibatis. ...
- PG cannot execute UPDATE in a read-only transaction | How to add column if not exists on PostgreSQL
PG cannot execute UPDATE in a read-only transaction出现这种情况时,说明SQL语句可能是运行在一个PG集群中的非master节点上.查看data/pg ...
- Jmeter(三十五)聚合报告
Jmeter的聚合报告是一个非常nice的listener,接口测试以及性能测试方面都会用到这个nice的监听器. 那么优秀在什么地方呢?上图 日常工作中可能只关注这部分内容: 可是这里边的指标真的都 ...