Java Swing JLabels在buildGUI方法中显示,但如果从另一个方法添加则不显示

时间:2013-04-05 13:15:14

标签: java swing jlabel miglayout

我是一名业余爱好者,正在写射箭计分卡。该程序运行良好,但代价是18个相同代码的18个部分。我试图通过使用方法调用来压缩代码。 我正在使用Java SE6和Mig Layout

以下是GUI中的代码部分。 GUI名称如下所示

HomePage(包含主要方法) - > ChoiceGUI - > buildScoresPanel

    public  void buildScoresPanelMIG(JPanel scoresPanel) {        

    for (row = 0; row<(int)numberofrows; row++){  
       scoresPanel.add(scorelabel1[row],"gapleft 0,w 35px, hmin 35px,split 18");
       scoresPanel.add(scorelabel2[row],"gap before 0px,gapleft 0,w 35px, hmin 35px");
       scoresPanel.add(scorelabel3[row],"gap before 0px,gapleft 0,w 35px, hmin 35px");
       scoresPanel.add(scorelabel4[row],"gap before 0px,gapleft 0,w 35px, hmin 35px");
       scoresPanel.add(scorelabel5[row],"gap before 0px,gapleft 0,w 35px, hmin 35px");
       scoresPanel.add(scorelabel6[row],"gap before 0px,gapleft 0,w 35px, hmin 35px");
       //another 12 Jlabels              }
    }

但是,如果我将代码放在方法中并按下面的方式调用它,即使我尝试了revalidate()repaint()和setVisible(true),Jlabels也不会显示

    public  void buildScoresPanelMIG(JPanel scoresPanel) {

           for (row = 0; row<(int)numberofrows; row++){  

              addScoreLabels();

           }
    }

    public void addScoreLabels(){

     scoresPanel.add(scorelabel1[row],"gapleft 0,w 35px, hmin 35px,split 18");
     scoresPanel.add(scorelabel2[row],"gap before 0px,gapleft 0,w 35px, hmin 35px");
     scoresPanel.add(scorelabel3[row],"gap before 0px,gapleft 0,w 35px, hmin 35px");
     scoresPanel.add(scorelabel4[row],"gap before 0px,gapleft 0,w 35px, hmin 35px");
     scoresPanel.add(scorelabel5[row],"gap before 0px,gapleft 0,w 35px, hmin 35px");
     scoresPanel.add(scorelabel6[row],"gap before 0px,gapleft 0,w 35px, hmin 35px");
    //another 12 labels
     //scoresPanel.revalidate(); 
     //scoresPanel.repaint();
     //scoresPanel.setVisible(true);
  }

我已经在互联网上拖了一段时间试图解决这个问题,我意识到我对Swing组件的工作方式存在根本的误解,如果有人可以解释,我会很感激。

2 个答案:

答案 0 :(得分:1)

我认为您的组件限制是非法的(除了可能的其他原因)。这些是我设法找到的关于MigLayout的主要资源:

备忘单是你最好的朋友,但阅读白皮书并下载并查看用户友好的演示并不会有什么坏处。如果你查看备忘单,你会发现你基本上试图以几种不同的(可能是不兼容的)方式设置相同的东西。

我已经制作了一个SSCCE,用于从MigLayout托管的JPanel动态添加/删除标签。它是使用MigLayout 3.7.4构建的。

截图: MigLayout add remove debug test SSCCE

代码:

public class App extends JFrame {

public JPanel mainPanel;
public int addedCount = 1;
public final int initRowsCount = 8;
public final int columnsCount = 5;

public App() {
    super("MiGLayout test");
    initUI();       
}

private void redrawMainPanel() {        
    mainPanel.revalidate();
    mainPanel.repaint();
}

private JMenuBar initMenuBar() {
    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("test menu");
    JMenuItem removeMenuItem = new JMenuItem("remove a component");
    JMenuItem addMenuItem = new JMenuItem("add a component");
    JCheckBoxMenuItem debugMenuItem = new JCheckBoxMenuItem("debug mode");
    removeMenuItem.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            if (mainPanel.getComponentCount() > 0) {
                mainPanel.remove(mainPanel.getComponents()[mainPanel.getComponentCount() - 1]);
                --addedCount;
            }
            App.this.redrawMainPanel();
        }
    });
    addMenuItem.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            mainPanel.add(
                        initLabel(addedCount / columnsCount, addedCount % columnsCount), 
                        (addedCount % columnsCount == columnsCount - 1 ? "grow 35, wrap" : "grow 35")
                        );
            ++addedCount;
            App.this.redrawMainPanel();
        }
    });
    debugMenuItem.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            MigLayout migLayout = ((MigLayout)mainPanel.getLayout());
            String lc = (String)migLayout.getLayoutConstraints();
            if (lc.contains("debug")) {
                lc = lc.substring(0, lc.lastIndexOf(','));
            }
            else {
                lc += ",debug";
            }
            migLayout.setLayoutConstraints(lc);  
            App.this.redrawMainPanel();
        }
    });
    menu.add(addMenuItem);
    menu.add(removeMenuItem);
    menu.add(debugMenuItem);
    menuBar.add(menu);
    return menuBar;
}

