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

news2024/11/18 11:33:49

【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.coloradmin.cn/o/1514981.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python--类与面向对象-2

一、对象在文本中的输出 class Person: def __init__(self,name,agg,live_value,money): self.namename self.aggagg self.live_valuelive_value self.moneymoney def describe(): print(%s的攻击力是%s%(self.name,self.agg)) pPerson(bob,10,10000,100) bPerson(tony,…

Python之装饰器

一&#xff1a;作用 在函数名以及函数体不改变的前提下&#xff0c;给一个函数附加一些额外代码 二、语法 三、举例子 两个功能函数 test1&#xff0c; test2 遵循 “开放封闭原则”&#xff0c; 已经写好的代码&#xff0c;尽可能不要修改。 如果想要新增功能&#xff0c;…

YOLOv5目标检测学习(5):源码解析之:推理部分dectet.py

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、导入相关包与路径、模块配置1.1 导入相关的python包1.2 获取当前文件的相对路径1.3 加载自定义模块1.4 总结 二、执行主体的main函数所以执行推理代码&…

Linux中YUM仓库的配置

Linux软件包的管理 YUM仓库是什么YUM的常用命令修改YUM源其实CentOS7已经对YUM做了优化 YUM仓库是什么 之前传统RPM的管理方式 可以简单理解为写Java的时候不用Maven管理 jar包都要自己手动去导入 去下载 但是配置好YUM仓库 就放佛在用Maven管理Java项目 基于RPM包管理 能够从…

temu英国电商市场洞察:2月份商品销售数据分析Python数据采集Api

文章目录 引言可视化分析数据展示商品类目占比分析销售额分析价格区间占比分析各类目新品占比分析 写在最后 引言 在美国市场稳步增长基础上&#xff0c;Temu也不断加快全球步伐&#xff0c;现已进入47个国家&#xff0c;光23年9月份就进驻了10个国家&#xff0c;创造单月扩张国…

Redis底层数据结构之Hash

文章目录 1. Redis底层hash编码格式2. Redis 6源码分析3. Redis 7源码分析 1. Redis底层hash编码格式 在redis6中hash的编码格式分别是ziplist&#xff08;压缩列表&#xff09;和hashtable&#xff0c;但在redis7中hash的编码格式变为了listpack&#xff08;紧凑列表&#xf…

HADOOP完全分布式搭建(饭制版)

HADOOP完全分布式搭建&#xff08;饭制版&#xff09; 1.虚拟机安装 安装系统 点击VMware Workstation左上角文件&#xff0c;新建虚拟机 选择自定义&#xff0c;点击下一步 点击下一步 选择稍后安装操作系统&#xff08;后续我们使用的操作系统为CentOS7&#xff09;,点击…

解决vue2+elementUI的下拉框出现自动校验的问题

问题&#xff1a; 总结原因是因为新增的时候&#xff0c;传了空值进去 可以这样子解决 this.formData.value && this.$set(this.model, this.formData.key, this.formData.value)这种是只有值存在的时候才会给他赋值&#xff0c;但是这只解决单选下拉框&#xff0c;…

SQLiteC/C++接口详细介绍之sqlite3类(五)

快速跳转文章列表&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;四&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;六&#xff09;&#xff08;未发表&#xff09; 14.sqlite3_busy_handle…

【STL】string各种函数的应用

1.string 基本赋值操作 string assign&#xff08;string str&#xff0c;int n&#xff09; string assign&#xff08;string str,int pos,int n&#xff09; 2.string存取字符操作 (at()) 注意&#xff1a;[ ]越界不会抛出异常&#xff0c;at越界会抛出异常 3.string拼接…

从零开始利用MATLAB进行FPGA设计(一):建立脉冲检测模型的Simulink模型1

文章灵感来源于MATLAB官方免费教程&#xff1a;HDL Coder Self-Guided Tutorial 考虑到MATLAB官网的英文看着慢&#xff0c;再加上视频讲解老印浓浓的咖喱味&#xff0c;我决定记录利用MATLAB&Simulink&SystemGenerator进行FPGA数字信号处理的学习过程。 在进行数字信…

vue学习笔记24-组件事件配合v-model使用

搜索时v-model绑定的search数据时时发生变化 watch侦听器时时监察变化&#xff0c;一旦数据发生变化 &#xff0c;就实时发送数据给父组件 子组件的完整代码&#xff1a; <template>搜索&#xff1a;<input type"text" v-model"search"> <…

如何把网站的http改成https?

想把网站从不安全的HTTP换成安全的HTTPS&#xff1f;来瞧瞧下面几步操作&#xff1a; 1.挑个SSL证书&#xff1a; - 根据你的网站情况&#xff08;比如就一个域名、多个域名还是啥域名都得管&#xff09;&#xff0c;找一款适合的SSL证书&#xff0c;有免费的DV&#xff08;验…

k8s-Istio服务网络 27

官网&#xff1a;https://istio.io/latest/zh/about/service-mesh/ Istio与k8s的区别 SpringCloud传统微服务结合k8s与Istio与k8s结合&#xff1a; Istio数据面&#xff1a;通过envoy以sidecar方式拦截svc的流量来进行治理。 Istio控制面&#xff1a;pilot list/watch APIserv…

【WSN覆盖优化】基于改进黏菌算法的无线传感器网络覆盖 WSN覆盖优化【Matlab代码#65】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第5节&#xff1a;资源获取】1. 改进SMA算法1.1 改进参数p1.2 混沌精英突变策略 2. WSN节点感知模型3. 部分代码展示4. 仿真结果展示5. 资源获取 【可更换其他算法&#xff0c;获取资源请见文章第5节&#xff1a;资源获取…

TypeScript(五)交叉类型,联合类型,映射类型

交叉类型 交叉类型是将多个类型合并为一个类型。可以把现有的多种类型叠加到一起成为一种类型&#xff0c;它包含了所需的所有类型的特性。使用符号 & 表示。交叉类型 A & B 表示&#xff0c;任何一个新类型必须同时属于 A 和 B&#xff0c;才属于交叉类型 A & B …

数据库基础知识超详细解析~‍(进阶/复习版)

文章目录 前言一、数据库的操作1.登入数据库2.创建数据库3.显示当前数据库4.使用数据库5.删除数据库 二、常用数据类型三、数据库的约束1约束类型2NULL约束3UNIQUE:唯一约束4DEFAULT&#xff1a;默认值约束5 PRIMARY KEY&#xff1a;主键约束6 FOREIGN KEY&#xff1a;外键约束…

MyBatis-Plus学习记录

目录 MyBatis-Plus快速入门 简介 快速入门 MyBatis-Plus核心功能 基于Mapper接口 CRUD 对比mybatis和mybatis-plus&#xff1a; CRUD方法介绍&#xff1a; 基于Service接口 CRUD 对比Mapper接口CRUD区别&#xff1a; 为什么要加强service层&#xff1a; 使用方式 CR…

【CSS颜色】

本文章属于学习笔记&#xff0c;在https://www.freecodecamp.org/chinese/learn/2022/responsive-web-design/中练习 三、CSS颜色 1、有两种主要的颜色模型:电子设备中使用的加性RGB(红、绿、蓝)模型和印刷品中使用的减色CMYK(青色、品红、黄色、黑色)模型。 使用RGB模型。这…

Ypay源支付6.9无授权聚合免签系统可运营源码

YPay是一款专为个人站长设计的聚合免签系统&#xff0c;YPay基于高性能的ThinkPHP 6.1.2 Layui PearAdmin架构&#xff0c;提供了实时监控和管理的功能&#xff0c;让您随时随地掌握系统运营情况。 说明 Ypay源支付6.9无授权聚合免签系统可运营源码 已搭建测试无加密版本…