【Swing】Java Swing实现省市区选择编辑器

【Swing】Java Swing实现省市区选择编辑器

  • 1.需求描述
  • 2.需求实现
  • 3.效果展示

系统:Win10
JDK:1.8.0_351
IDEA:2022.3.3

1.需求描述

在公司的一个 Swing 的项目上需要实现一个选择省市区的编辑器,这还是第一次做这种编辑器,在前端实现各种地区选择编辑器都比较常见,反而是 Swing 实现还是第一次,故将结果记录下来。

2.需求实现

地区选择从原理上来看很简单,通过级联的方式,将某个对象的所属对象数据展示出来,比如先选择省,就将省下的市等数据展示出来再选。

在 Swing 里我选择使用JPopupMenu 的方式来展示省市区的选择,相对于JDialog 来说,JPopupMenu 的级联操作更加简单一点。

实现代码如下:

import com.lijinjiang.beautyeye.BeautyEyeLNFHelper;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description 地址选择器demo
 * @Author 03010430
 * @ModifyDate 2024/3/13 13:20
 */
public class CityPickerDemo {
    public static JTextField textField;
    public static JPopupMenu popupMenu;
    public static DefaultListModel<String> provinceModel;
    public static JList<String> provinceList;//省份列表
    public static DefaultListModel<String> cityModel;
    public static JList<String> cityList;//城市列表
    public static DefaultListModel<String> districtModel;
    public static JList<String> districtList;//区县列表
    public static boolean haveInit;//初始化完毕

