【问题标题】:MigLayout confused by JTable objects contained in JScrollBar objectsMigLayout 被 JScrollBar 对象中包含的 JTable 对象混淆
【发布时间】:2012-04-04 02:40:54
【问题描述】:

似乎 MigLayout 被 JScrollPane 对象中包含的 JTable 对象弄糊涂了。由于在 JScrollPane 中包含 JTable 似乎是一种常见的习惯用法,我认为找出原因很重要。

在随附的示例程序中,创建了一个简化的表格,由 12 行和 4 列组成。所有宽度和高度都设置为百分比。许多组件被添加到表单中,全部按单元格位置。一些跨行或列。最后一列显示单元格行索引和大小百分比。

如果程序以参数“JLabel”启动,包含在 JSCrollPane 中的 JLabel 被添加到第 0 列,所有对齐看起来都很好。如果程序以“JTable”参数启动,所有列的行大小都会被打乱。

这是错误还是功能?

Make:  javac -classpath <path to miglayout> migtest.java
Usage:  java -classpath <path to miglayout> migtest <JTable|JLabel>

注意:如果下面的代码出现混淆(没有标签),我尝试了各种粘贴方法 - 我无法让预览看起来正确。如果有什么我可以解决的,请告诉我。

import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.*;
import java.io.*;
import java.text.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.filechooser.*;
import javax.swing.table.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableColumn;
import net.miginfocom.swing.MigLayout;

public class Migtest extends JFrame {
    public final static int appWidth = 1200; // default

    public final static int appHeight = 800; // default

    String[] clientColNames = { "Name", "Address", "Alternate Address" };

    JComponent createClientsPane(int numCols, String arg) {
        if (arg.equals("jtable")) {
            JTable clientsTable = new JTable(1, numCols);
            clientsTable.getTableHeader().setReorderingAllowed(false);
            clientsTable.getSelectionModel().setSelectionMode(
                    ListSelectionModel.SINGLE_SELECTION);
            clientsTable.getSelectionModel().setSelectionInterval(0, 0);
            JScrollPane scrollPane = new JScrollPane(clientsTable);
            return scrollPane;
        } else
            return new JScrollPane(new JLabel("bear tenders"));
    }

    void init(String[] args) {
        JPanel topPanel = null, subpanel = null;
        String arg;
        if (args.length != 1) {
            System.out.println("missing arg - s/b 'JLabel' or 'jTable'");
            System.exit(0);
        }
        arg = args[0].trim().toLowerCase();
        if (!arg.equals("jlabel") && !arg.equals("jtable")) {
            System.out.println("missing arg - s/b 'JLabel' or 'jTable'");
            System.exit(0);
        }
        setSize(appWidth, appHeight);
        topPanel = new JPanel(new MigLayout("fill,debug",
                "[30%][15%][50%][5%]",
                "[5%][7%][5%][10%][7%][7%][7%][7%][6%][7%][2%][30%]"));
        JCheckBox dynamicInstrumentCheckbox = new JCheckBox(
                "Wood Activities Enabled", false);
        topPanel.add(dynamicInstrumentCheckbox, "cell 0 2");
        topPanel.add(new JLabel("BEAR TENDERS"), "cell 0 4, alignx center");
        topPanel.add(createClientsPane(clientColNames.length, arg),
                "cell 0 5, spany 4, grow");
        topPanel.add(new JLabel("BEAR FACTS"), "cell 1 4, alignx center");
        JRadioButton noneButton = new JRadioButton("None");
        topPanel.add(noneButton, "cell 1 5, gapleft 2%");
        JRadioButton rangeButton = new JRadioButton("Fact 1");
        topPanel.add(rangeButton, "cell 1 6, gapleft 2%");
        JRadioButton playbackButton = new JRadioButton("Fact 2");
        topPanel.add(playbackButton, "cell 1 7, gapleft 2%");
        JButton controlsButton = new JButton("Controls =>");
        topPanel.add(controlsButton, "cell 1 8, alignx center");
        topPanel.add(new JLabel("GUMMY BEARS"), "cell 2 1, alignx center");
        topPanel.add(new JLabel("(gummy bears)"), "cell 2 2, spany 4, grow");
        topPanel.add(new JLabel("CHICAGO BEARS"), "cell 2 6, alignx center");
        topPanel.add(new JLabel("(chicago bears)"), "cell 2 7, spany 3, grow");
        topPanel.add(new JLabel("LOG"), "cell 0 10, alignx left");
        JButton clearLogButton = new JButton("Clear Log");
        topPanel.add(clearLogButton, "cell 2 10, alignx right");
        topPanel.add(new JLabel("(log pane)"), "cell 0 11, spanx 3, grow");
        topPanel.add(new JLabel("0-5%"), "cell 3 0, grow");
        topPanel.add(new JLabel("1-7%"), "cell 3 1, grow");
        topPanel.add(new JLabel("2-5%"), "cell 3 2, grow");
        topPanel.add(new JLabel("3-10%"), "cell 3 3, grow");
        topPanel.add(new JLabel("4-7%"), "cell 3 4, grow");
        topPanel.add(new JLabel("5-7%"), "cell 3 5, grow");
        topPanel.add(new JLabel("6-7%"), "cell 3 6, grow");
        topPanel.add(new JLabel("7-7%"), "cell 3 7, grow");
        topPanel.add(new JLabel("8-6%"), "cell 3 8, grow");
        topPanel.add(new JLabel("9-7%"), "cell 3 9, grow");
        topPanel.add(new JLabel("10-2%"), "cell 3 10, grow");
        topPanel.add(new JLabel("11-30%"), "cell 3 11, grow");
        setContentPane(topPanel);
    }

