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
相关产品推荐
相关产品推荐

