Java Swing如何固定JTextArea的百分比占比避免尺寸变动?
GridBagLayout下JTextArea因DocumentListener导致尺寸异常的解决方案
问题分析
你遇到的核心问题是:DocumentListener触发文本更新时,会间接触发容器的布局重绘,而GridBagLayout在未明确约束组件最小/首选尺寸的情况下,会根据RSyntaxTextArea随内容变化的首选大小重新计算布局,导致左侧文本区域宽度异常拉伸或收缩。同时初始布局的权重设置比例错误,也加剧了布局计算的混乱。
解决步骤
1. 统一左侧组件布局
把两个文本区域放到同一个JPanel中,作为一个整体参与主布局,避免单个组件的尺寸变化影响整体40%的占比。
2. 锁定左侧容器尺寸
为左侧容器设置最小宽度和首选宽度(按窗口40%比例初始化),确保文本内容变化时不会突破宽度限制。
3. 修正布局权重比例
主布局中左侧容器weightx设为0.4,右侧列表设为0.6,严格对应40%/60%的占比需求。
4. 优化文本更新逻辑
在DocumentListener中用SwingUtilities.invokeLater延迟更新字数标签,避免同步触发布局重绘。
修改后的完整代码
package jlist.demo; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rtextarea.RTextArea; import org.fife.ui.rtextarea.RTextScrollPane; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.*; public class TestWinFrame2 extends JFrame { RTextArea textArea; RTextScrollPane scrollForTextArea; RTextArea textArea2; RTextScrollPane ScrollForTextArea2; JPanel leftPanel; // 左侧统一容器 JList jList; JScrollPane listScrollPane; JLabel wordNumberLabel; JToolBar toolBar; public TestWinFrame2() { GridBagLayout gridBagLayout = new GridBagLayout(); setLayout(gridBagLayout); // 工具栏布局 toolBar = new JToolBar(JToolBar.HORIZONTAL); GridBagConstraints bag = new GridBagConstraints(); bag.anchor = GridBagConstraints.NORTHWEST; bag.gridx = 0; bag.gridy = 0; bag.gridheight = 1; bag.gridwidth = 2; bag.weightx = 1.0; bag.fill = GridBagConstraints.HORIZONTAL; wordNumberLabel = new JLabel("word-count"); toolBar.add(wordNumberLabel); add(toolBar, bag); // 左侧容器布局 leftPanel = new JPanel(new GridBagLayout()); GridBagConstraints leftGbc = new GridBagConstraints(); leftGbc.fill = GridBagConstraints.BOTH; leftGbc.weightx = 1.0; leftGbc.weighty = 0.5; leftGbc.gridx = 0; // 第一个文本区域 textArea = new RSyntaxTextArea(); textArea.setLineWrap(true); textArea.setWrapStyleWord(true); scrollForTextArea = new RTextScrollPane(textArea); leftGbc.gridy = 0; leftPanel.add(scrollForTextArea, leftGbc); // 第二个文本区域 textArea2 = new RSyntaxTextArea(); textArea2.setLineWrap(true); textArea2.setWrapStyleWord(true); ScrollForTextArea2 = new RTextScrollPane(textArea2); leftGbc.gridy = 1; leftPanel.add(ScrollForTextArea2, leftGbc); // 锁定左侧容器最小宽度 int initLeftWidth = (int) (1200 * 0.4); leftPanel.setMinimumSize(new Dimension(initLeftWidth, 0)); leftPanel.setPreferredSize(new Dimension(initLeftWidth, 0)); // 左侧容器加入主布局 GridBagConstraints gbcLeftPanel = new GridBagConstraints(); gbcLeftPanel.anchor = GridBagConstraints.WEST; gbcLeftPanel.fill = GridBagConstraints.BOTH; gbcLeftPanel.gridx = 0; gbcLeftPanel.gridy = 1; gbcLeftPanel.gridheight = 2; gbcLeftPanel.gridwidth = 1; gbcLeftPanel.weightx = 0.4d; gbcLeftPanel.weighty = 1.0d; add(leftPanel, gbcLeftPanel); // 右侧列表布局 jList = new JList(); listScrollPane = new JScrollPane(jList); GridBagConstraints gbc_listScrollPane = new GridBagConstraints(); gbc_listScrollPane.anchor = GridBagConstraints.WEST; gbc_listScrollPane.fill = GridBagConstraints.BOTH; gbc_listScrollPane.gridx = 1; gbc_listScrollPane.gridy = 1; gbc_listScrollPane.gridheight = 2; gbc_listScrollPane.gridwidth = 1; gbc_listScrollPane.weightx = 0.6d; gbc_listScrollPane.weighty = 1.0d; add(listScrollPane, gbc_listScrollPane); // 添加文本监听 textAreaAddInsertListener(); setSize(1200, 800); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } public void textAreaAddInsertListener() { textArea.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { updateWordCount(); } @Override public void removeUpdate(DocumentEvent e) { updateWordCount(); } @Override public void changedUpdate(DocumentEvent e) { updateWordCount(); } private void updateWordCount() { SwingUtilities.invokeLater(() -> { wordNumberLabel.setText(String.valueOf(textArea.getText().length())); }); } }); } public static void main(String[] args) { SwingUtilities.invokeLater(TestWinFrame2::new); } }
关键修改说明
- 用
leftPanel统一管理左侧两个文本区域,避免单个组件尺寸变化干扰整体布局比例。 - 为
leftPanel设置固定最小宽度,阻止文本内容变化引发的宽度异常。 - 修正主布局
weightx比例,确保左右区域严格按40%/60%分配宽度。 - 延迟更新字数标签,避免在文档事件处理中同步触发布局重绘,减少不必要的布局计算。
内容的提问来源于stack exchange,提问作者apython
相关产品推荐
相关产品推荐

