【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年中华人民共和国县以上行政区划代码 国家区划数据

在这里插入图片描述

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

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

相关文章

【数据结构】二叉树OJ题目

965. 单值二叉树 如果二叉树每个节点都具有相同的值&#xff0c;那么该二叉树就是单值二叉树。 只有给定的树是单值二叉树时&#xff0c;才返回 true&#xff1b;否则返回 false。 示例 1&#xff1a; 输入&#xff1a;[1,1,1,1,1,null,1] 输出&#xff1a;true示例 2&#x…

考研复试C语言篇

第一章 概述 1.1什么是程序 为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的合集。 1.4C语言的特点 代码级别的跨平台&#xff1a;由于标准的存在&#xff0c;使得几乎同样的C代码可用于多种操作系统&#xff0c;也适用于多种机型。使允许直接访问物理地址…

Java基础 - 9 - 集合进阶(一)

集合是一种容器&#xff0c;用来装数据的&#xff0c;类似于数组&#xff0c;但集合的大小可变&#xff0c;开发中非常常用 为了满足不同的业务场景需求&#xff0c;Java除了ArrayList还提供了很多不同特点的集合给我们选择 一. 集合的体系结构 集合可以分为两类&#xff1a;…

案例--某站视频爬取

众所周知&#xff0c;某站的视频是&#xff1a; 由视频和音频分开的。 所以我们进行获取&#xff0c;需要分别获得它的音频和视频数据&#xff0c;然后进行音视频合并。 这么多年了&#xff0c;某站还是老样子&#xff0c;只要加个防盗链就能绕过。&#xff08;防止403&#xf…

Git之版本回退

文章转载于&#xff1a;https://www.jianshu.com/p/3020740561a8 以前&#xff0c;如果是要去除某一块功能&#xff0c;我都是选择性删除&#xff0c;选择性注释&#xff0c;然后前后逻辑各种查看&#xff0c;各种比较。每一次&#xff0c;改完这些我总感觉心好累啊&#xff01…

Prompt进阶3:LangGPT(构建高性能质量Prompt策略和技巧2)--稳定高质量文案生成器

Prompt进阶3:LangGPT(构建高性能质量Prompt策略和技巧2)–稳定高质量文案生成器 1.LangGPT介绍 现有 Prompt 创建方法有如下缺点&#xff1a; 缺乏系统性&#xff1a;大多是细碎的规则&#xff0c;技巧&#xff0c;严重依赖个人经验缺乏灵活性&#xff1a;对他人分享的优质 …

数据结构 day2

1:思维导图 2&#xff1a;计算结构体大小 3&#xff1a;大小端存储 &#xff08;1&#xff09;&#xff1a;数据溢出 1 #include <stdio.h>2 #include <string.h>3 #include <stdlib.h>4 int main(int argc, const char *argv[])5 {6 short a 0x1234;…

STM32输入捕获频率和占空比proteus仿真失败

这次用了两天的时间来验证这个功能&#xff0c;虽然实验没有成功&#xff0c;但是也要记录一下&#xff0c;后面能解决了&#xff0c;回来再写上解决的办法&#xff1a; 这个程序最后的实验结果是读取到的CCR1和CCR2的值都是0&#xff0c;所以没有办法算出来频率和占空比。 还…

FPGA - 单总线协议(one-wire)

1&#xff0c;简介 单总线&#xff08;one-wire&#xff09;是美国 DALLAS 公司推出的外围串行扩展总线技术&#xff0c;与 SPI、I2C 等串行数据通信方式不同&#xff0c;它采用单根信号线&#xff0c;既传输时钟又传输数据&#xff0c;而且数据传输是双向的。它具有节省 I/O口…

数据结构中的平衡搜索树 --- 红黑树 (如何旋转与变色)

目录 红黑树的概念 红黑树的性质 红黑树节点的定义 红黑树的插入 1. 按照二叉搜索的树规则插入新节点 2. 检测新节点插入后&#xff0c;红黑树的性质是否造到破坏 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的农作物害虫检测系统(深度学习模型+UI界面+训练数据集)

摘要&#xff1a;开发农作物害虫检测系统对于提高农业生产效率和作物产量具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个农作物害虫检测系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&#xff0…

Linux——多线程

目录 线程概念 线程控制 线程创建 进程 vs 线程 线程异常 线程等待 线程终止 pthread_cancel 进程替换 线程分离 线程互斥 mutex mutex接口 mutex的理解 互斥锁的实现 可重入和线程安全 死锁 什么是死锁 死锁产生的必要条件 避免死锁 线程同步 概念 条件…

论坛管理系统|基于Spring Boot+ Mysql+Java+B/S架构的论坛管理系统设计与实现(可运行源码+数据库+设计文档+部署说明+视频演示)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 目录 前台功能效果图 管理员功能登录前台功能效果图 用户功能模块 系统功能设计 数据库E-R图设计 l…

webpack面试题

1、webpack是干什么的 Webpack是一个现代的JavaScript应用程序的静态模块打包工具。当webpack处理应用程序时&#xff0c;它会在内部构建一个依赖图&#xff0c;此依赖图对应映射到项目所需的每个模块&#xff0c;然后将所有这些模块打包成一个或多个bundle。Webpack的主要功能…

Java初阶数据结构队列的实现

1.队列的概念 1.队列就是相当于排队打饭 2.在排队的时候就有一个队头一个队尾。 3.从队尾进对头出 4.所以他的特点就是先进先出 所以我们可以用链表来实现 单链表实现要队尾进队头出{要有last 尾插头删} 双向链表实现效率高&#xff1a;不管从哪个地方当作队列都是可以的&…

HttpContext请求接收上下文模块设计与实现(http模块四)

目录 类功能 类定义 类实现 编译测试 类功能 类定义 // HttpContext接收请求上下文模块功能设计 typedef enum {RECV_HTTP_ERROR,RECV_HTTP_LINE,RECV_HTTP_HEAD,RECV_HTTP_BODY,RECV_HTTP_OVER } HttpRecvStatu;class HttpContext { private:int _resp_statu; …

Games101笔记-变换

Scale Reflection Shear Rotate 没有额外提示默认绕原点旋转 线性变换 Transiation 不属于线性变换&#xff0c;仿射变换 齐次坐标 二维的点和向量增加一个维度 点加点等于两个点的中点 所有的仿射变换都可以写成齐次坐标的形式 在表示二维情况下的仿射变换时&#…

Linux驱动分离与分层的简介

一. 简介 我们在前面几章编写的设备驱动都非常的简单&#xff0c;都是对 IO 进行最简单的读写操作。 像 I2C 、SPI 、 LCD 等这些复杂外设的驱动就不能这么去写了&#xff0c; Linux 系统要考虑到驱动的可重用性&#xff0c;因 此&#xff0c;提出了驱动的分离与分层这样的软…

Maven: There are test failures.(已解决)

问题解决办法 进行package打包时报错如下&#xff1a; 然后这些并不能看出是测试的哪里的问题&#xff0c;可以点击上一级进行查看更详细的错误&#xff0c;越向上日志越详细&#xff0c;可以看到是52行出了错误&#xff0c; 52对应代码如下&#xff1a; 原因是存在注册的测…

基于FPGA的图像锐化算法(USM)设计

免费获取源码请关注微信号《FPGA学习笔记册》&#xff01; 1.图像锐化算法说明 图像锐化算法在实际的图像处理应用很广泛&#xff0c;例如&#xff1a;医学成像、工业检测和军事领域等&#xff1b;它的作用就是将模糊的图像变的更加清晰。常用的图像锐化算法有拉普拉斯算子、s…