在事件的JFrame中创建动态JTextField

时间:2017-01-28 17:52:27

标签: java swing jtextfield

我根据“+”按钮上的点击事件动态创建JTextField。以下是截图。

enter image description here

问题是,当我点击“+”按钮时,已创建但未在JFrame上显示的字段。当我将光标放在“项目名称”下的下一行时,文本字段变为可见。

问题出在哪里?

enter image description here

以下是我的代码。

CreateBill()
{

    jf = new JFrame("Create Bill");
    jf.getContentPane().setLayout(null);
    jf.setExtendedState(JFrame.MAXIMIZED_BOTH);
    jf.setBounds(0, 0, d1.width, d1.height);
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);



    createRow();  // This will create first row by default.
    jf.pack();
    jf.setVisible(true);

}


private void createRow() {

    textField = new JTextField();
    textField.setToolTipText("item name");
    textField.setBounds(143, 46+j, 288, 20);
    textField.setColumns(10);
    textField.getDocument().addDocumentListener(new DocumentListener()
    {

        @Override
        public void insertUpdate(DocumentEvent e) {
            updatePrice();

        }

        @Override
        public void removeUpdate(DocumentEvent e) {


        }

        @Override
        public void changedUpdate(DocumentEvent e) {
            updatePrice();

        }

    });

    AutoCompleteDecorator.decorate(textField, names, true);
    jf.getContentPane().add(comboComplete);
    jf.getContentPane().add(textField);
    comboComplete.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e)
        {
            String ItemSel = textField.getText().trim();
            for(Item s:items)
            {
                if(s.getItemName().equals(ItemSel))
                        {
                            textField_1.setText(String.valueOf(s.getUnitPrice()));
                        }
            }


        }
    });


    textFields.add(textField);
    textField_1 = new JTextField();
    textField_1.setEditable(false);
    textField_1.setBounds(639, 46+j, 175, 20);
    jf.getContentPane().add(textField_1);
    textField_1.setColumns(10);



    qty = new JTextField();
    qty.setBounds(455, 46+j, 156, 20);
    jf.getContentPane().add(qty);
    qty.setColumns(10);

    qty.getDocument().addDocumentListener(new DocumentListener()
    {

        @Override
        public void insertUpdate(DocumentEvent e) {
                getTotal();

        }

        @Override
        public void removeUpdate(DocumentEvent e) {


        }

        @Override
        public void changedUpdate(DocumentEvent e) {
            getTotal();

        }

    });

    textFields.add(qty);
    textFields.add(textField_1);


    textField_3 = new JTextField();
    textField_3.setEditable(false);
    textField_3.setBounds(1038, 46+j, 156, 20);
    jf.getContentPane().add(textField_3);

    textField_3.setColumns(10);



    textFields.add(textField_3);

    JButton button = new JButton("+");
    button.setBounds(1235, 45+j, 89, 23);
    jf.getContentPane().add(button);
    button.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("value of J"+j);
            createRow();                    // after pressing '+' button i am calling same method again. by changing value of j.

        }
    });

    j=j+22;

    jf.setVisible(true);

}

我希望我的所有4个文本字段同时显示。

1 个答案:

答案 0 :(得分:3)

在向其添加组件后,您需要在容器上调用repaint()。在调用重绘之前,你也调用revalidate(),因为这告诉布局管理器布局新组件,但是你使用的是null布局,你真的想避免这样做。

所以我的建议是:1)使用嵌套的JPanels和适当的布局管理器,并在添加或删除组件后在容器上调用revalidaterepaint,或者2)是的,使用Cardlayout来交换意见,正如安德鲁汤普森精明推荐的那样。你可以让你的第二个JPanel有一个JTextField,它使用与前一个JPanel相同的Document,所以看起来它们都使用相同的JTextField(作为顶级的JTextField)。

在进一步研究你的图像时,我不得不怀疑JTable是否可能是一个更好的解决方案。是的,在您开始使用布局管理器之后,在添加所有组件之后并在将其设置为可见之前,也请在顶级窗口上调用pack()

关于JTable实现的一个例子,有些东西......

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;

@SuppressWarnings("serial")
public class CreateRowGui extends JPanel {
    private static final Item[] ITEMS = { 
            new Item("Light Bulb", 2.00), 
            new Item("Toilet Paper", 3.00),
            new Item("Toothpaste", 1.50), 
            new Item("Aspirin", 3.75) };
    private ItemTableModel tableModel = new ItemTableModel();
    private JTable table = new JTable(tableModel);
    private AddRowAction addRowAction = new AddRowAction("Add Row", KeyEvent.VK_A);

