MigLayout与JScrollBar对象中包含的JTable对象混淆 [英] MigLayout confused by JTable objects contained in JScrollBar objects
问题描述
看起来MigLayout被JScrollPane对象中包含的JTable对象弄糊涂了.由于在JScrollPane中包含JTable似乎是一种常见的习惯用法,所以我认为找出原因很重要.
It appears the MigLayout becomes confused by JTable objects contained in JScrollPane objects. Since it seems likely that it is a common idiom to have a JTable within a JScrollPane, I thought it would be important to find out why.
在所附的示例程序中,将创建一个简化的表单,该表单由12行和4列组成.所有宽度和高度均设置为百分比.许多元素都按单元格位置添加到表单中.一些跨越行或列.最后一列显示单元格行索引和大小百分比.
In the attached example program, a simplified form is created, consisting of 12 rows and 4 columns. All widths and heights are set as percentages. A number of components are added to the form, all by cell position. Some span rows or columns. The last column shows cell row index and size percentage.
如果程序以参数"JLabel"启动,则JSCrollPane中包含的JLabel将添加到列0,所有对齐方式看起来都不错.如果程序以参数"JTable"启动,则所有列的行大小都会中断.
If the program is started with argument "JLabel", a JLabel contained in a JSCrollPane is added to column 0, all alignments look good. If the program is started with argument "JTable", row sizes for all columns are disrupted.
这是错误还是功能?
Make: javac -classpath <path to miglayout> migtest.java
Usage: java -classpath <path to miglayout> migtest <JTable|JLabel>
注意:如果下面的代码显得模糊(没有选项卡),则我尝试了多种粘贴方法-无法使预览看起来正确.让我知道是否有什么可以解决的方法.
Note: if the code below appears obfuscated (no tabs), I tried various paste methods - I couldn't get the preview to look right. Let me know if there's anything I can do to fix it.
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
推荐答案
有很多组件约束(对我来说实在太多了,无法深入研究它们;-)因此,答案只是一个粗略的类型:
That's a lot of component constraints (too many for me to really digging into them ;-) So just a cursory type of answer:
标签与表格之间的区别在于,后者实现了可滚动显示,尤其是其可滚动显示
The difference between a label vs. a table is that the latter implements scrollable, in particular its
Dimension getPreferredScrollableViewportSize();
这是为了返回固定的维度而实现的,不幸的是,该维度硬编码在表格的初始代码中:
This is implemented to return a fixed dimension, unfortunately hard-coded in the table's init code:
setPreferredScrollableViewportSize(new Dimension(450, 400));
这几乎不是您想要的.
which is rarely what you want.
对MigLayout的影响是,由于面积较大(在实际行上是独立的),因此其单元格溢出太多,以至于其他单元格必须缩小.
The effect on MigLayout is that with the rather large area (and indendent on the actual rows) overflows its cell so much that the other cells must shrink.
在您的上下文中解决的方法是简单地将prefViewport设置为null:
The way out in your context is to simply set the prefViewport to null:
clientsTable.setPreferredScrollableViewportSize(null);
(编辑请注意,重点是您的上下文-不同的LayoutManager将被混淆,请参见
(Edit note that the emphasis is on your context - different LayoutManagers will be confused, see a recent question)
一个更通用的解决方案可能是将吸气剂实现为更合理的方式.用#of行(大约,尽管不完全是JXTable所做的事情)计算优先级
A more general solution might be to implement the getter to to something more reasonable, f.i. calculate the preference in terms of #of rows (roughly, though not exactly, what JXTable does)
@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...
}
这篇关于MigLayout与JScrollBar对象中包含的JTable对象混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!