2011-08-08 87 views
23

當用戶單擊JDialog上的按鈕時,我無法將JComponents添加到JDialog。基本上我希望它看起來像這樣:將組件動態添加到JDialog

When the dialog is opened

然後,當用戶點擊「添加新字段」我希望它看起來像這樣:

After the user clicks "Add New Field"

我似乎無法到讓對話框添加新的JLabel或JTextField。任何人都可以將我指向正確的方向嗎?

編輯:這是「添加新字段」按鈕的操作(現在只需要嘗試標籤)。

@Action 
public void addNewField() 
{ 
    Container contentPane = getContentPane(); 
    JLabel label = new JLabel ("welkom"); 
    contentPane.add(label, BorderLayout.CENTER); 
} 

SOLUTION

我使用MRE的解決方案,並得到它的工作。這是我最後的功能:

@Action 
public void addNewField() 
{ 
    System.out.println("New Field..."); 
    Container contentPane = getContentPane(); 
    JLabel label = new JLabel ("welcome"); 
    label.setBounds(10,10,100,10); //some random value that I know is in my dialog 
    contentPane.add(label); 

    contentPane.validate(); 
    contentPane.repaint(); 
    this.pack(); 
} 

我的問題另外一個是我正在使用NetBeans的「自由設計」的佈局,這意味着我的標籤可能是在一些奇怪的位置,而不是在邊界被我的對話(只是猜測)。我用label.setBounds()解決了這個問題,這樣它就能準確顯示我想要的位置。

+0

請參閱編輯1我的答案。 –

+0

只有一個組件可以進入'BorderLayout.CENTER'(或者'BorderLayout.ANYTHING')。 –

+0

順便說一句 - 出於可用性的目的,「添加新字段」按鈕應該可能在新字段出現的位置之上。這樣用戶可以通過點擊5次按鈕來添加5個新字段(而不必在點擊過程中移動鼠標)。 –

回答

21

當動態添加/刪除容器中的組件時,必須在以後調用revalidate()/validate()repaint()。前者將強制容器重新佈置組件,後者將移除任何視覺「工件」。

+0

要清楚,我應該在什麼情況下調用revalidate()? JDialog沒有重新驗證方法?我假設你的意思是我需要重新驗證我添加的組件。 – NeilMonday

+0

@NeilMonday,在包含其他組件的JComponent上發佈'revalidate()',否則只需在'JDialog()'上調用'validate()'。 – mre

+0

revalidate() - 「當屬性值發生變化時,此組件會自動調用此方法,以便此組件的大小,位置或內部佈局受到影響。此自動更新與AWT不同,因爲程序通常不再需要調用驗證以獲取GUI的內容以更新...「 - Jdocs – Vort3x

11

我同意mre(1+給他的回答),但我還想補充說,添加或刪除組件後,您可能需要在JDialog上調用pack(),特別是如果對話框需要調整大小以適應組件因爲你的圖像表明可能會發生。

編輯1
例如與一個JFrame(但它的工作原理相同與一個JDialog):

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

import javax.swing.*; 

public class SwingFoo extends JPanel { 
    private JTextField nameField = new JTextField(10); 
    private JComboBox searchTermsCombo = new JComboBox(); 
    private JButton addNewFieldBtn = new JButton("Add New Field"); 
    private JButton submitBtn = new JButton("Submit"); 
    private JPanel centerPanel = new JPanel(new GridBagLayout()); 
    private int gridY = 0; 

    public SwingFoo() { 
     GridBagConstraints gbc = createGBC(0, gridY); 
     centerPanel.add(new JLabel("Name:"), gbc); 
     gbc = createGBC(1, gridY); 
     centerPanel.add(nameField, gbc);  
     gridY++; 

     gbc = createGBC(0, gridY); 
     centerPanel.add(new JLabel("Search Terms:"), gbc); 
     gbc = createGBC(1, gridY); 
     centerPanel.add(searchTermsCombo, gbc); 
     gridY++; 

     addNewFieldBtn.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      addNewFieldAction(e); 
     } 
     }); 

     JPanel bottomPanel = new JPanel(); 
     bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.PAGE_AXIS)); 
     JPanel addNewFieldPanel = new JPanel(new GridLayout(1, 0)); 
     addNewFieldPanel.add(addNewFieldBtn); 
     addNewFieldPanel.add(new JLabel()); 
     JPanel submitPanel = new JPanel(new BorderLayout()); 
     submitPanel.add(submitBtn); 
     bottomPanel.add(addNewFieldPanel); 
     bottomPanel.add(Box.createVerticalStrut(5)); 
     bottomPanel.add(submitPanel); 

     int eb = 8; 
     setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb)); 
     setLayout(new BorderLayout()); 
     add(centerPanel, BorderLayout.CENTER); 
     add(bottomPanel, BorderLayout.SOUTH); 
    } 

    private void addNewFieldAction(ActionEvent e) { 
     GridBagConstraints gbc = createGBC(0, gridY); 
     centerPanel.add(new JLabel("New Item:"), gbc); 
     gbc = createGBC(1, gridY); 
     centerPanel.add(new JTextField(10), gbc);  
     gridY++; 

     Window win = SwingUtilities.getWindowAncestor(addNewFieldBtn); 
     if (win != null) { 
     win.pack(); 
     win.setLocationRelativeTo(null); 
     } 
    } 

    private GridBagConstraints createGBC(int x, int y) { 
     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.gridx = x; 
     gbc.gridy = y; 
     gbc.gridwidth = 1; 
     gbc.gridheight = 1; 
     gbc.weightx = 1.0; 
     gbc.weighty = 1.0; 
     gbc.anchor = (x == 0) ? gbc.LINE_START : gbc.LINE_END; 
     gbc.fill = (x == 0) ? gbc.BOTH : gbc.HORIZONTAL; 
     gbc.insets = (x == 0) ? new Insets(5, 0, 5, 5) : new Insets(5, 5, 5, 0); 
     return gbc; 
    } 

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

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 
+1

