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

标签 java swing jlabel miglayout

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

这是 GUI 中有效的代码部分。 GUI 调用如下

主页(包含主要方法)-> 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 组件的工作原理存在根本性的误解,如果有人能解释一下,我将不胜感激。

最佳答案

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

备忘单是您最好的 friend ,但阅读白皮书并下载和查看用户友好的演示也无妨。如果您查看备忘单,您会发现您基本上已经尝试以几种不同(可能不兼容)的方式设置相同的内容。

我已经制作了一个 SSCCE,用于从 MigLayout 管理的 JPanel 中动态添加/删除标签。它是用 MigLayout 3.7.4 build 的.

截图: 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 布局约束)。

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

flow-only 模式相当于 web 浏览器视觉格式化系统:内联元素排成一行(例如 HTML span 标签),而 block 元素从下一行开始(例如 HTML div)。 wrap 组件约束换行 - 将以下组件放在下一行。

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

fill 布局约束:

Claims all available space in the container for the columns and/or rows. At least one component need to have a "grow" constaint for it to fill the container. The space will be divided equal, though honoring "growpriority". If no columns/rows has "grow" set the grow weight of the componets in the rows/columns will migrate to that row/column.

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

Sets how keen the component should be to grow in relation to other component in the same cell. The weight (defaults to 100 if not specified) is purely a relative value to other components' weight. Twice the weight will get double the extra space. If this constraint is not set the grow weight is set to 0 and the component will not grow (unless fill is set in the row/column in which case "grow 0" can be used to explicitly make it not grow). Grow weight will only be compared against the weights in the same grow priority group and for the same cell. See below.

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

关于Java Swing JLabels 在 buildGUI 方法中显示,但如果从另一个方法添加则不显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15834955/

相关文章:

java - 用java打开并刷新本地网页

Java Swing JTree 未被垃圾回收

Java基本if/else语句状态改变

java - 将日期时间转换为 yyyy-MM-dd HH :mm:ss"format

java - 如何在 JavaDoc 中自定义 "Overview"页面?

java - 在jtable中的某些列中显示图像

java - 如何将 JLabel 添加到扩展 JPanel 的类

java - 如何在右侧标签中设置文本?

java - 使用 Fragments 进行 Android 搜索

JRuby 中的 Java 命令