    public static void main(String[] args) {
        try {
            Migtest thisTest = new Migtest();
            thisText.init(args);
//            thisTest.init(new String[] {"jLabel"});
//            thisTest.init(new String[] {"jTable"});

            // center app window
            GraphicsConfiguration gc = thisTest.getGraphicsConfiguration();
            Rectangle bounds = gc.getBounds();
            thisTest.setLocation(
                    (int) ((bounds.width - thisTest.appWidth) / 2),
                    (int) ((bounds.height - thisTest.appHeight) / 2));
            thisTest.setVisible(true);
        } catch (Exception e) {
            System.out.println("runTest caught exception:  " + e.getMessage());
            e.printStackTrace();
        }
    }
} // class test

【问题讨论】:

  • 请学习java命名约定并遵守它们(注意我在这里为你做了,不能忍受小写的className :-)
  • 至于代码格式:所以不喜欢标签,也许你的代码中有一些标签(在让我的 IDE 修复它之前没有尝试过 :-)?

标签: swing jtable jscrollpane miglayout


【解决方案1】:

这是很多组件限制(对我来说太多了,无法真正深入研究它们 ;-) 所以只是粗略的回答:

标签与表格的区别在于后者实现了可滚动,尤其是它的

Dimension getPreferredScrollableViewportSize();

这是为了返回一个固定的维度而实现的,不幸的是在表的初始化代码中硬编码:

setPreferredScrollableViewportSize(new Dimension(450, 400));

这很少是你想要的。

对 MigLayout 的影响是,相当大的区域(并且在实际行上缩进)会溢出它的单元格,以至于其他单元格必须缩小。

在您的上下文中的出路是简单地将 prefViewport 设置为 null:

clientsTable.setPreferredScrollableViewportSize(null);

编辑请注意,重点在于您的上下文 - 不同的 LayoutManager 会混淆,请参阅 recent question

一个更通用的解决方案可能是将 getter 实现为更合理的东西,f.i.根据 #of 行计算偏好(大致,但不完全是 JXTable 所做的)

@Override 
public Dimension getPreferredScrollableViewportSize() {
    if (preferredViewportSize == null) { // hasn't been hard-coded
        if (visibleRowCount < 0) { // a property similar as in JList
             return getPreferredSize(); // use the actual size
        } else {
             Dimension pref = getPreferredSize();
           // calculate height based on # rows that should be visible 
             pref.height = ....
             return pref;
        } 
    } 
    return super.getPr...
}

【讨论】:

  • 太棒了!建议的 tweek 似乎可以解决问题。
【解决方案2】:

我想知道布局管理器是否没有像它可能的那样处理组件。除非滚动的 JTable 组件添加了“spany”术语,否则总体布局行间距不会受到不利影响。此外,通过稍微调整我的应用程序的布局,我发现了一种安排,一切都很好。我的应用程序在对话框中有几个其他滚动的 JTable 组件,我没有在示例中使用。所以有时布局管理器似乎能够获得正确的间距。但我现在可能超出了stackoverflow的范围。 (我计划将问题提交给 miglayout.com,但我无法在他们的支持论坛上注册。) 感谢您的帮助。

【讨论】:

    猜你喜欢
    • 2010-11-30
    • 2012-07-30
    • 2012-05-21
    • 2017-07-14
    • 2017-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多