'win.setLocationRelativeTo(null);'當我選擇添加一個新項目時,我會發現對話跳轉(回到 - 給定我經常將它們拖到屏幕的一側)到屏幕中間令人不安。 –

+0

謝謝,這也幫助我。如果我可以投票給我2個答案。 – NeilMonday

14

避免任何進一步discusion需要/非所需的任何方法...

通知:用於增加/去除了JComponents(簡單只是在一個行/列,並用相同Size on Screen結構)就足夠了剛剛動作JFrame.pack()

enter image description here

enter image description here

enter image description here

但對於標準Swing LayoutManagers中的一些標準所佈置的大多數完整GUI,則需要使用

revalidate(); 
repaint(); // required in most of cases 

例如一列

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JCheckBox; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.border.LineBorder; 

public class AddComponentsAtRuntime { 

    private JFrame f; 
    private JPanel panel; 
    private JCheckBox checkValidate, checkReValidate, checkRepaint, checkPack; 

    public AddComponentsAtRuntime() { 
     JButton b = new JButton(); 
     b.setBackground(Color.red); 
     b.setBorder(new LineBorder(Color.black, 2)); 
     b.setPreferredSize(new Dimension(600, 10)); 
     panel = new JPanel(new GridLayout(0, 1)); 
     panel.add(b); 
     f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(panel, "Center"); 
     f.add(getCheckBoxPanel(), "South"); 
     f.setLocation(200, 200); 
     f.pack(); 
     f.setVisible(true); 
    } 

    private JPanel getCheckBoxPanel() { 
     checkValidate = new JCheckBox("validate"); 
     checkValidate.setSelected(false); 
     checkReValidate = new JCheckBox("revalidate"); 
     checkReValidate.setSelected(false); 
     checkRepaint = new JCheckBox("repaint"); 
     checkRepaint.setSelected(false); 
     checkPack = new JCheckBox("pack"); 
     checkPack.setSelected(false); 
     JButton addComp = new JButton("Add New One"); 
     addComp.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       JButton b = new JButton(); 
       b.setBackground(Color.red); 
       b.setBorder(new LineBorder(Color.black, 2)); 
       b.setPreferredSize(new Dimension(600, 10)); 
       panel.add(b); 
       makeChange(); 
       System.out.println(" Components Count after Adds :" + panel.getComponentCount()); 
      } 
     }); 
     JButton removeComp = new JButton("Remove One"); 
     removeComp.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       int count = panel.getComponentCount(); 
       if (count > 0) { 
        panel.remove(0); 
       } 
       makeChange(); 
       System.out.println(" Components Count after Removes :" + panel.getComponentCount()); 
      } 
     }); 
     JPanel panel2 = new JPanel(); 
     panel2.add(checkValidate); 
     panel2.add(checkReValidate); 
     panel2.add(checkRepaint); 
     panel2.add(checkPack); 
     panel2.add(addComp); 
     panel2.add(removeComp); 
     return panel2; 
    } 

    private void makeChange() { 
     if (checkValidate.isSelected()) { 
      panel.validate(); 
     } 
     if (checkReValidate.isSelected()) { 
      panel.revalidate(); 
     } 
     if (checkRepaint.isSelected()) { 
      panel.repaint(); 
     } 
     if (checkPack.isSelected()) { 
      f.pack(); 
     } 
    } 

    public static void main(String[] args) { 
     AddComponentsAtRuntime makingChanges = new AddComponentsAtRuntime(); 
    } 
} 
+0

爲什麼我們需要使用repaint()?它會重新繪製先前創建的組件 –

+0

@Raj Trivedi默認情況下不需要未觸及的JComponets(包含所有內容),更適合與repaint()一起使用(錯誤和滯後在這裏有幾個線程) – mKorbel