private JLabel initLabel(int i,int j) {
    JLabel label = new JLabel("label " + i + " " + j);        
    label.setHorizontalAlignment(JLabel.CENTER);
    label.setBorder(BorderFactory.createEtchedBorder());       
    return label;
}
private JPanel initMainPanel() {
    JPanel panel = new JPanel(); 
    panel.setLayout(new MigLayout("nogrid, fill, debug"));
    JLabel label; 
    for (int i = 0; i < initRowsCount; i++) {
        for (int j = 0; j < columnsCount; j++) {                
            panel.add(initLabel(i, j), (j == columnsCount - 1 ? "grow 35, wrap" : "grow 35"));
             ++addedCount;
        }
    }  
    addedCount--;
    return panel;
}

public void initUI() {
    this.setPreferredSize(new Dimension(1024, 768));
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setJMenuBar(initMenuBar());
    this.getContentPane().add(mainPanel = initMainPanel());
    this.setLocationByPlatform(true);
    this.pack();        
}

public static void main(String[] args) {       
    // SwingUtilities.invokeLater
    // or
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            new App().setVisible(true);     ;
        }
    });
}
}

MigLayout有两种或三种操作模式,它们被设置为布局约束--MigLayout构造函数参数。基本模式是网格和仅流模式(nogrid布局约束)。

如果我没记错的话,在网格模式下,你需要至少定义一个维度(行,列),并有多种方法可以随意使用(至少是布局,行和列约束)。然后有两种模式:你可以添加有和没有单元格坐标的组件。

仅流模式等同于Web浏览器可视化格式化系统:内联元素排成一行(例如HTML span标记),而块元素从下一行开始(例如a HTML div)。 wrap组件约束会破坏该行 - 将以下组件放在下一行中。

debug布局约束分别绘制红线和蓝线,分别是布局和组件边界。

fill布局约束:

  

声明容器中列和/或行的所有可用空间。 至少有一个组件需要有一个“增长”的constaint来填充容器。该空间将被分割为相同,但尊重“growpriority”。如果没有列/行设置“增长”,则行/列中组件的增长权重将迁移到该行/列。

grow组件约束(也可用作行/列约束):

  

设置组件相对于同一单元中的其他组件的增长程度。权重(如果未指定,则默认为100)纯粹是其他组件权重的相对值。两倍的重量将获得额外空间的两倍。如果未设置此约束,则将增长权重设置为0并且组件不会增长(除非在行/列中设置填充,在这种情况下,“grow 0”可用于显式使其不增长)。增长权重仅与同一增长优先级组和同一细胞中的权重进行比较。见下文。

以这种方式,框架的大小调整不会弄乱布局,因为它们都平等地增长。有许多方法可以实现非常不同的布局。它似乎是“一个布局管理器来统治它们”。如果您对下载演示有疑问。甚至还有一个动画示例。对业余爱好者来说是一个很好的技术选择;)。

答案 1 :(得分:0)

尝试将scoresPanel作为参数传递给addScoreLabels()方法:

addScoreLabels(scoresPanel);

...

public void addScoreLabels(JPanel scoresPanel) { ...

正如克里斯·库尼在评论中指出的那样,你可能在scoresPanel字段变量中存储了一个不同的面板,第一种方法中的局部变量将其隐藏,而第二种方法则不存在。