前言:

马总给我提出计算器3.0新需求:可以在页面上输入一个组件,用户的组件库里面就多一个组件,用户就可以使用

一、解决方法:

1. 新增成员变量和初始化

// 新增的输入框
private InputBox newInputBox;
// 新增的组件面板
private JPanel newComponentsPanel;

newInputBox:用于用户输入自定义组件内容(数字或运算符)的输入框。
newComponentsPanel:用于展示用户通过输入框添加的自定义组件按钮。
2. 初始化界面组件方法,新增了以下部分:

 // 新增的输入组件面板JPanel newInputPanel = new JPanel();newInputPanel.setLayout(new FlowLayout(FlowLayout.LEFT));// 新增的标签JLabel newInputLabel = new JLabel("请添加组件:");newInputPanel.add(newInputLabel);// 新增的输入框newInputBox = new InputBox(inputBoxes.size() + 1);newInputPanel.add(newInputBox.getPanel());// 新增的添加组件按钮JButton addComponentButton = new JButton("添加组件");addComponentButton.addActionListener(e -> handleAddComponent());newInputPanel.add(addComponentButton);// 新增的组件标签JLabel newComponentsLabel = new JLabel("用户自定义组件:");newInputPanel.add(newComponentsLabel);// 新增的组件面板newComponentsPanel = new JPanel();newComponentsPanel.setLayout(new FlowLayout(FlowLayout.LEFT));// 为新增组件面板添加水平滚动条(当内容超出宽度时可滚动)JScrollPane scrollPane2 = new JScrollPane(newComponentsPanel);scrollPane2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);scrollPane2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);                                // 底部面板采用网格布局,4行1列,水平间距5,垂直间距2jp_below.setLayout(new GridLayout(4, 1,5,2));add(jp_below, BorderLayout.SOUTH);// 将按钮面板添加到底部面板第2行jp_below.add(buttonPanel);// 将新增组件面板的滚动面板添加到底部面板第3行jp_below.add(newInputPanel);jp_below.add(scrollPane2);

创建了一个新的面板newInputPanel,用于容纳所有新增组件。
添加了 “请添加组件:” 标签和自定义输入框newInputBox。
添加了 “添加组件” 按钮,点击后调用handleAddComponent()方法处理添加逻辑。
添加了 “新加的组件:” 标签和newComponentsPanel面板,用于显示用户添加的自定义组件按钮。并且为newComponentsPanel设置scrollPane2 滚动条。这样当 newComponentsPanel 中的自定义组件过多时,用户可以通过水平滚动条来查看所有组件。

新建了jp_below面板用于3行1列的布局,将按钮面板,新增组件面板,滚动条添加进来。使得不会相互覆盖,布局更美观。


3. 处理添加组件逻辑(handleAddComponent方法)
 

