JFrame多次使用一个组件

时间:2014-02-19 13:56:48

标签: java swing jframe

我正在创建一个夹具程序。我有一个按钮CREATE的页面。当用户点击创建时,它会在下一页上添加一个新按钮。我怎么能得到它,以便当用户点击CREATE时,它会添加一个新按钮,前面的按钮向下移动50个像素(例如)。

createFixtures.setLayout(null);     //Create a new fixture panel components
        createPanelLabel.setBounds(160, 30, 500, 50);
        createPanelLabel.setFont(new Font("TimesRoman", Font.PLAIN, 50));
        createPanelLabel.setForeground(Color.WHITE);
        southBar4.setBounds(0, 730, 500, 1);
        northBar4.setBounds(0, 100, 500, 1);
        backButton2.setBounds(20, 750, 150, 60);
        createButton2.setBounds(320, 750, 150, 60);
        sportLabel.setBounds(30, 150, 500, 40);
        sportLabel.setFont(new Font("TimesRoman", Font.PLAIN, 35));
        sportLabel.setForeground(Color.WHITE);
        descriptionLabel.setBounds(30, 300, 500, 40);
        descriptionLabel.setFont(new Font("TimesRoman", Font.PLAIN, 35));
        descriptionLabel.setForeground(Color.WHITE);
        dateLabel.setBounds(30, 450, 500, 40);
        dateLabel.setFont(new Font("TimesRoman", Font.PLAIN, 35));
        dateLabel.setForeground(Color.WHITE);
        resultLabel.setBounds(30, 600, 500, 40);
        resultLabel.setFont(new Font("TimesRoman", Font.PLAIN, 35));
        resultLabel.setForeground(Color.WHITE);
        sportDropDown.setBounds(250, 150, 200, 40);
        descriptionField.setBounds(250, 300, 200, 100);
        descriptionField.setFont(new Font("TimesRoman", Font.PLAIN, 20));
        descriptionField.setLineWrap(true);
        descriptionField.setWrapStyleWord(true);
        createFixtures.add(southBar4);
        createFixtures.add(northBar4);
        createFixtures.add(createPanelLabel);
        createFixtures.add(backButton2);
        createFixtures.add(createButton2);
        createFixtures.add(sportLabel);
        createFixtures.add(descriptionLabel);
        createFixtures.add(dateLabel);
        createFixtures.add(resultLabel);
        createFixtures.add(sportDropDown);
        createFixtures.add(descriptionField);

container.add(fixtures, "2");   //Labels each panel with a number allowing me to call the number when switching panels also adds panels to main container
        container.add(loginPanel, "3");
        container.add(createFixtures, "4");
        container.add(editFixtures, "5");
        container.add(adminFixturesFootball, "6");
        container.add(adminFixturesSwimming, "7");
        container.add(adminFixturesTennis, "8");

createButton2.addActionListener(new ActionListener() {   //Back button listener, switches back to ADMIN fixtures panel
            @Override
            public void actionPerformed(ActionEvent e) {
                cardLayout.show(container, "6");
                String descriptionText = descriptionField.getText();
                fixtureDescButton.setText( descriptionText );
                fixtureDescButton2.setText( descriptionText );
            }
        });

1 个答案:

答案 0 :(得分:2)

同样,您应该创建一个创建JPanel的工厂方法。

即,

public JPanel createPanel(String buttonText, String dataOnPanel) {
  JPanel panel = new JPanel();
  JButton myButton = new JButton(buttonText);
  myButton.addActionListener(new ButtonListener());
  panel.add(myButton);
  // add jtextarea if need be with the dataOnPanel String,...

  return panel;
}

修改
你问

  

这有什么不同?

您无法将单个组件添加到多个容器,但您可以创建类似的组件并将它们添加到多个容器中。使用工厂方法可以执行此操作。有关您的问题的更多详细信息,请考虑创建并发布minimal, compilable, runnable example program


另外,您似乎在使用null布局并在组件上调用setBounds(...)。虽然这似乎是新手创建复杂GUI的更好方法,但这是一个谬论,你创建Swing GUI的次数越多,你学会尊重和使用布局管理器就越多,并且看到这些生物在创造灵活,美丽和创造方面有很大帮助。需要,复杂的GUI。


编辑2
注意:如果组件具有足够重要的独特行为,那么我同意nachokk,创建一个类来封装它,然后创建此类的实例而不是简单的工厂方法。


编辑3

关键是,虽然您不能多次向容器添加组件,但您可以添加多次使用相同模型的新组件,这几乎是一回事。您的组件的组件甚至可以共享相同的模型,例如,您的JButtons可以共享相同的Action,如果需要,您的JTextField可以使用相同的Document。


编辑4 你说:

  

每次用户点击CREATE时递增按钮的方法。所以它每次都会添加另一个按钮,但是它们会向下移动,而不是在同一个位置上产生。

这里的布局管理器很关键。使用按钮保存JPanels的容器需要使用布局管理器,该管理器将接受新的JPanel并将其放置在正确的位置。考虑:

  • 接受新JPanel的容器可以使用GridLayout(0,1) - 表示具有一列和可变行数的网格。
  • 使用JPanel将此GridLayout使用JPanel放入BorderLayout的BorderLayout.NORTH位置。这会将您的网格面板压缩到最小的合理尺寸,因此JPanels不会扩展。
  • 使用JPanel将BorderLayout放入JScrollPane。
  • 添加新的JPanel时,使用JPanel将其添加到GridLayout,然后使用JPanel在GridLayout上调用revalidate()repaint(),以便新的JPanel定位良好。
  • 同样,有关问题的详细信息,请考虑创建并发布minimal, compilable, runnable example program

编辑5
例如,我的MCVE

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;

import javax.swing.*;

@SuppressWarnings("serial")
public class GridButtons extends JPanel {
   private JPanel gridPanel = new JPanel(new GridLayout(0, 1));

   public GridButtons() {
      JPanel topPanel = new JPanel();
      topPanel.add(new JButton(new AddRowAction("Add Row")));

      JPanel middlePanel = new JPanel(new BorderLayout());
      middlePanel.add(gridPanel, BorderLayout.NORTH);
      JScrollPane scrollpane = new JScrollPane(middlePanel);
      scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
      scrollpane.setPreferredSize(new Dimension(400, 400)); 

      setLayout(new BorderLayout());
      add(topPanel, BorderLayout.NORTH);
      add(scrollpane, BorderLayout.CENTER);
   }

   private class AddRowAction extends AbstractAction {

      public AddRowAction(String name) {
         super(name);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         // my factory method here
         JPanel panel = new JPanel();
         panel.add(new JButton("Button"));
         panel.add(new JTextField(20));
         gridPanel.add(panel);
         gridPanel.revalidate();
         gridPanel.repaint();
      }

   }

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

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