    public static void main(String[] args) {
        try {
            BeautyEyeLNFHelper.frameBorderStyle = BeautyEyeLNFHelper.FrameBorderStyle.generalNoTranslucencyShadow;
            BeautyEyeLNFHelper.launchBeautyEyeLNF();
        } catch (Exception e) {
            e.printStackTrace();
        }
        JFrame frame = new JFrame();
        JPanel panel = new JPanel(null);
        JLabel label = new JLabel("选择地址");
        label.setBounds(10, 30, 80, 36);
        panel.add(label);
        textField = new JTextField();
        textField.setEditable(false);
        textField.setBounds(100, 30, 270, 36);
        textField.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                clickFieldAction();
            }
        });
        panel.add(textField);
        frame.add(panel);
        frame.setSize(400, 150);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置默认关闭操作
        frame.setVisible(true);
    }

    public static void clickFieldAction() {
        popupMenu = new JPopupMenu();//初始化菜单面板
        provinceModel = new DefaultListModel<>();
        provinceList = new JList<>(provinceModel);//省份列表
        cityModel = new DefaultListModel<>();
        cityList = new JList<>(cityModel);//城市列表
        districtModel = new DefaultListModel<>();
        districtList = new JList<>(districtModel);//区县列表
        haveInit = false;//初始化赋值

        popupMenu.setLayout(new GridLayout(1, 3));
        //添加省份模块
        JScrollPane scrollPane1 = new JScrollPane(provinceList);
        scrollPane1.setBorder(BorderFactory.createTitledBorder("省级"));
        popupMenu.add(scrollPane1);
        //添加城市模块
        JScrollPane scrollPane2 = new JScrollPane(cityList);
        scrollPane2.setBorder(BorderFactory.createTitledBorder("地级/县级"));
        popupMenu.add(scrollPane2);
        //添加区县模块
        JScrollPane scrollPane3 = new JScrollPane(districtList);
        scrollPane3.setBorder(BorderFactory.createTitledBorder("县级"));
        popupMenu.add(scrollPane3);

        String text = textField.getText();
        if (text != null && !text.isEmpty()) {
            initProvinceData();
            String[] arr = text.trim().split("/");
            if (arr.length > 0) {
                String oldProvince = arr[0];
                if (provinceModel.contains(oldProvince)) {
                    provinceList.setSelectedValue(oldProvince, true);
                }
                if (arr.length > 1) {
                    String oldCity = arr[1];
                    if (cityModel.contains(oldCity)) {
                        cityList.setSelectedValue(oldCity, true);
                    }
                    if (arr.length > 2) {
                        String oldDistrict = arr[2];
                        if (districtModel.contains(oldDistrict)) {
                            districtList.setSelectedValue(oldDistrict, true);
                        }
                    }
                }
            }
        } else {
            initProvinceData();//初始化省份列表
        }
        haveInit = true;//标识初始化结束
        showPopupMenu(textField, popupMenu);
    }

    //第一级:省级
    public static void initProvinceData() {
        try {
            List<String> list = getProvinceData();//模拟省份数据
            for (String str : list) {
                provinceModel.addElement(str);
            }
            //添加事件监听
            provinceList.addListSelectionListener(e -> {
                String province = provinceList.getSelectedValue();
                if (province != null && !province.isEmpty()) {
                    initCityData(province);
                }
            });
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    //第二级:地级/县级
    public static void initCityData(String province) {
        try {
            cityModel.removeAllElements();//清空城市数据
            districtModel.removeAllElements();//清空区县数据
            List<String> list = getCityData(province);//模拟城市数据
            if (haveInit && list.size() == 0) {
                //第二级没有数据时,直接第一级的数据填写上
                textField.setText(province);//取值
                popupMenu.setVisible(false); //隐藏菜单
                popupMenu.removeAll(); //移除所有菜单项
            } else {
                for (String str : list) {
                    cityModel.addElement(str);
                }
                //添加事件监听
                cityList.addListSelectionListener(e -> {
                    String selectedProvince = provinceList.getSelectedValue();
                    String selectedCity = cityList.getSelectedValue();
                    if (selectedCity != null && !selectedCity.isEmpty()) {
                        initDistrictData(selectedProvince, selectedCity);
                    }
                });
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    public static void initDistrictData(String province, String city) {
        try {
            districtModel.removeAllElements();//先清空区县数据
            List<String> list = getDistrictData(province,city);//模拟区县数据
            if (haveInit && list.size() == 0) {
                //区县没有数据时,直接将市的数据填写上
                String value = province + "/" + city;
                textField.setText(value);//取值
                popupMenu.setVisible(false); //隐藏菜单
                popupMenu.removeAll(); //移除所有菜单项
            } else {
                for (String str : list) {
                    districtModel.addElement(str);
                }
                //添加事件监听
                districtList.addListSelectionListener(e -> {
                    if (haveInit) {
                        String selectedDistrict = districtList.getSelectedValue();
                        if (selectedDistrict != null && !selectedDistrict.isEmpty()) {
                            String selectedProvince = provinceList.getSelectedValue();
                            String selectedCity = cityList.getSelectedValue();
                            String value = selectedProvince + "/" + selectedCity + "/" + selectedDistrict;
                            textField.setText(value);//取值
                            popupMenu.setVisible(false); //隐藏菜单
                            popupMenu.removeAll(); //移除所有菜单项
                        }
                    }
                });
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    //点击按钮事件,继承该类的编辑器都要复写改代码
    public static void showPopupMenu(JComponent parent, JPopupMenu popupMenu) {
        GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
        Rectangle maximumWindowBounds = graphicsEnvironment.getMaximumWindowBounds();
        double deskHeight = maximumWindowBounds.getHeight();//桌面高度(不包括任务栏)

        int width = parent.getWidth();
        if (width < 400) {
            width = 400;
        }
        popupMenu.setPreferredSize(new Dimension(width, 200));
        int popupMenuBottom = parent.getLocationOnScreen().y + parent.getHeight() + 200;

        if (deskHeight < popupMenuBottom) {//超出桌面高度显示在输入框上面
            popupMenu.show(parent, parent.getWidth() - width, -200);
        } else {
            popupMenu.show(parent, 0, parent.getHeight());
        }
    }

    //模拟省份数据
    private static List<String> getProvinceData() {
        List<String> list = new ArrayList<>();
        list.add("北京市");
        list.add("上海市");
        list.add("江西省");
        list.add("福建省");
        list.add("浙江省");
        list.add("江苏省");
        list.add("河北省");
        list.add("安徽省");
        list.add("台湾省");
        return list;
    }

    //模拟城市数据
    private static List<String> getCityData(String province) {
        List<String> list = new ArrayList<>();
        switch (province) {
            case "北京市": {
                list.add("东城区");
                list.add("西城区");
                list.add("朝阳区");
                break;
            }
            case "上海市": {
                list.add("黄浦区");
                list.add("徐汇区");
                list.add("长宁区");
                list.add("静安区");
                break;
            }
            case "江西省": {
                list.add("南昌市");
                list.add("景德镇市");
                list.add("萍乡市");
                list.add("九江市");
                list.add("新余市");
                list.add("鹰潭市");
                list.add("赣州市");
                list.add("吉安市");
                list.add("宜春市");
                list.add("抚州市");
                list.add("上饶市");
                break;
            }
            case "福建省": {
                list.add("福州市");
                list.add("厦门市");
                list.add("莆田市");
                break;
            }
            default:
                break;
        }
        return list;
    }

    private static List<String> getDistrictData(String province, String city) {
        List<String> list = new ArrayList<>();
        if ("江西省".equals(province)){
            if ("南昌市".equals(city)){
                list.add("东湖区");
                list.add("西湖区");
                list.add("青云谱区");
                list.add("青山湖区");
                list.add("新建区");
                list.add("红谷滩区");
                list.add("南昌县");
                list.add("安义县");
                list.add("进贤县");
            } else if ("上饶市".equals(city)){
                list.add("信州区");
                list.add("广丰区");
                list.add("广信区");
                list.add("玉山县");
                list.add("铅山县");
                list.add("横峰县");
                list.add("弋阳县");
                list.add("余干县");
                list.add("鄱阳县");
                list.add("万年县");
                list.add("婺源县");
                list.add("德兴市");
            }
        }
        return list;
    }
}

3.效果展示

我这里测试代码中的数据只模拟了一部分数据,在生产中根据实际接口获取数据。这里推荐使用 2022年中华人民共和国县以上行政区划代码 国家区划数据

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/274268.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第四百一十一回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"给geolocator插件提交问题的结果"相关的内容&#xff0c;本章回中将介绍自定义标题栏.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我…

Java基础-IO流

文章目录 1.文件1.基本介绍2.常用的文件操作1.创建文件的相关构造器和方法代码实例结果 2.获取文件相关信息代码实例结果 3.目录的删除和文件删除代码实例 2.IO流原理及分类IO流原理IO流分类 3.FileInputStream1.类图2.代码实例3.结果 4.FileOutputStream1.类图2.案例代码实例 …

全国农产品价格分析预测可视化系统设计与实现

全国农产品价格分析预测可视化系统设计与实现 【摘要】在当今信息化社会&#xff0c;数据的可视化已成为决策和分析的重要工具。尤其是在农业领域&#xff0c;了解和预测农产品价格趋势对于农民、政府和相关企业都至关重要。为了满足这一需求&#xff0c;设计并实现了全国农产…

Apache SeaTunnel MongoDB CDC 使用指南

随着数据驱动决策的重要性日益凸显&#xff0c;实时数据处理成为企业竞争力的关键。SeaTunnel MongoDB CDC(Change Data Capture) 源连接器的推出&#xff0c;为开发者提供了一个高效、灵活的工具&#xff0c;以实现对 MongoDB 数据库变更的实时捕获和处理。 本文将深入探讨该连…

3月19日做题

[NPUCTF2020]验证&#x1f40e; if (first && second && first.length second.length && first!second && md5(firstkeys[0]) md5(secondkeys[0]))用数组绕过first1&second[1] 这里正则规律过滤位(Math.) (?:Math(?:\.\w)?) : 匹配 …

详解命令docker run -d --name container_name -e TZ=Asia/Shanghai your_image

docker run 是Docker的主要命令&#xff0c;用于从镜像启动一个新的容器。下面详细解释并举例说明 -d, --name, -e TZ 参数的用法&#xff1a; -d 或 --detach&#xff1a; 这个标志告诉Docker以守护进程&#xff08;后台&#xff09;模式运行容器。这意味着当你执行 docker ru…

②免费AI软件开发工具测评:通义灵码 VS 码上飞

前言 我又双叒叕来测评了&#xff01;上次给大家带来的是iFlyCode和CodeFlying两款产品的测评&#xff0c;受到了大家的一致好评~ 今天咱就继续来聊聊&#xff0c;这次我们选的的对象是通义灵码和码上飞&#xff0c;从名字上也能看到出来这两款产品一定是跟软件开发有关系的&…

IPD集成产品开发:塑造企业未来竞争力的关键

随着市场竞争的日益激烈&#xff0c;企业对产品开发的要求也越来越高。如何在快速变化的市场环境中&#xff0c;既保证产品的批量生产效率&#xff0c;又满足客户的个性化需求&#xff0c;成为了企业面临的重要挑战。IPD&#xff08;集成产品开发&#xff09;模式&#xff0c;作…

Linux 常用操作命令大全

目录 一、命令大集合 1.1 whereis 1.2 which 1.3 sudo 1.4 grep 1.5 free 1.6 top 动态显示进程的状态 1.7 ps 静态显示进程信息 1.8 df 1.9 iostat 看IO性能状态 1.10 yum安装插件命令 1.11 rpm 1.12 scp远程拷贝 1.13 uname 二、linux网络命令 2.1 centos7 防火…

理论学习:with torch.no_grad()

如果不加上“with torch.no_grad():”&#xff0c;模型参数会发生改变吗&#xff1f; 如果不使用with torch.no_grad():&#xff0c;在进行模型推理&#xff08;即计算outputs_cls net(inputs[batch_size//2:])这一步&#xff09;时&#xff0c;模型参数不会发生改变&#xf…

#Ubuntu(修改root信息)

&#xff08;一&#xff09;发行版&#xff1a;Ubuntu16.04.7 &#xff08;二&#xff09;记录&#xff1a; &#xff08;1&#xff09;命令行终端&#xff1a; a.右键&#xff0c;open terminal b.快捷键 ctrlaltt &#xff08;2&#xff09;进行root修改 sudo passwd &a…

Gradle v8.5 笔记 - 从入门到进阶(基于 Kotlin DSL)

目录 一、前置说明 二、Gradle 启动&#xff01; 2.1、安装 2.2、初始化项目 2.3、gradle 项目目录介绍 2.4、Gradle 项目下载慢&#xff1f;&#xff08;万能解决办法&#xff09; 2.5、Gradle 常用命令 2.6、项目构建流程 2.7、设置文件&#xff08;settings.gradle.…

linux 安装常用软件

文件传输工具 sudo yum install –y lrzsz vim编辑器 sudo yum install -y vimDNS 查询 sudo yum install bind-utils用法可以参考文章 《掌握 DNS 查询技巧&#xff0c;dig 命令基本用法》 net-tools包 yum install net-tools -y简单用法&#xff1a; # 查看端口占用情况…

2024流星全自动网页生成系统重构版源码

2024流星全自动网页生成系统重构版源码 源码介绍 流星全自动网页生成系统重构版源码分享&#xff0c;所有模板经过精心审核与修改&#xff0c;完美兼容小屏手机大屏手机&#xff0c;以及各种平板端、电脑端和360浏览器、谷歌浏览器、火狐浏览器等等各大浏览器显示。 为用户使…

微信支付宝--充ChatGPTPLUS/openAI key

ChatGPT是人工智能技术驱动的自然语言处理工具&#xff0c;它能够基于在预训练阶段所见的模式和统计规律&#xff0c;来生成回答&#xff0c;还能根据聊天的上下文进行互动&#xff0c;真正像人类一样来聊天交流&#xff0c;甚至能完成撰写论文、邮件、脚本、文案、翻译、代码等…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Refresh)

可以进行页面下拉操作并显示刷新动效的容器组件。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 支持单个子组件。 从API version 11开始&#xff0c;Refresh子组件会跟随手势下拉而下移…

恒驰喜讯 | 亮相华为中国合作伙伴大会2024,荣膺最佳服务一致性奖等3大奖项

3月14日至15日&#xff0c;华为中国合作伙伴大会2024在深圳隆重召开。大会以“因聚而生&#xff0c;数智有为”为主题&#xff0c;面向数智化转型的浪潮&#xff0c;华为携手伙伴共同探讨如何通过强化“伙伴华为”体系&#xff0c;帮助客户抓住数智化转型的巨大机遇&#xff0c…

QT信号与槽实现方式

1、第一种实现方式 在QT开发工具UI界面先拖入按钮&#xff0c;然后鼠标右键拖入按钮&#xff0c;点击选中槽&#xff0c;在页面选着需要的信号&#xff0c;然后OK&#xff0c;随即将会跳转到类的.cpp文件&#xff0c;&#xff08;这种UI代码结合的方式&#xff0c;会自动去绑定…

医药工厂5G智能制造数字孪生可视化平台,推进医药企业数字化转型

医药工厂5G智能制造数字孪生可视化平台&#xff0c;推进医药企业数字化转型。随着科技的不断发展&#xff0c;数字化转型已成为医药企业不可或缺的一部分。5G智能制造医药工厂数字孪生可视化平台作为数字化转型的重要工具&#xff0c;正在逐步改变医药企业的生产方式和管理模式…
最新文章