You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JFrame下NameFrame类开发需求:绘图、蜂鸣提示及名称列表存储扩展

Alright, let's walk through implementing your NameFrame class step by step, covering all the required features including the missing persistence for your displayed names list. I'll break this down into core functionality first, then dive into the persistence options that fit best for this use case.

1. Core NameFrame Implementation

First, we'll build the basic Swing UI, wire up the "Graph" button logic, and handle the name search + feedback flow. We'll use an ArrayList<String> to track the displayed names as specified.

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

public class NameFrame extends JFrame {
    private JTextField nameInput;
    private JButton graphButton;
    private NameGraph nameGraph;
    private ArrayList<String> displayedNames;

    public NameFrame() {
        // Frame setup
        setTitle("Name Data Visualizer");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // We'll handle close for persistence
        setLayout(new BorderLayout());

        // Initialize displayed names storage
        displayedNames = new ArrayList<>();

        // Input panel (top)
        JPanel inputPanel = new JPanel();
        nameInput = new JTextField(25);
        graphButton = new JButton("Graph");
        inputPanel.add(new JLabel("Enter Name:"));
        inputPanel.add(nameInput);
        inputPanel.add(graphButton);
        add(inputPanel, BorderLayout.NORTH);

        // Graph rendering panel (center)
        nameGraph = new NameGraph(displayedNames);
        add(nameGraph, BorderLayout.CENTER);

        // Load persisted names on startup
        loadDisplayedNames();

        // Wire up button action
        graphButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String targetName = nameInput.getText().trim();
                if (targetName.isEmpty()) {
                    JOptionPane.showMessageDialog(NameFrame.this, "Please enter a valid name!");
                    return;
                }

                // Check if name exists in NameRecord
                boolean nameExists = NameRecord.hasDataForName(targetName); // Assume this method exists
                if (nameExists) {
                    // Avoid duplicate entries
                    if (!displayedNames.contains(targetName)) {
                        displayedNames.add(targetName);
                        nameGraph.repaint(); // Trigger graph update with new name
                    }
                } else {
                    // Trigger system beep and notify user
                    Toolkit.getDefaultToolkit().beep();
                    JOptionPane.showMessageDialog(NameFrame.this, "No data found for that name!");
                }
            }
        });

        // Handle window close to save data
        addWindowListener(new java.awt.event.WindowAdapter() {
            @Override
            public void windowClosing(java.awt.event.WindowEvent windowEvent) {
                saveDisplayedNames();
                System.exit(0);
            }
        });
    }

    public static void main(String[] args) {
        // Run UI on Swing's Event Dispatch Thread (EDT) for safety
        SwingUtilities.invokeLater(() -> {
            new NameFrame().setVisible(true);
        });
    }

    // Persistence methods will go here
}

Notes on Core Logic:

  • We set DO_NOTHING_ON_CLOSE so we can save the displayed names before exiting.
  • The NameRecord.hasDataForName() is a placeholder — replace this with your actual method to check if the name exists in your dataset.
  • NameGraph should accept the displayedNames list in its constructor and use it to render data in its paintComponent() method. Calling repaint() triggers a redraw when a new name is added.
2. Persistence for Displayed Names

Now let's add the persistence layer. We'll cover two common, simple options for saving/loading the ArrayList<String>:

Option 1: Plain Text/Properties File (Simple, Human-Readable)

This is great if you want the saved data to be editable manually. We'll use a properties file to store the names as a comma-separated string.

Add these methods to your NameFrame class:

import java.io.*;
import java.util.Properties;

private void loadDisplayedNames() {
    Properties props = new Properties();
    // Store file in user's home directory to avoid permission issues
    File saveFile = new File(System.getProperty("user.home") + File.separator + ".name_visualizer" + File.separator + "saved_names.properties");
    
    // Create directory if it doesn't exist
    saveFile.getParentFile().mkdirs();

    try (FileInputStream fis = new FileInputStream(saveFile)) {
        props.load(fis);
        String namesString = props.getProperty("displayed_names", "");
        if (!namesString.isEmpty()) {
            String[] namesArray = namesString.split(",");
            for (String name : namesArray) {
                displayedNames.add(name.trim());
            }
            nameGraph.repaint(); // Update graph with loaded names
        }
    } catch (IOException e) {
        // Ignore on first run (file won't exist yet) — or log the error
        System.out.println("No saved names found, starting fresh.");
    }
}

private void saveDisplayedNames() {
    Properties props = new Properties();
    File saveFile = new File(System.getProperty("user.home") + File.separator + ".name_visualizer" + File.separator + "saved_names.properties");
    saveFile.getParentFile().mkdirs();

    String namesString = String.join(",", displayedNames);
    props.setProperty("displayed_names", namesString);

    try (FileOutputStream fos = new FileOutputStream(saveFile)) {
        props.store(fos, "Saved names for Name Visualizer");
    } catch (IOException e) {
        JOptionPane.showMessageDialog(this, "Failed to save displayed names!");
        e.printStackTrace();
    }
}

Option 2: Object Serialization (Flexible for Future Changes)

If you might expand the data stored beyond just strings later, serialization is a better fit — it lets you save the entire ArrayList directly.

Replace the persistence methods above with these:

import java.io.*;

private void loadDisplayedNames() {
    File saveFile = new File(System.getProperty("user.home") + File.separator + ".name_visualizer" + File.separator + "saved_names.ser");
    saveFile.getParentFile().mkdirs();

    try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(saveFile))) {
        displayedNames = (ArrayList<String>) ois.readObject();
        nameGraph.repaint();
    } catch (IOException | ClassNotFoundException e) {
        System.out.println("No saved names found, starting fresh.");
    }
}

private void saveDisplayedNames() {
    File saveFile = new File(System.getProperty("user.home") + File.separator + ".name_visualizer" + File.separator + "saved_names.ser");
    saveFile.getParentFile().mkdirs();

    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(saveFile))) {
        oos.writeObject(displayedNames);
    } catch (IOException e) {
        JOptionPane.showMessageDialog(this, "Failed to save displayed names!");
        e.printStackTrace();
    }
}

Persistence Best Practices:

  • We save the file in the user's home directory (with a hidden folder) to avoid permission problems that can occur when writing to the program's installation directory.
  • Always handle exceptions gracefully — show user feedback instead of just printing stack traces in production code.
3. Final Checks
  • Swing Thread Safety: We use SwingUtilities.invokeLater() to launch the UI, which ensures all UI operations run on the EDT (critical for avoiding race conditions).
  • Duplicate Prevention: The code checks if a name is already in the list before adding it, so you won't have duplicate entries cluttering the graph.
  • Cross-Platform Beep: Toolkit.getDefaultToolkit().beep() works on Windows, macOS, and Linux, making it a reliable choice for the error feedback.

内容的提问来源于stack exchange,提问作者Yuhe Zhu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:56:31