前言:
馬總給我提出計算器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方法)與原來的運算符組件有相同功能。