当字体或文本大小改变时 JTextArea 改变其大小

问题描述

我是 Java 初学者,我正在尝试制作一个可以更改字体和文本大小的简单文本编辑器。虽然它有一个问题,即文本区域大小似乎在更改某些内容时固定为字体和文本大小,但它仍然有效。 我希望文本区域的大小始终相同。我在调试时发现文本区域的行和列永远不会改变

更改字体前的图像:

https://i.stack.imgur.com/83nzf.png

更改字体后的图像:

https://i.stack.imgur.com/9AA2j.png

完整代码

public class Run {
    public static void main(String args[]) {
        MainFrame main_frame = new MainFrame();
    }
}

public class MainFrame extends JFrame{

    private TextAreaPanel text_area_panel = new TextAreaPanel(60,20);
    private ComboBoxesPanel combo_Boxes_panel = new ComboBoxesPanel(this.text_area_panel);
    
    public MainFrame() {
        this.initUI();
    }
    
    private void initUI() {
        setLayout(new BorderLayout());
        add(combo_Boxes_panel,BorderLayout.norTH);
        add(text_area_panel,BorderLayout.CENTER);
        setSize(getToolkit().getScreenSize().width / 2,getToolkit().getScreenSize().height / 2);
        setLocation(getToolkit().getScreenSize().width / 4,getToolkit().getScreenSize().height / 4);
        setTitle("Simple Text Editor");
        setDefaultCloSEOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }
}

public class TextAreaPanel extends JPanel{
    
    private JTextArea text_area = new JTextArea();
    private JScrollPane scroll_text_area = new JScrollPane(text_area);
    
    public TextAreaPanel(int width,int height) {
        this.addComponets();
        setTextAreaSize(width,height);
    }
    
    private void addComponets() {
        add(scroll_text_area);
    }
    
    public void setTextAreaSize(int width,int height) {
        text_area.setRows(height);
        text_area.setColumns(width);
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        //setTextAreaSize(getWidth() / 15,getHeight() / 20);
    }
    
    public JTextArea getArea() {
        return this.text_area;
        }
}

public class ComboBoxesPanel extends JPanel{
    
    private String[] system_fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
    private Object[] sizes = {8,10,12,14,16,20,24,36,48};
    private JComboBox font_Box = new JComboBox(system_fonts);
    private JComboBox size_Box = new JComboBox(sizes);
    private TextAreaPanel text_area_panel;
    
    public ComboBoxesPanel(TextAreaPanel text_area_panel) {
        this.text_area_panel = text_area_panel;
        font_Box.addActionListener(font_listener);
        size_Box.addActionListener(size_listener);
        add(font_Box);
        add(size_Box);
    }
    
    private ActionListener font_listener = new ActionListener() {
        
        @Override
        public void actionPerformed(ActionEvent e) {
            
            (text_area_panel.getArea()).setFont(new Font((String)font_Box.getSelectedItem(),Font.PLAIN,(int)size_Box.getSelectedItem()));
        }
    };
    
    private ActionListener size_listener = new ActionListener() {
        
        @Override
        public void actionPerformed(ActionEvent e) {
            (text_area_panel.getArea()).setFont(new Font((String)font_Box.getSelectedItem(),(int)size_Box.getSelectedItem()));
        }
    };
    
}

有人知道如何解决这个问题吗?知道如何解决这个问题吗? 如果有人想提供帮助,还有我的 GitLab 存储库中的所有代码https://gitlab.com/RichardCG/simpletexteditor 谢谢。 :)

解决方法

首先,我将吹嘘一下你的变量名。

当您创建 JTextArea 时,您指定文本区域的“行/列”:

  1. 为什么在类中使用“宽度/高度”作为变量名?在 Swing 中,“宽度/高度”用于表示像素值。
  2. 为什么要更改变量的顺序?您指定“行、列”作为文本区域的参数。为什么要将参数顺序更改为“宽度,高度”。 “宽度”与“行”无关。

API 不一致时会令人困惑。

文字区域大小好像固定为字体和文字大小

正确,所有 Swing 组件都负责确定自己的首选大小。大小基于组件的属性。因此,当您更改字体或字体大小时,组件将重新计算其首选大小。

这是一件好事,因为它允许:

  1. 布局管理器正常工作
  2. 滚动窗格正常工作,因为滚动条会在需要时出现。

我希望文本区域的大小始终相同

您可以控制滚动窗格的大小,从而使文本区域保持大小,同时根据需要显示/隐藏滚动条。

在你类的构造函数中你可以添加:

int scrollBarSize = UIManager.getInt("ScrollBar.width");
Dimension d = text_area.getPreferredSize();
d.width += scrollBarSize;
d.height += scrollBarSize;
scroll_text_area.setPreferredSize(d);

这是可行的,因为 FlowLayout 尊重添加到面板的任何组件的首选大小。

然而,这不是一个好的解决方案。相反,您应该将编辑器设计为对用户更加友好。

对于我使用过的任何编辑器,编辑器组件会占用框架中的所有可用空间。因此,您可能有一个工具栏(在顶部)或状态栏(在底部),而编辑器会占用剩余空间。这允许编辑器大小随着用户调整框架大小而改变。

因此,通常在创建文本区域并将文本区域添加到 JScrollPane 时,您只需设置 JTextArea 的行/列。然后滚动窗格被添加到BorderLayout 的CENTER 上。框架,然后在使框架可见之前pack() 框架。

不需要 TextAreaPanel 类。