带字体切换的简易文本编辑器开发:如何刷新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:
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); }Give ButtonPanel a reference to WriteArea
Add a setter method toButtonPanelto hold theWriteAreainstance:private WriteArea writeArea; public void setWriteArea(WriteArea writeArea) { this.writeArea = writeArea; }Connect the two components in Notepad
After creating both panels, passWriteAreatoButtonPanel:public Notepad(){ ButtonPanel buttonPanel = new ButtonPanel(); WriteArea writeArea = new WriteArea(buttonPanel); buttonPanel.setWriteArea(writeArea); // Add this line // Rest of your code stays the same... }Trigger the update in the ComboBox listener
Modify thefontListlistener 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:
Create a custom listener interface
package SimpleNotepad; public interface FontChangeListener { void onFontChanged(String newFontName); }Add listener support to ButtonPanel
LetButtonPanelmanage 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); } }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); } });Register WriteArea as a listener
UpdateWriteArea'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); }
其他代码问题和优化建议
Encapsulation improvements
ButtonPanel'smenuBaris package-private—change it toprivateand add a getter method (public JMenuBar getMenuBar()) instead of lettingNotepadaccess it directly.WriteArea'stextAreashould also beprivateto follow encapsulation best practices.
Unused variables
currentStyleandcurrentSizeinButtonPanelare defined but not used. Add listeners to their respectiveJComboBoxes and update the font with style/size when they change (modify theupdateFontmethod to accept style and size parameters).
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.
- Use English names for variables to improve readability for other developers (e.g.,
Default ComboBox selection
You setcurrentFont = "Arial", but thefontListComboBox doesn't default to this value. AddfontList.setSelectedItem(currentFont);right after creating the ComboBox to keep the variable and UI in sync.Swing thread safety
Great job usingSwingUtilities.invokeLaterin the main method! Keep this habit—all Swing component creation/modification should happen on the Event Dispatch Thread (EDT).
内容的提问来源于stack exchange,提问作者Suule

