汉字、拼音、拼音首字母的模糊查询(匹配左侧)完整示例,JavaFX方式

汉字、拼音、拼音首字母的模糊查询(匹配左侧)完整示例,JavaFX方式_第1张图片

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 observable, Boolean oldValue,
                                    Boolean newValue) {
        // 文本框失去焦点时,如果列表框未获得焦点,隐藏列表框
        if (!newValue) {
            if (!resultsListView.isFocused()) {
                vBox.getChildren().remove(resultsListView);
            }
        } else {
            searchResults(queryTextField.getText());
        }
    }

    private void queryTextChange(ObservableValue 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 observable, Boolean oldValue,
                                    Boolean newValue) {
        // 文本框失去焦点时,如果列表框未获得焦点,隐藏列表框
        if (!newValue) {
            if (!resultsListView.isFocused()) {
                vBox.getChildren().remove(resultsListView);
            }
        } else {
            searchResults(queryTextField.getText());
        }
    }

    private void queryTextChange(ObservableValue 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

你可能感兴趣的:(Java,#,JavaFX)