2

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

这是 GUI 中有效的代码部分。GUI被称为如下

HomePage(包含 main 方法) -> 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 组件的工作原理有一个基本的误解,如果有人能解释一下,我将不胜感激。

4

2 回答 2

1

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

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

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

截屏: MigLayout 添加删除调试测试 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 模式相当于网络浏览器的可视化格式化系统:内联元素排成一行(例如 HTMLspan标签),而块元素从下一行开始(例如 HTML div)。组件约束打破了界限 -将wrap以下组件放置在下一行。

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

fill布局约束:

为列和/或行声明容器中的所有可用空间。至少一个组件需要有一个“增长”约束才能填充容器。尽管尊重“增长优先”,但空间将被平均分配。如果没有列/行具有“增长”设置,则行/列中组件的增长权重将迁移到该行/列。

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

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

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

于 2013-04-06T14:12:43.267 回答
0

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

addScoreLabels(scoresPanel);

...

public void addScoreLabels(JPanel scoresPanel) { ...

正如 Chris Cooney 在评论中指出的那样,您可能在scoresPanel字段变量中存储了一个不同的面板,该面板在第一种方法中被局部变量隐藏,但在第二种方法中没有。

于 2013-04-05T13:24:00.860 回答