2017-01-28 16 views
0

Я динамически создаю JTextField на основе события click на кнопке «+». Ниже приведен снимок экрана.Динамическое создание JTextField в JFrame в событии

enter image description here

Проблема заключается в том, когда я нажимаю кнопку «+», поля, созданные, но не показаны на JFrame. Когда я помещаю курсор в следующую строку под «item Name», текстовое поле становится видимым.

В чем проблема?

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 текстовых поля отображались одновременно.

+0

Используйте [ 'CardLayout'] (http://download.oracle.com/javase/8/ docs/api/java/awt/CardLayout.html), как показано в [этом ответе] (http://stackoverflow.com/a/5786005/418556). –

ответ

3

Необходимо добавить repaint() в контейнер после добавления к нему компонента. Вы также должны позвонить по номеру revalidate(), прежде чем вызывать перерисовку, так как это говорит менеджерам компоновки о компоновке нового компонента, но вы используете нулевые макеты, чего вы действительно хотите избежать.

Поэтому мое предложение заключается либо 1) использовать вложенные JPanels с соответствующими менеджерами компоновки, и вызвать revalidate и repaint на контейнерах после добавления или удаления компонентов, или 2) да, использовать CardLayout поменять взгляды, как Эндрю Томпсон проницательно рекомендует , У вашего второго JPanel есть JTextField, который использует тот же документ, что и предыдущий JPanel, поэтому похоже, что оба используют тот же 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 + "]"; 
    } 

} 
+0

Для лучшей помощи подумайте о создании и публикации [mcve]. –

+1

* «Вы также ** должны ** вызывать ..» * 'pack()' в случае, если размер кадра не достаточно велик для размещения поля. В качестве альтернативы используйте макет карты и пакет при запуске (что я предпочитаю). –

+1

@AndrewThompson: да. Мне нужно задаться вопросом, не может ли JTable быть более чистым решением для этого графического интерфейса. –

 Смежные вопросы

  • Нет связанных вопросов^_^