简体   繁体   English

Java Swing JLabels在buildGUI方法中显示,但从其他方法添加时则不显示

[英]Java Swing JLabels show in a buildGUI method but not if added from another method

I'm an amateur writing an archery score card. 我是一个业余爱好者,在写射箭记分卡。 The programme works well but at the cost of 19 sections of identical code each of 18 lines. 该程序运行良好,但代价是18行中每行都有19个相同代码的部分。 I'm trying to condense the code by using a method call. 我正在尝试通过使用方法调用来压缩代码。 I'm using Java SE6 and Mig Layout 我正在使用Java SE6和Mig Layout

Here is the section of code in the GUI which works. 这是GUI中有效的代码部分。 The GUI is called as below GUI如下所示

HomePage (containing the main method) -> ChoiceGUI -> buildScoresPanel 主页(包含主要方法)-> 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              }
    }

If, however I put the code in a method and call it as below the Jlabels won't show even though I've tried revalidate() repaint() and setVisible(true) 但是,如果我将代码放入方法中并按如下所示进行调用,即使我尝试了revalidate(),repaint()和setVisible(true),Jlabel也不会显示

    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);
  }

I have trawled the internet for quite a while trying to solve the problem and I realise that I have a fundamental misunderstanding of how Swing components work and would be grateful if someone could explain. 我已经拖了很长时间试图解决该问题,并且意识到我对Swing组件的工作方式有一个根本性的误解,如果有人可以解释,我将不胜感激。

I believe your component constraints are illegal (in addition to possible other causes). 我相信您的组件约束是非法的(除了可能的其他原因)。 These are main resources regarding the MigLayout that I have managed to find: 这些是我设法找到的有关MigLayout的主要资源:

The cheatsheet is your best friend, though it wouldn't hurt to read the whitepaper and download and view the user-friendly demos. 该备忘单是您最好的朋友,尽管阅读白皮书并下载并查看用户友好的演示文稿也没有什么坏处。 If you look into the cheatsheet you'll see that you've basically tried to set the same thing in a couple of different (probably non-compatible) ways. 如果您查看备忘单,您会发现您基本上已经尝试以几种不同的方式(可能是不兼容的方式)设置相同的内容。

I've made an SSCCE for dynamic add/remove of a label from a MigLayout managed JPanel. 我已经为从MigLayout管理的JPanel动态添加/删除标签创建了一个SSCCE。 It was built with MigLayout 3.7.4 . 它是使用MigLayout 3.7.4构建的。

Screenshot: 截图: MigLayout添加删除调试测试SSCCE

Code: 码:

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 has two or three modes of operation which are set as layout constraints - the MigLayout constructor argument. MigLayout具有两种或三种设置为布局约束的操作模式-MigLayout构造函数参数。 The basic modes are grid and flow-only mode (the nogrid layout constraint). 基本模式是网格和仅流模式(无nogrid布局约束)。

If I remember correctly, in the grid mode you need to define at least one dimension (rows, columns) and have several ways to do so at your disposal (layout, row and column constraints at least). 如果我没记错的话,在网格模式下,您需要定义至少一个维度(行,列),并有几种方法可以使用(至少布局,行和列约束)。 Then there are two modes: you can add components with and without cell coordinates . 然后有两种模式:您可以添加具有和不具有单元格坐标的零部件。

The flow-only mode is equivalent to the web browser visual formatting system: the inline elements are laid out in a row (eg HTML span tag), while a block element starts at the next row (eg a HTML div ). 纯流模式等效于Web浏览器视觉格式系统:内联元素排成一行(例如HTML span标签),而块元素从下一行开始(例如HTML div )。 The wrap component constraint breaks the line - places the following component in the next row. wrap组件约束打破了这一行-将以下组件放置在下一行中。

The debug layout constraint draws the red and blue lines, which are layout and component bounds, respectively. debug布局约束绘制红线和蓝线,分别是布局边界和组件边界。

The fill layout constraint: 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. 如果没有列/行具有“增长”设置,则行/列中组件的增长权重将迁移到该行/列。

The grow component constraint (may be used as row/column constraint also): 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. 重量(如果未指定,默认为100)纯粹是相对于其他组件重量的相对值。 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). 如果未设置此约束,则将增长权重设置为0,并且组件将不会增长(除非在行/列中设置了填充,在这种情况下,可以使用“增长0”显式使其不增长)。 Grow weight will only be compared against the weights in the same grow priority group and for the same cell. 仅将生长权重与相同生长优先级组和同一单元格中的权重进行比较。 See below. 见下文。

In this manner, the resizing of the frame can't mess the layout, beacuse they all grow equally. 以这种方式,调整框架的大小不会弄乱布局,因为它们都一样增长。 There are many more ways of achieving very different layouts. 还有许多实现完全不同布局的方法。 It does seem it is "one layout manager to rule them all". 似乎确实是“一个将所有规则全部统治的布局管理器”。 If you have doubts download the demos. 如果您有疑问,请下载演示。 There is even an animation example. 甚至还有一个动画示例。 An excellent technology choice for an amateur ;). 业余爱好者的绝佳技术选择;)。

Try passing scoresPanel as an argument to your addScoreLabels() method too: 也尝试将scoresPanel作为参数传递给您的addScoreLabels()方法:

addScoreLabels(scoresPanel);

...

public void addScoreLabels(JPanel scoresPanel) { ...

As Chris Cooney points out in the comments, you probably have a different panel stored in a scoresPanel field variable, which is being hidden by a local variable in the first method, but not in the second. 正如Chris Cooney在评论中指出的那样,您可能在scoresPanel字段变量中存储了一个不同的面板,该变量在第一种方法中被局部变量隐藏,而在第二种方法中则没有。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM