package pinyintest;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import pinyintest.pinyin.PinYinTool;
import java.util.*;
import java.util.regex.Pattern;
/**
* 文本框Enter、列表框双击或者Enter、按钮点击皆可搜索,模糊搜索后可上下键选择列表框中某一项,提供汉字、拼音、拼音首字母的模糊查询(匹配左侧)
*/
public class SearchTest extends Application {
/**
* 搜索文本框
*/
private TextField queryTextField = new TextField();
/**
* 搜索文本框和搜索结果列表的父容器
*/
private VBox vBox = new VBox(1);
/**
* 查询列表
*/
private ListView resultsListView = new ListView<>();
/**
* 存储内容
*/
private List contents = getContents();
/**
* 存储内容对应的拼音和拼音首字母
*/
private Map> pinyingMap = getPinYingMap(contents);
/**
* 搜索内容
*/
private String searchContent = "";
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
HBox hBox = new HBox(5);
Label searchLabel = new Label("搜索:");
// 标签文本向下移
searchLabel.setPadding(new Insets(5, 0, 0, 0));
queryTextField.setMaxWidth(80);
// 监听文本框输入值变化
queryTextField.textProperty().addListener(this::queryTextChange);
// 监听文本框焦点变化
queryTextField.focusedProperty().addListener(this::queryFocusedChange);
queryTextField.setOnKeyPressed(event -> {
handleKeyPressed(event);
});
resultsListView.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
// 双击搜索
if (e.getClickCount() == 2) {
saveSelectedInfo();
confirmSelectedResult();
}
// 单击选中
if (e.getClickCount() == 1) {
saveSelectedInfo();
}
});
resultsListView.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
handleKeyPressed(event);
});
resultsListView.setMaxWidth(80);
Button btn = new Button("搜索");
btn.setOnAction(event -> {
// 按钮点击搜索
confirmSelectedResult();
});
vBox.getChildren().add(queryTextField);
hBox.getChildren().addAll(searchLabel, vBox, btn);
// 使标签、文本框、按钮居于顶部
hBox.setAlignment(Pos.TOP_LEFT);
Pane pane = new Pane();
pane.getChildren().add(hBox);
pane.setPrefWidth(170);
pane.setPrefHeight(400);
primaryStage.setScene(new Scene(pane, 170, 400));
primaryStage.show();
}
/**
* 处理按键点击
*/
private void handleKeyPressed(KeyEvent event) {
if (event.getCode().equals(KeyCode.ENTER)) {
// Enter搜索
confirmSelectedResult();
}
// 可选的个数
int searchItemNum = resultsListView.getItems().size();
// 当前选中的列表项的索引
int selectedIndex = resultsListView.getSelectionModel().getSelectedIndex();
if (event.getCode().equals(KeyCode.UP) && (selectedIndex - 1) < searchItemNum) {
// 选择列表框中上一个
resultsListView.getSelectionModel().select(--selectedIndex);
saveSelectedInfo();
// 阻止原生事件进行,如文本框光标移动
event.consume();
}
if (event.getCode().equals(KeyCode.DOWN) && (selectedIndex + 1) > -1) {
// 选择列表框中下一个
resultsListView.getSelectionModel().select(++selectedIndex);
saveSelectedInfo();
// 阻止原生事件进行,如文本框光标移动
event.consume();
}
}
/**
* 保存选择的信息
*/
private void saveSelectedInfo() {
// 当前选中的列表项
searchContent = resultsListView.getSelectionModel().getSelectedItem();
}
private void queryFocusedChange(ObservableValue extends Boolean> observable, Boolean oldValue,
Boolean newValue) {
// 文本框失去焦点时,如果列表框未获得焦点,隐藏列表框
if (!newValue) {
if (!resultsListView.isFocused()) {
vBox.getChildren().remove(resultsListView);
}
} else {
searchResults(queryTextField.getText());
}
}
private void queryTextChange(ObservableValue extends String> observable, String oldValue, String newValue) {
searchResults(newValue);
}
private void searchResults(String searchText) {
clearQuery();
if (searchText.equals("")) {
return;
}
// 是否得到第一个搜索结果
boolean isNotHasFirstItem = queryContents(searchText);
if (!isNotHasFirstItem) {
// 无滚动条下的展示个数
int showCount = resultsListView.getItems().size();
// 有滚动条下的展示个数
if (showCount > 16) {
showCount = 16;
}
resultsListView.setMaxHeight(22 * showCount);
}
}
/**
* 搜索,返回是否未第一次查到结果
*/
private Boolean queryContents(String intputText) {
// 过滤汉字
boolean isHanziPart = false;
// 过滤拼音
boolean isPinyinPart = false;
// 过滤拼音首字母组合
boolean isPinyinHeadPart = false;
boolean isNotHasFirstItem = true;
for (Map.Entry> queryInfo : pinyingMap.entrySet()) {
isHanziPart = Pattern.matches(intputText + ".*", queryInfo.getKey());
isPinyinPart = Pattern.matches(intputText + ".*", queryInfo.getValue().get(0));
isPinyinHeadPart = Pattern.matches(intputText + ".*", queryInfo.getValue().get(1));
if (isHanziPart || isPinyinPart || isPinyinHeadPart) {
resultsListView.getItems().add(queryInfo.getKey());
if (isNotHasFirstItem) {
// 显示列表框
vBox.getChildren().add(resultsListView);
// 存储第一个中文名
searchContent = queryInfo.getKey();
// 默认选中列表框中第一个
resultsListView.getSelectionModel().select(0);
isNotHasFirstItem = false;
}
}
}
return isNotHasFirstItem;
}
/**
* 清空内存中查询记录
*/
private void clearQuery() {
searchContent = "";
resultsListView.getItems().clear();
vBox.getChildren().remove(resultsListView);
}
/**
* 确定选择结果并搜索
*/
private void confirmSelectedResult() {
queryTextField.setText(searchContent);
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("正在搜索:" + searchContent);
alert.setContentText("弹框对应confirmSelectedResult()方法");
alert.show();
}
private List getContents() {
List contents = new ArrayList<>();
contents.add("苹果");
contents.add("橙子");
contents.add("猕猴桃");
contents.add("香瓜");
contents.add("向日葵");
contents.add("西红柿");
contents.add("西瓜");
return contents;
}
private Map> getPinYingMap(List contents) {
Map> factoriesInfo = new HashMap>();
for (int i = 0; i < contents.size(); i++) {
String content = contents.get(i);
String pinying = PinYinTool.getPinYinString(content);
String pingyingHead = PinYinTool.getPinYinHeadString(content);
Vector pinyinInfo = new Vector();
pinyinInfo.add(pinying);
pinyinInfo.add(pingyingHead);
factoriesInfo.put(content, pinyinInfo);
}
return factoriesInfo;
}
}
改良版(点击面板使下拉列表消失,默认显示所有可选内容,查询结果拼音排序):
package pinyintest;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import pinyintest.pinyin.PinYinTool;
import java.text.Collator;
import java.util.*;
import java.util.regex.Pattern;
/**
* 文本框Enter、列表框双击或者Enter、按钮点击皆可搜索,模糊搜索后可上下键选择列表框中某一项,提供汉字、拼音、拼音首字母的模糊查询(匹配左侧)
*/
public class SearchTest extends Application {
/**
* 搜索文本框
*/
private TextField queryTextField = new TextField();
/**
* 搜索文本框和搜索结果列表的父容器
*/
private VBox vBox = new VBox(1);
/**
* 查询列表
*/
private ListView resultsListView = new ListView<>();
/**
* 存储内容
*/
private List contents = getContents();
/**
* 存储内容对应的拼音和拼音首字母
*/
private Map> pinyingMap = getPinYingMap(contents);
/**
* 搜索内容
*/
private String searchContent = "";
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
HBox hBox = new HBox(5);
Label searchLabel = new Label("搜索:");
// 标签文本向下移
searchLabel.setPadding(new Insets(5, 0, 0, 0));
queryTextField.setMaxWidth(80);
// 监听文本框输入值变化
queryTextField.textProperty().addListener(this::queryTextChange);
// 监听文本框焦点变化
queryTextField.focusedProperty().addListener(this::queryFocusedChange);
queryTextField.setOnKeyPressed(event -> {
handleKeyPressed(event);
});
resultsListView.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
// 双击搜索
if (e.getClickCount() == 2) {
saveSelectedInfo();
confirmSelectedResult();
}
// 单击选中
if (e.getClickCount() == 1) {
saveSelectedInfo();
}
});
resultsListView.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
handleKeyPressed(event);
});
resultsListView.setMaxWidth(80);
Button btn = new Button("搜索");
btn.setOnAction(event -> {
// 按钮点击搜索
confirmSelectedResult();
});
vBox.getChildren().add(queryTextField);
hBox.getChildren().addAll(searchLabel, vBox, btn);
// 使标签、文本框、按钮居于顶部
hBox.setAlignment(Pos.TOP_LEFT);
Pane pane = new Pane();
pane.getChildren().add(hBox);
pane.setPrefWidth(170);
pane.setPrefHeight(400);
// 点击面板,使面板获得焦点
pane.setOnMouseClicked(event -> pane.requestFocus());
primaryStage.setScene(new Scene(pane, 170, 400));
primaryStage.show();
}
/**
* 处理按键点击
*/
private void handleKeyPressed(KeyEvent event) {
if (event.getCode().equals(KeyCode.ENTER)) {
// Enter搜索
confirmSelectedResult();
}
// 可选的个数
int searchItemNum = resultsListView.getItems().size();
// 当前选中的列表项的索引
int selectedIndex = resultsListView.getSelectionModel().getSelectedIndex();
if (event.getCode().equals(KeyCode.UP) && (selectedIndex - 1) < searchItemNum) {
// 选择列表框中上一个
resultsListView.getSelectionModel().select(--selectedIndex);
saveSelectedInfo();
// 阻止原生事件进行,如文本框光标移动
event.consume();
}
if (event.getCode().equals(KeyCode.DOWN) && (selectedIndex + 1) > -1) {
// 选择列表框中下一个
resultsListView.getSelectionModel().select(++selectedIndex);
saveSelectedInfo();
// 阻止原生事件进行,如文本框光标移动
event.consume();
}
}
/**
* 保存选择的信息
*/
private void saveSelectedInfo() {
// 当前选中的列表项
searchContent = resultsListView.getSelectionModel().getSelectedItem();
}
private void queryFocusedChange(ObservableValue extends Boolean> observable, Boolean oldValue,
Boolean newValue) {
// 文本框失去焦点时,如果列表框未获得焦点,隐藏列表框
if (!newValue) {
if (!resultsListView.isFocused()) {
vBox.getChildren().remove(resultsListView);
}
} else {
searchResults(queryTextField.getText());
}
}
private void queryTextChange(ObservableValue extends String> observable, String oldValue, String newValue) {
searchResults(newValue);
}
private void searchResults(String searchText) {
clearQuery();
// 是否得到第一个搜索结果
boolean isNotHasFirstItem = true;
if (searchText.equals("")) {
for (Map.Entry> queryInfo : pinyingMap.entrySet()) {
resultsListView.getItems().add(queryInfo.getKey());
if (isNotHasFirstItem) {
// 存储第一个中文名
searchContent = queryInfo.getKey();
// 默认选中列表框中第一个
resultsListView.getSelectionModel().select(0);
isNotHasFirstItem = false;
}
}
}else{
isNotHasFirstItem = queryContents(searchText);
}
if (!isNotHasFirstItem) {
// 无滚动条下的展示个数
int showCount = resultsListView.getItems().size();
// 有滚动条下的展示个数
if (showCount > 16) {
showCount = 16;
}
// 显示列表框
vBox.getChildren().add(resultsListView);
resultsListView.setMaxHeight(22 * showCount);
}
}
/**
* 搜索,返回是否未第一次查到结果
*/
private Boolean queryContents(String intputText) {
// 过滤汉字
boolean isHanziPart = false;
// 过滤拼音
boolean isPinyinPart = false;
// 过滤拼音首字母组合
boolean isPinyinHeadPart = false;
boolean isNotHasFirstItem = true;
for (Map.Entry> queryInfo : pinyingMap.entrySet()) {
isHanziPart = Pattern.matches(intputText + ".*", queryInfo.getKey());
isPinyinPart = Pattern.matches(intputText + ".*", queryInfo.getValue().get(0));
isPinyinHeadPart = Pattern.matches(intputText + ".*", queryInfo.getValue().get(1));
if (isHanziPart || isPinyinPart || isPinyinHeadPart) {
resultsListView.getItems().add(queryInfo.getKey());
if (isNotHasFirstItem) {
// 存储第一个中文名
searchContent = queryInfo.getKey();
// 默认选中列表框中第一个
resultsListView.getSelectionModel().select(0);
isNotHasFirstItem = false;
}
}
}
return isNotHasFirstItem;
}
/**
* 清空内存中查询记录
*/
private void clearQuery() {
searchContent = "";
resultsListView.getItems().clear();
vBox.getChildren().remove(resultsListView);
}
/**
* 确定选择结果并搜索
*/
private void confirmSelectedResult() {
queryTextField.setText(searchContent);
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("正在搜索:" + searchContent);
alert.setContentText("弹框对应confirmSelectedResult()方法");
alert.show();
}
private List getContents() {
List contents = new ArrayList<>();
contents.add("苹果");
contents.add("橙子");
contents.add("猕猴桃");
contents.add("香瓜");
contents.add("向日葵");
contents.add("西红柿");
contents.add("西瓜");
return contents;
}
private Map> getPinYingMap(List contents) {
Map> info = new LinkedHashMap<>();
Collections.sort(contents, (String s1, String s2) -> Collator.getInstance(Locale.CHINESE).compare(s1, s2));
for (int i = 0; i < contents.size(); i++) {
String content = contents.get(i);
String pinying = PinYinTool.getPinYinString(content);
String pingyingHead = PinYinTool.getPinYinHeadString(content);
Vector pinyinInfo = new Vector();
pinyinInfo.add(pinying);
pinyinInfo.add(pingyingHead);
info.put(content, pinyinInfo);
}
return info;
}
}
完整工程下载(工程中为非改良版,非改良版到改良版,只需替换SearchTest类):
https://download.csdn.net/download/haoranhaoshi/10889627