    public CreateRowGui() {
        TableCellRenderer moneyRenderer = new DefaultTableCellRenderer() {
            private NumberFormat currFormat = NumberFormat.getCurrencyInstance();

            @Override
            protected void setValue(Object value) {
                if (value != null) {
                    value = currFormat.format(value);
                }
                super.setValue(value);
            }
        };
        table.getColumnModel().getColumn(2).setCellRenderer(moneyRenderer);
        table.getColumnModel().getColumn(3).setCellRenderer(moneyRenderer);

        JPanel btnPanel = new JPanel();
        btnPanel.add(new JButton(addRowAction));
        btnPanel.add(new JButton("Remove Row")); // TODO: need Action for this

        setLayout(new BorderLayout());
        add(new JScrollPane(table));
        add(btnPanel, BorderLayout.PAGE_END);
    }

    class AddRowAction extends AbstractAction {
        private NewRowPanel newRowPanel = new NewRowPanel(ITEMS);

        public AddRowAction(String name, int mnemonic) {
            super(name);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            newRowPanel.reset();
            int reply = JOptionPane.showConfirmDialog(table, 
                    newRowPanel.getMainPanel(), 
                    "Select Item and Quantity",
                    JOptionPane.OK_CANCEL_OPTION, 
                    JOptionPane.PLAIN_MESSAGE);
            if (reply == JOptionPane.OK_OPTION) {
                Item item = newRowPanel.getSelectedItem();
                int quantity = newRowPanel.getQuantity();
                tableModel.addRow(item, quantity);
            }
        }
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("CreateRowGui");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new CreateRowGui());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

class NewRowPanel {
    private JPanel mainPanel = new JPanel();
    private JComboBox<Item> itemsCombo;
    private JSpinner quantitySpinner = new JSpinner(new SpinnerNumberModel(0, 0, 20, 1));

    @SuppressWarnings("serial")
    public NewRowPanel(Item[] items) {
        itemsCombo = new JComboBox<>(items);
        itemsCombo.setRenderer(new DefaultListCellRenderer(){
            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
                    boolean cellHasFocus) {
                if (value != null) {
                    value = ((Item) value).getName();
                } else {
                    value = "";
                }
                return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            }
        });
        mainPanel.add(new JLabel("Item:"));
        mainPanel.add(itemsCombo);
        mainPanel.add(Box.createHorizontalStrut(15));
        mainPanel.add(new JLabel("Quantity"));
        mainPanel.add(quantitySpinner);
    }

    public void reset() {
        itemsCombo.setSelectedIndex(-1);
        quantitySpinner.setValue(0);
    }

    public JPanel getMainPanel() {
        return mainPanel;
    }

    public Item getSelectedItem() {
        return (Item) itemsCombo.getSelectedItem();
    }

    public int getQuantity() {
        return (int) quantitySpinner.getValue();
    }
}

class ItemTableModel extends AbstractTableModel {
    private static final String[] COL_NAMES = { "Item Name", "Quantity", "Unit Price", "Total" };
    private static final long serialVersionUID = 1L;
    private List<ItemWithCount> itemsWithCount = new ArrayList<>();

    @Override
    public int getColumnCount() {
        return 4;
    }

    @Override
    public int getRowCount() {
        return itemsWithCount.size();
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
        case 0:
            return super.getColumnClass(columnIndex);
        case 1:
            return Integer.class;
        case 2:
        case 3:
            return Double.class;
        }
        return super.getColumnClass(columnIndex);
    }

    @Override
    public String getColumnName(int column) {
        return COL_NAMES[column];
    }

    @Override
    public Object getValueAt(int row, int column) {
        ItemWithCount itemWithCount = itemsWithCount.get(row);
        switch (column) {
        case 0:
            return itemWithCount.getItem().getName();
        case 1:
            return itemWithCount.getCount();
        case 2:
            return itemWithCount.getItem().getUnitPrice();
        case 3:
            return itemWithCount.getCount() * itemWithCount.getItem().getUnitPrice();
        }
        return null;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        ItemWithCount itemWithCount = itemsWithCount.get(rowIndex);
        switch (columnIndex) {
        case 1:
            itemWithCount.setCount((int) aValue);
            fireTableRowsUpdated(rowIndex, rowIndex);
            break;

        default:
            break;
        }
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return columnIndex == 0 || columnIndex == 1;
    }

    public void addRow(Item item, int quantity) {
        ItemWithCount itemWithCount = new ItemWithCount(item, quantity);
        itemsWithCount.add(itemWithCount);
        int row = itemsWithCount.size() - 1;
        fireTableRowsInserted(row, row);
    }

    private class ItemWithCount {
        private Item item;
        private int count;

        public ItemWithCount(Item item, int count) {
            this.item = item;
            this.count = count;
        }

        public int getCount() {
            return count;
        }

        public void setCount(int count) {
            this.count = count;
        }

        public Item getItem() {
            return item;
        }

    }
}

class Item {
    private String name;
    private double unitPrice;

    public Item(String name, double unitPrice) {
        this.name = name;
        this.unitPrice = unitPrice;
    }

    public String getName() {
        return name;
    }

    public double getUnitPrice() {
        return unitPrice;
    }

    public void setUnitPrice(double unitPrice) {
        this.unitPrice = unitPrice;
    }

    @Override
    public String toString() {
        return "Item [name=" + name + ", unitPrice=" + unitPrice + "]";
    }

}