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

Swing项目:ShapeTwenty中JTextField不可见,无法向JTable传数据

问题分析

1. ShapeTwenty中重复添加文本框导致布局异常

在ShapeTwenty构造函数里连续执行了两次add(txtLength):

this.add(txtLength);
add(txtLength, gbc);

Swing组件无法被重复添加到同一容器,第二次添加会强制移除原位置的组件并重新添加,干扰布局管理器的计算逻辑,直接导致文本框无法正常渲染。

2. 窗口尺寸限制导致文本框被遮挡

打开ShapeTwenty窗口时,给JDialog设置了230x150的固定首选尺寸,但ShapeTwenty面板自身的首选尺寸是300x200,窗口尺寸小于面板,导致包括文本框在内的部分组件被裁剪到可视区域外。

3. 数据获取时误用新实例

在CreateRebar的addBar按钮监听中,重新创建了ShapeTwenty实例:

ShapeTwenty shapeTwenty = new ShapeTwenty();
String obj = shapeTwenty.getTxtLength().getText();

这会获取新实例的默认文本值("A"),而非用户在之前打开的窗口中输入的内容,完全无法传递有效数据。


修复后的代码

1. 修正ShapeTwenty类

移除重复添加逻辑,调整布局约束确保文本框显示正常:

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

public class ShapeTwenty extends JPanel {
    private JTextField txtLength = new JTextField(3);

    public ShapeTwenty() {
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        setBorder(BorderFactory.createTitledBorder("20"));
        
        // 仅添加一次文本框,设置约束让它居中显示
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = new Insets(10, 10, 10, 10);
        add(txtLength, gbc);
        
        txtLength.setText("A");
        txtLength.setHorizontalAlignment(SwingConstants.CENTER);
        txtLength.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Window w = SwingUtilities.getWindowAncestor(ShapeTwenty.this);
                w.setVisible(false);
            }
        });
    }

    public JTextField getTxtLength() {
        return txtLength;
    }

    public void setTxtLength(JTextField txtLength) {
        this.txtLength = txtLength;
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(300, 200);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHints(rh);
        g2.setColor(Color.black);
        g2.setStroke(new BasicStroke(2));
        g2.drawLine(20, 65, 170, 65);
    }
}

2. 修正CreateRebar类

移除窗口固定尺寸,使用pack()自动适配;调用类成员实例获取用户输入:

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

public class CreateRebar extends JPanel {
    private ShapeTwenty shapeTwenty = new ShapeTwenty();
    String[] diaSizes = {"20", "32"};
    JComboBox cmbDia = new JComboBox(diaSizes);
    JTextField txtMark = new JTextField(3);
    JLabel lblMark = new JLabel("Add Bar Mark");
    JLabel lblLength = new JLabel("Select Shape");
    JButton addBar = new JButton("Add Rebar");
    
    public CreateRebar() {
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.weightx = 0.1;
        gbc.weighty = 0.1;
        gbc.insets = new Insets(5, 5, 5, 5);
        
        add(lblMark, gbc);
        
        gbc.gridx = 0;
        gbc.gridy = 1;
        add(lblLength, gbc);
        
        gbc.gridx = 1;
        gbc.gridy = 0;
        add(txtMark, gbc);
        
        gbc.gridx = 1;
        gbc.gridy = 1;
        add(cmbDia, gbc);
        
        gbc.gridx = 0;
        gbc.gridy = 2;
        add(addBar, gbc);
        
        cmbDia.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String type = (String) cmbDia.getSelectedItem();
                if (type.equals("20")) {
                    shapeTwenty.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
                    JDialog sDialog = new JDialog();
                    sDialog.setTitle("Shape 20");
                    sDialog.getContentPane().setLayout(new GridBagLayout());
                    GridBagConstraints gbcDialog = new GridBagConstraints();
                    gbcDialog.insets = new Insets(5, 5, 5, 5);
                    gbcDialog.fill = GridBagConstraints.BOTH;
                    gbcDialog.weightx = 1.0;
                    gbcDialog.weighty = 1.0;
                    sDialog.add(shapeTwenty, gbcDialog);
                    sDialog.setModal(true);
                    sDialog.pack(); // 自动适配面板尺寸
                    sDialog.setLocationRelativeTo(null);
                    sDialog.setVisible(true);
                }
            }
        });
        
        addBar.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (txtMark.getText().isEmpty()) {
                    JOptionPane.showMessageDialog(null, "Add Bar Mark");
                    return;
                }
                
                String mark = (String) cmbDia.getSelectedItem();
                if (mark.equals("20")) {
                    // 使用类成员的shapeTwenty实例获取用户输入
                    String lengthText = shapeTwenty.getTxtLength().getText();
                    String barMark = txtMark.getText();
                    Object[] row = {barMark, lengthText};
                    AppUI.addRebar(row);
                }
            }
        });
    }
}

3. 修正Gui类(支持动态添加行)

原代码使用固定数组创建JTable,无法动态更新,改为用DefaultTableModel实现:

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

public class Gui {
    private DefaultTableModel tableModel;

    public Gui() {
        JFrame frame = new JFrame();
        String data[][] = {};
        String column[] = {"Bar Mark", "Length"};
        tableModel = new DefaultTableModel(data, column);
        JTable table = new JTable(tableModel);
        table.setPreferredScrollableViewportSize(new Dimension(500, 500));
        JScrollPane pane = new JScrollPane(table);
        frame.getContentPane().add(pane, BorderLayout.NORTH);
        
        JButton button = new JButton("Create Rebar");
        frame.getContentPane().add(button, BorderLayout.SOUTH);
        
        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        // 注册Gui实例到AppUI,方便CreateRebar调用
        AppUI.setInstance(this);
        
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                CreateRebar createRebar = new CreateRebar();
                createRebar.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
                JDialog bDialog = new JDialog(frame, "Create Rebar", true);
                bDialog.getContentPane().setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.insets = new Insets(5, 5, 5, 5);
                gbc.fill = GridBagConstraints.BOTH;
                gbc.weightx = 1.0;
                gbc.weighty = 1.0;
                bDialog.add(createRebar, gbc);
                bDialog.pack();
                bDialog.setLocationRelativeTo(frame);
                bDialog.setVisible(true);
            }
        });
    }

    // 提供添加行的方法
    public void addRebar(Object[] row) {
        tableModel.addRow(row);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Gui());
    }

    // 静态内部类,用于传递数据
    public static class AppUI {
        private static Gui instance;

        public static void setInstance(Gui gui) {
            instance = gui;
        }

        public static void addRebar(Object[] row) {
            if (instance != null) {
                instance.addRebar(row);
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:10:30