【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() {@Overridepublic 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.mzph.cn/news/742783.shtml

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

相关文章

开源办公系统CRM管理系统

基于ThinkPHP6 Layui MySQL的企业办公系统。集成系统设置、人事管理、消息管理、审批管理、日常办公、客户管理、合同管理、项目管理、财务管理、电销接口集成、在线签章等模块。系统简约&#xff0c;易于功能扩展&#xff0c;方便二次开发。 服务器运行环境要求 PHP > 7.…

Mybatis Plus + Spring 分包配置 ClickHouse 和 Mysql 双数据源

目录 一、背景 二、各个配置文件总览&#xff08;文件位置因人而异&#xff09; 2.1 DataSourceConfig 2.2 MybatisClickHouseConfig &#xff08;ClickHouse 配置类&#xff09; 2.3 MybatisMysqlConfig&#xff08;Mysql 配置类&#xff09; 2.4 application.propertie…

《安富莱嵌入式周报》第334期:开源SEM扫描电子显微镜,自制编辑器并搭建嵌入式环境,免费产品设计审查服务,实用电子技术入门,USB资料汇总,UDS统一诊断

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版&#xff1a; https://www.bilibili.com/video/BV1om411Z714/ 《安富莱嵌入式周报》第334期&#xff1a;开源SEM…

ABCDE联合创始人和普通合伙人BMAN确认出席Hack .Summit() 2024

ABCDE联合创始人和普通合伙人BMAN确认出席Hack .Summit() 2024&#xff01; ABCDE联合创始人和普通合伙人BMAN确认出席由 Hack VC 主办&#xff0c;并由 AltLayer 和 Berachain 联合主办&#xff0c;与 SNZ 和数码港合作&#xff0c;由 Techub News 承办的Hack.Summit() 2024区…

【Paper Reading】6.RLHF-V 提出用RLHF的1.4k的数据微调显著降低MLLM的虚幻问题

分类 内容 论文题目 RLHF-V: Towards Trustworthy MLLMs via Behavior Alignment from Fine-grained Correctional Human Feedback 作者 作者团队&#xff1a;由来自清华大学和新加坡国立大学的研究者组成&#xff0c;包括Tianyu Yu, Yuan Yao, Haoye Zhang, Taiwen He, Y…

VB播放器(动态服务器获取歌词)-183-(代码+说明)

转载地址: http://www.3q2008.com/soft/search.asp?keyword183 VBASP vb动态从服务器读取歌词 VB asp交互 程序, 模式不一样, 与普通的MP3播放器不一样, 这个是可以实现歌词从服务器上查询功能的. 看好了在咨询 我可以給您演示 目  录 前  言 1 1 . 简述 2 1.1 开发…

阿里云国际DDoS高防接入配置最佳实践

业务接入DDoS高防产品后&#xff0c;可以将攻击流量引流到DDoS高防&#xff0c;有效避免业务在遭受大流量DDoS攻击时出现服务不可用的情况&#xff0c;确保源站服务器的稳定可靠。本文九河云的接入配置和防护策略最佳实践&#xff0c;在各类场景中使用DDoS高防更好地保护您的业…

Linux系统下基于VSCode和Cmake进行C++开发

目录 简介一、GCC编译器1.1创建cpp文件1.2编译过程1.3g重要编译参数 二、GDB调试器三、IDE-VScode3.1 VSCode常用快捷键3.2 swap测试 四、CMake4.1CMake介绍4.2 CMake语法特性介绍4.3 CMake重要指令和常用变量4.4 CMake编译流程4.5CMake代码实践 五、使用VSCode进行完整项目开发…

【JavaScript】面试手撕柯里化函数

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 引入柯里化定义实现快速使用柯里化的作用提高自由度bind函数 参考资料 引入 上周…

开源绘图工具 PlantUML 入门教程(常用于画类图、用例图、时序图等)

文章目录 一、类图二、用例图三、时序图 一、类图 类的UML图示 startuml skinparam classAttributeIconSize 0 class Dummy {-field1 : String#field2 : int~method1() : Stringmethod2() : void } enduml定义能见度&#xff08;可访问性&#xff09; startumlclass Dummy {-f…

ES6(一):let和const、模板字符串、函数默认值、剩余参数、扩展运算符、箭头函数

一、let和const声明变量 1.let没有变量提升&#xff0c;把let放下面打印不出来&#xff0c;放上面可以 <script>console.log(a);let a1;</script> 2.let是一个块级作用域,花括号里面声明的变量外面找不到 <script>console.log(b);if(true){let b1;}//und…

vscode插件开发-发布插件

安装vsce vsce是“Visual Studio Code Extensions”的缩写&#xff0c;是一个用于打包、发布和管理VS Code扩展的命令行工具。 确保您安装了Node.js。然后运行&#xff1a; npm install -g vscode/vsce 您可以使用vsce轻松打包和发布扩展&#xff1a; // 打包插件生成name…

一.java介绍和idea基础使用

java技术体系 Java技术体系说明Java SE(Java standard Edition):标准版Java技术的核心和基础Java EE(Java Enterprise Edition):企业版企业级应用开发的一套解决方案Java ME(Java Micro Edition):小型版针对移动设备应用的解决方案&#xff08;认可少&#xff0c;主要是安卓和…

目标跟踪SORT算法原理浅析

SORT算法 Simple Online and Realtime Tracking(SORT)是一个非常简单、有效、实用的多目标跟踪算法。在SORT中&#xff0c;仅仅通过IOU来进行匹配虽然速度非常快&#xff0c;但是ID switch依然非常严重。 SORT最大特点是基于Faster RCNN的目标检测方法&#xff0c;并利用卡尔…

Unity开发中Partial 详细使用案例

文章目录 **1. 分割大型类****2. 与 Unity 自动生成代码协同工作****3. 团队协作****4. 共享通用逻辑****5. 自定义编辑器相关代码****6. 配合 Unity 的 ScriptableObjects 使用****7. 多人协作与版本控制系统友好** 在 Unity 开发中&#xff0c; partial 关键字是 C# 语言提供…

【音视频开发】:RTSP服务器协议内容

一、什么是RTSP协议 RTSP是一个实时传输流协议&#xff0c;是一个应用层的协议。通常说的RTSP包括RTSP协议、RTP协议、RTCP协议。 RTSP协议&#xff1a;负责服务器与客户端之间的请求与相应RTP协议 &#xff1a;负责服务器与客户端之间传输媒体数据RTCP协议&#xff1a;负责提…

使用html+css制作一个发光立方体特效

使用htmlcss制作一个发光立方体特效 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Documen…

Acwing.4261 孤独的照片(贡献法)

题目 Farmer John 最近购入了 N 头新的奶牛&#xff0c;每头奶牛的品种是更赛牛&#xff08;Guernsey&#xff09;或荷斯坦牛&#xff08;Holstein&#xff09;之一。 奶牛目前排成一排&#xff0c;Farmer John 想要为每个连续不少于三头奶牛的序列拍摄一张照片。 然而&…

视觉信息处理与FPGA实现第三次作业-7人表决器

一、模块端口图 二、代码 timescale 1ns / 1nsmodule vote_7(person1,person2,person3,person4,person5,person6,person7,out); input person1,person2,person3,person4,person5,person6,person7 ; output out ; assi…

mac激活pycharm,python环境安装和包安装问题

1.PyCharm到官网下载就行 地址&#xff1a;Other Versions - PyCharm (jetbrains.com) 2.MacOS 下载python环境&#xff0c;地址&#xff1a; Python Releases for macOS | Python.org 3.PyCharm环境配置&#xff1a; 4. 如果包下载不下来可以换个源试试 pip install py…