/*** 处理"添加组件"按钮的点击事件* - 验证用户输入是否为合法的数字或运算符* - 检查组件是否已存在* - 若合法且不存在则创建新按钮并添加到界面* - 若不合法或已存在则显示错误提示*/private void handleAddComponent() {// 获取用户在输入框中的内容并去除首尾空格String input = newInputBox.getText().trim();// 隐藏之前的错误提示newInputBox.hideError();// 验证输入是否为合法的数字或单个运算符if (!isNumber(input) && !isOperator(input)) {newInputBox.showError("输入数字或单个运算符");return;}// 检查组件是否已存在if (isComponentExists(input)) {newInputBox.showError("已经添加");return;}// 创建一个新按钮,文本为用户输入内容JButton newButton = new JButton(input);// 为按钮添加点击事件监听器newButton.addActionListener(e -> handleOperatorClick(input));// 设置按钮的右键菜单(支持删除功能)setupButtonContextMenu(newButton);// 将新按钮添加到"新加的组件"面板newComponentsPanel.add(newButton);// 重新验证面板布局并刷新显示newComponentsPanel.revalidate();newComponentsPanel.repaint();// 清空输入框并设置焦点newInputBox.setText("");newInputBox.requestFocus();}

获取用户在newInputBox中输入的内容,检查是否为数字或运算符。
如果是有效输入,创建一个新按钮,设置按钮文本为输入内容,并绑定点击事件(调用原有的handleOperatorClick方法)。
为按钮设置右键菜单(通过setupButtonContextMenu方法),支持删除操作。
将按钮添加到newComponentsPanel中并刷新界面。


4. 设置按钮右键菜单(setupButtonContextMenu方法)
 

/*** 为按钮设置右键菜单,支持删除功能*/private void setupButtonContextMenu(JButton button) {// 创建右键弹出菜单JPopupMenu popupMenu = new JPopupMenu();// 创建"删除"菜单项并添加点击事件处理JMenuItem deleteItem = new JMenuItem("删除");deleteItem.addActionListener(e -> {// 显示确认对话框,防止误操作int confirm = JOptionPane.showConfirmDialog(calculator3.this,"删除按钮 \"" + button.getText() + "\" 吗?","确认删除",JOptionPane.YES_NO_OPTION);// 用户确认后执行删除操作if (confirm == JOptionPane.YES_OPTION) {// 从面板移除按钮组件newComponentsPanel.remove(button);// 重新计算布局并刷新UInewComponentsPanel.revalidate();newComponentsPanel.repaint();}});// 将菜单项添加到弹出菜单popupMenu.add(deleteItem);// 为按钮添加鼠标监听器,处理右键触发逻辑button.addMouseListener(new MouseAdapter() {//鼠标按下事件处理:检测是否为右键触发条件@Overridepublic void mouseReleased(MouseEvent e) {if (e.isPopupTrigger()) {popupMenu.show(e.getComponent(), e.getX(), e.getY());}}});}

为自定义组件按钮创建右键菜单,包含 “删除” 选项。
点击删除时,检查是否已完成计算(避免修改已计算的表达式),并通过确认对话框验证是否删除
确认后从newComponentsPanel中移除按钮并刷新界面。

5、新增3.0版本按钮

// 创建版本3.0切换按钮JButton version3Button = new JButton("3.0");// 给版本2按钮绑定点击事件:显示3.0版本信息version3Button.addActionListener(e -> showVersionInfo(3));// 将版本按钮添加到版本面板versionPanel.add(version3Button);
//在showVersionInfo方法新增
else if (version == 3) {message = "3.0版本:\n增加用户自定义组件,";}// 显示信息对话框JOptionPane.showMessageDialog(this, message, "版本信息", JOptionPane.INFORMATION_MESSAGE);}

源码在:java实现计算器3.0源码-CSDN博客

二、小结

通过实现用户自定义功能,对JFrame有了更深的理解,在BorderLayout将容器分为五个区域,将新增组件的面板放到South区域,会覆盖原来的运算符组件面板。于是GridLayout布局管理器,可以将容器划分为规则的网格(行 × 列),便于添加面板。并且当用户自定义组件较多时,设置scrollPane 滚动条,用户可以通过水平滚动条来查看所有组件。在用户添加自定义组件时,会先检验是否为数字或者单个运算符和是否已经存在。校验合理后绑定点击事件(调用原有的handleOperatorClick方法)与原来的运算符组件有相同功能。

 

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

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

相关文章

PIG AI 全新升级:全新 MCP 能力加持,让企业级 AI 开发效率翻倍!

你是否曾为 AI 应用的开发门槛而头疼?调试代码耗费数小时、集成外部工具需要复杂配置、想要快速构建智能系统却不知从何下手…别担心!PIG AI 最新版本带来的 MCP(Model Context Protocol)能力,正为这些问题提供一站式解决方案。本文将带你深入浅出地了解这一重磅升级,手把…

Springboot+vue超市管理系统的设计与实现

文章目录前言详细视频演示具体实现截图后端框架SpringBoot前端框架Vue持久层框架MyBaits成功系统案例:代码参考数据库源码获取前言 博主介绍:CSDN特邀作者、985高校计算机专业毕业、现任某互联网大厂高级全栈开发工程师、Gitee/掘金/华为云/阿里云/GitHub等平台持续…

一文快速了解Docker和命令详解

本文让你快速了解Docker是什么的东西,在我们程序开发的时候到底有什么作用,为什么需要去学习它。本文章只是做一个简单的概述配套黑马课程让你快速了解、使用Docker。 一、什么是Docker? Docker是一个开源的容器化平台,允许开发者…

【GaussDB】如何从GaussDB发布包中提取出内核二进制文件

【GaussDB】如何从GaussDB发布包中提取出内核二进制文件 背景 GaussDB 从505和506版本起(前面的版本不清楚),华为官方不再提供用脚本安装GaussDB的方式(应该是基于运维交付标准化的角度考虑),仅支持使用T…

ETH 交易流程深度技术详解

概述在前面对 PolkaVM 和 Revive 的文章中,我们介绍了很多技术细节,开发工具。还对比 EVM,知道了 PolkaVM 的优势。很多同学还是对 Polkadot SDK 为什么可以运行 EVM 兼容的智能合约,以及交易处理的整个流程不太清楚。这篇文章将会…

【算法训练营Day17】二叉树part7

文章目录二叉树的最近公共祖先二叉搜索树的最近公共祖先二叉搜索树中的插入操作删除二叉搜索树中的节点二叉树的最近公共祖先 题目链接:236. 二叉树的最近公共祖先 解题逻辑: 最近公共祖先的定义为:对于有根树 T 的两个节点 p、q&#xff0c…

Vue插件与组件核心区别详解

在 Vue 中,插件(Plugin) 和 组件(Component) 是两种不同层次的概念,它们的主要区别如下:1. 组件 (Component) 定义: Vue 应用的基本构建单元,是可复用的 Vue 实例&#x…

基础NLP | 02 深度学习基本原理

文章目录 深度学习基本原理 数学基础 线代 numpy 常用操作 导数, 梯度 梯度下降法 梯度下降代码 GradientDescent.py 反向传播 完整的反向传播过程 权重更新方式 pytorch 网络结构 全连接层 (线性层) 例子 - 手动实现模拟一个线性层 DNNforward.py 激活函数 激活函数-Sigmoid…

MySQL面试题及详细答案 155道(001-020)

《前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs&…

Ansible安装与入门

目录 Ansible ansible任务执行模式 ansible执行流程 ansible命令执行过程(背会) ansible的安装方式 ansible的程序结构(yum安装为例) ansible的配置文件查找顺序(背会) 核心配置文件 ansible的配置…

【Spring】Spring Boot启动过程源码解析

目录 一、启动入口 二、SpringApplication的构造过程 2.1 设置应用类型 2.2 设置初始化器(Initializer) 2.2.1 获取BootstrapRegistryInitializer对象 2.2.2 获取ApplicationContextInitializer对象 2.3 设置监听器(Listener&#xff…

CDN架构全景图

CDN架构全景图 CDN(内容分发网络)是一种通过在全球范围内部署边缘节点服务器,将内容缓存至离用户最近的位置,从而加速内容分发、降低延迟并减轻源站压力的分布式网络架构。其核心设计目标是优化互联网内容传输效率,提升…

【pytest高阶】源码的走读方法及插件hook

一、pytest源码走读方法 依赖库认知篇 📦这是理解 pytest 源码的 “前菜”,先认识 3 个超重要的小伙伴:iniconfig 📄:像个 “文件小管家”,专门负责读取 ini 配置文件(比如 pytest 的配置&#…

算法训练营day32 动态规划理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

今天开始动态规划的部分! 其实说白了,动态规划我感觉就是找类似递归的规律, 动态规划理论基础 动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规…

基于神经网络的手写数字识别系统

基于神经网络的手写数字识别系统 结合模板匹配和神经网络两种方法进行手写数字识别。这个系统包括图像预处理、特征提取、神经网络训练和可视化分析。 %% 基于神经网络的手写数字识别系统%% 清理工作区 clear; clc; close all;%% 加载手写数字数据集 % 使用MATLAB自带的手写数字…

机器学习?一文看懂这门热门技术

🌟 什么是机器学习?一文看懂这门热门技术在人工智能(AI)的大潮中,机器学习(Machine Learning, ML) 无疑是最耀眼的明星之一。它让计算机具备了 “自我学习” 的能力,让自动驾驶、智能…

Spring的初始化钩子

1. PostConstruct JSR-250 标准注解(不是 Spring 独有),用来标记 Bean 初始化完成后要执行的方法。会在 Bean 的构造方法执行完、依赖注入完成后执行。 使用实例: Component public class Demo {PostConstructpublic void init() …

【AI】Java生态对接大语言模型:主流框架深度解析

文章目录1. Deep Java Library (DJL)2. LangChain4j(LLM)3. HuggingFace Inference API4. OpenAI Java Client技术对比矩阵架构设计建议在人工智能浪潮下,大语言模型(LLM)已成为技术核心。Java生态通过以下框架实现高效…

【06】C#入门到精通——C# 多个 .cs文件项目 同一项目下添加多个 .cs文件

文章目录1 单个 .cs文件2 创建 多个 .cs文件2.1 添加Hero类2.1 添加ShowInfo类2.3 关于命名空间的引用2.4 所有.cs文件代码3 test3项目文件下载1 单个 .cs文件 上一讲中 描述游戏中英雄的角色 所有代码在一个.cs文件中, 如果代码很多,类很多&#xff0…

【MySQL基础篇】:MySQL常用数据类型的选择逻辑与正确使用

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨ 文章所属专栏:MySQL篇–CSDN博客 文章目录数据类型1.数据类型分类2.数值类型int整形类型bit位类型float小…