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

带字体切换的简易文本编辑器开发:如何刷新WriteArea获取字体

解决字体切换后刷新WriteArea的问题 + 代码优化建议

Hey there! Let's start with your core issue: getting the updated font from ButtonPanel to refresh the text in WriteArea, then we'll walk through some other code improvements you can make.


核心问题:组件间的通信

Right now, your WriteArea only reads the currentFont once during initialization. When the user selects a new font in the JComboBox, ButtonPanel updates its own currentFont variable—but WriteArea has no way of knowing this change happened. We need a way to notify WriteArea when the font changes. Here are two straightforward solutions:

方法1:直接注入WriteArea引用(简单直接)

This is the easiest approach for small projects:

  1. Add an update method to WriteArea
    Add this method to let external components update the text area's font:

    public void updateFont(String fontName) {
        // Keep the existing style and size, only change the font family
        Font currentFont = textArea.getFont();
        Font newFont = new Font(fontName, currentFont.getStyle(), currentFont.getSize());
        textArea.setFont(newFont);
    }
    
  2. Give ButtonPanel a reference to WriteArea
    Add a setter method to ButtonPanel to hold the WriteArea instance:

    private WriteArea writeArea;
    
    public void setWriteArea(WriteArea writeArea) {
        this.writeArea = writeArea;
    }
    
  3. Connect the two components in Notepad
    After creating both panels, pass WriteArea to ButtonPanel:

    public Notepad(){
        ButtonPanel buttonPanel = new ButtonPanel();
        WriteArea writeArea = new WriteArea(buttonPanel);
        buttonPanel.setWriteArea(writeArea); // Add this line
        // Rest of your code stays the same...
    }
    
  4. Trigger the update in the ComboBox listener
    Modify the fontList listener to call the update method when a new font is selected:

    fontList.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            JComboBox comboBox = (JComboBox) e.getSource();
            currentFont = (String)comboBox.getSelectedItem();
            System.out.println(currentFont);
            // Notify WriteArea to update
            if (writeArea != null) {
                writeArea.updateFont(currentFont);
            }
        }
    });
    

方法2:自定义事件监听器(更解耦,适合扩展)

If you plan to add more components that need to react to font changes, this approach is more scalable:

  1. Create a custom listener interface

    package SimpleNotepad;
    
    public interface FontChangeListener {
        void onFontChanged(String newFontName);
    }
    
  2. Add listener support to ButtonPanel
    Let ButtonPanel manage a list of listeners and trigger events when the font changes:

    import java.util.ArrayList;
    import java.util.List;
    
    // ...
    
    private List<FontChangeListener> fontChangeListeners = new ArrayList<>();
    
    public void addFontChangeListener(FontChangeListener listener) {
        fontChangeListeners.add(listener);
    }
    
    private void fireFontChanged(String newFont) {
        for (FontChangeListener listener : fontChangeListeners) {
            listener.onFontChanged(newFont);
        }
    }
    
  3. Trigger the event in the ComboBox listener

    fontList.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            JComboBox comboBox = (JComboBox) e.getSource();
            currentFont = (String)comboBox.getSelectedItem();
            System.out.println(currentFont);
            // Fire the event to all listeners
            fireFontChanged(currentFont);
        }
    });
    
  4. Register WriteArea as a listener
    Update WriteArea's constructor to listen for font changes:

    public WriteArea(ButtonPanel buttonPanel){
        this.buttonPanel = buttonPanel;
        // Register the listener
        buttonPanel.addFontChangeListener(new FontChangeListener() {
            @Override
            public void onFontChanged(String newFontName) {
                updateFont(newFontName);
            }
        });
        // Initial font setup (same as before)
        String fontName = buttonPanel.getCurrentFont();
        Font font = new Font(fontName, Font.ITALIC, 12);
        textArea.setForeground(Color.WHITE);
        textArea.setBackground(Color.BLACK);
        textArea.setFont(font);
        JScrollPane scrollPane = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        add(scrollPane);
    }
    
    // Keep the updateFont method from method 1
    public void updateFont(String fontName) {
        Font currentFont = textArea.getFont();
        Font newFont = new Font(fontName, currentFont.getStyle(), currentFont.getSize());
        textArea.setFont(newFont);
    }
    

其他代码问题和优化建议

  1. Encapsulation improvements

    • ButtonPanel's menuBar is package-private—change it to private and add a getter method (public JMenuBar getMenuBar()) instead of letting Notepad access it directly.
    • WriteArea's textArea should also be private to follow encapsulation best practices.
  2. Unused variables

    • currentStyle and currentSize in ButtonPanel are defined but not used. Add listeners to their respective JComboBoxes and update the font with style/size when they change (modify the updateFont method to accept style and size parameters).
  3. Naming conventions

    • Use English names for variables to improve readability for other developers (e.g., menuZapisz → menuSave).
    • Make variable names more descriptive: fontStyle → fontStyleComboBox, fontSize → fontSizeComboBox.
  4. Default ComboBox selection
    You set currentFont = "Arial", but the fontList ComboBox doesn't default to this value. Add fontList.setSelectedItem(currentFont); right after creating the ComboBox to keep the variable and UI in sync.

  5. Swing thread safety
    Great job using SwingUtilities.invokeLater in the main method! Keep this habit—all Swing component creation/modification should happen on the Event Dispatch Thread (EDT).


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:48:16