2017-01-28 1 views
0

'+'버튼을 클릭 이벤트에 따라 동적으로 JTextField을 만듭니다. 아래는 스크린 샷입니다. 나는, '+'버튼을 생성 필드를 클릭하지만 JFrame에 표시하지 않을 경우이벤트 JFrame에서 동적 JTextField 생성

enter image description here

문제입니다. '항목 이름'아래의 다음 행에 커서를 놓으면 텍스트 필드가 표시됩니다.

어디에 문제가 있습니까?

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

사용 A ['CardLayout' (http://download.oracle.com/javase/8/ docs/api/java/awt/CardLayout.html)에 나와있는 것처럼 [this answer] (http://stackoverflow.com/a/5786005/418556). –

답변

3

컨테이너에 부품을 추가 한 후 repaint()으로 전화해야합니다. 또한 revalidate()도 호출해야합니다. repaint를 호출하기 전에 레이아웃 관리자에게 새 구성 요소의 레이아웃을 알려주지 만 실제로는 수행하지 않으려는 null 레이아웃을 사용하고 있기 때문입니다.

그래서 내 제안 중 1) 2) 네, 앤드류 톰슨은 예리하게 권장으로 의견을 교환하는 Cardlayout를 사용하여 적절한 레이아웃 관리자와 중첩 된 JPanel의를 사용하여 구성 요소를 추가하거나 제거 후 용기에 revalidaterepaint 전화하거나하는 것입니다 . 두 번째 JPanel에 이전 JPanel과 동일한 Document를 사용하는 JTextField가있을 수 있으므로 두 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이이 GUI를위한 더 깨끗한 솔루션이 아닐지 궁금하다. –