调整 JDialog 和 JTable 列的大小时出现问题
Problem resizing JDialog and JTable columns
我正在创建一个带有 JTable
的 JDialog
window,并且我正在尝试使其成为 "responsive" 以适应不同的屏幕尺寸。由于 window 和 table 大小可能会改变,我按百分比设置列宽。
目前没有问题。第一次显示 table 时一切看起来都很好。一旦 table 被重新加载(由于修改或其他原因),列的大小看起来不同,但 table 和 window 的大小仍然相同。这种情况仅在第一次重新加载时发生,然后每次重新加载时所有内容都保持相同的大小。
我使用 JOptionPane
消息对话框在每次加载时显示 table 宽度,我发现了问题。 table 第一次加载时使用的是不同的大小(JScrollPane
首选大小),然后下一次使用应该是调整大小操作的大小。
1st time loaded (image)
2nd time loaded (image)
真正的问题是为什么?
我已经尝试将 JDialog
调整大小的代码移动到 initComponents()
方法的不同位置(创建全局维度变量),但同样的事情仍在发生。如果我删除调整大小的 JDialog
代码,一切都很好,但这是胆小鬼的方式,哈哈。
这是我正在使用的代码,至少我认为是相关的。
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
public class Test extends JDialog {
private javax.swing.JButton bUpdate;
private javax.swing.JPanel jPanel1;
private javax.swing.JTable tabla;
private javax.swing.JScrollPane tablaSP;
public Test(Dimension d){
initComponents();
int w = (int) (Math.round(d.getWidth())/2);
int h = (int) (Math.round(d.getHeight())/2);
setSize(w, h);
setLocationRelativeTo(null);
bUpdate.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
cargarProductos();
}
});
cargarProductos();
}
private void cargarProductos(){
try{
String atr[] = {"Código", "Proveedor", "Nombre", "Clasificación", "Descripción", "Tipo", "P. Compra", "P. Venta"};
DefaultTableModel model = new DefaultTableModel(null, atr){
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
//Filling table model
tabla.setModel(model);
int tw = tablaSP.getWidth();
TableColumnModel cm=tabla.getColumnModel();
cm.getColumn(0).setPreferredWidth((int) (tw*.10));
cm.getColumn(1).setPreferredWidth((int) (tw*.15));
cm.getColumn(2).setPreferredWidth((int) (tw*.15));
cm.getColumn(3).setPreferredWidth((int) (tw*.10));
cm.getColumn(4).setPreferredWidth((int) (tw*.19));
cm.getColumn(5).setPreferredWidth((int) (tw*.10));
cm.getColumn(6).setPreferredWidth((int) (tw*.10));
cm.getColumn(7).setPreferredWidth((int) (tw*.10));
tabla.setAutoCreateRowSorter(true);
JOptionPane.showMessageDialog(null, tw, "Table width", JOptionPane.PLAIN_MESSAGE);
}catch(Exception e){
JOptionPane.showMessageDialog(this, e.getMessage(), "Error llenando tabla de productos", JOptionPane.PLAIN_MESSAGE);
}
}
public static void main(String[]args){
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch(Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage());
}
EventQueue.invokeLater(new Runnable() {
public void run() {
Test dialog = new Test(new Dimension (Toolkit.getDefaultToolkit().getScreenSize()));
dialog.setVisible(true);
}
});
}
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
bUpdate = new javax.swing.JButton();
tablaSP = new javax.swing.JScrollPane();
tabla = new javax.swing.JTable();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setModalityType(java.awt.Dialog.ModalityType.APPLICATION_MODAL);
setSize(new java.awt.Dimension(0, 0));
bUpdate.setText("Update");
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(bUpdate, javax.swing.GroupLayout.DEFAULT_SIZE, 83, Short.MAX_VALUE)
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(bUpdate)
.addContainerGap(242, Short.MAX_VALUE))
);
tabla.setModel(new javax.swing.table.DefaultTableModel(
new Object[][]{ {},{},{},{} },
new String[]{}
));
tablaSP.setViewportView(tabla);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(tablaSP)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(tablaSP, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addContainerGap())
);
pack();
}
}
我希望它是 JDialog
,因为我需要它作为模态 Window,但我还需要让它变大一些 "responsive",因为内容 [=47] =] 可能很大。
最初的问题是您提前调用 initComponents
,即在应用您希望它具有的尺寸之前。因此,在 initComponents
components 方法中调用 pack
会将您的面板缩小到最小尺寸。
之后您更改了对话框的大小(通过调用 setSize(w,h)
),
但这并没有直接影响所涉及的组件。但是,当对话框设置为 visible
时,组件会自动调整以适应定义的大小。这不适用于您的列大小,因为您没有定义会触发此操作的 ComponentListener
(请参见下面的第二个示例)。
这导致单击 update
按钮第一次考虑组件的调整大小,因此它们被应用到列。
要解决不同大小的问题,请将构造函数中的方法调用更改为
(下面是构造函数的完整示例):
int w = (int) (Math.round(d.getWidth()) / 2);
int h = (int) (Math.round(d.getHeight()) / 2);
setPreferredSize(new Dimension(w, h));
initComponents();
您可能想从 initComponents()
方法中删除 setSize(new java.awt.Dimension(0, 0));
。
如果您想在用户手动调整对话框大小时保持列大小,请考虑添加 ComponentListener
,再举一个例子,检查此 answer
。
这也可以用作原始代码的替代解决方案,
但首先正确定义尺寸可能更清晰。
public Test(Dimension d) {
int w = (int) (Math.round(d.getWidth()) / 2);
int h = (int) (Math.round(d.getHeight()) / 2);
setPreferredSize(new Dimension(w, h));
initComponents();
setLocationRelativeTo(null);
bUpdate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cargarProductos();
}
});
this.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
cargarProductos();
}
});
}
我正在创建一个带有 JTable
的 JDialog
window,并且我正在尝试使其成为 "responsive" 以适应不同的屏幕尺寸。由于 window 和 table 大小可能会改变,我按百分比设置列宽。
目前没有问题。第一次显示 table 时一切看起来都很好。一旦 table 被重新加载(由于修改或其他原因),列的大小看起来不同,但 table 和 window 的大小仍然相同。这种情况仅在第一次重新加载时发生,然后每次重新加载时所有内容都保持相同的大小。
我使用 JOptionPane
消息对话框在每次加载时显示 table 宽度,我发现了问题。 table 第一次加载时使用的是不同的大小(JScrollPane
首选大小),然后下一次使用应该是调整大小操作的大小。
1st time loaded (image)
2nd time loaded (image)
真正的问题是为什么?
我已经尝试将 JDialog
调整大小的代码移动到 initComponents()
方法的不同位置(创建全局维度变量),但同样的事情仍在发生。如果我删除调整大小的 JDialog
代码,一切都很好,但这是胆小鬼的方式,哈哈。
这是我正在使用的代码,至少我认为是相关的。
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
public class Test extends JDialog {
private javax.swing.JButton bUpdate;
private javax.swing.JPanel jPanel1;
private javax.swing.JTable tabla;
private javax.swing.JScrollPane tablaSP;
public Test(Dimension d){
initComponents();
int w = (int) (Math.round(d.getWidth())/2);
int h = (int) (Math.round(d.getHeight())/2);
setSize(w, h);
setLocationRelativeTo(null);
bUpdate.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
cargarProductos();
}
});
cargarProductos();
}
private void cargarProductos(){
try{
String atr[] = {"Código", "Proveedor", "Nombre", "Clasificación", "Descripción", "Tipo", "P. Compra", "P. Venta"};
DefaultTableModel model = new DefaultTableModel(null, atr){
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
//Filling table model
tabla.setModel(model);
int tw = tablaSP.getWidth();
TableColumnModel cm=tabla.getColumnModel();
cm.getColumn(0).setPreferredWidth((int) (tw*.10));
cm.getColumn(1).setPreferredWidth((int) (tw*.15));
cm.getColumn(2).setPreferredWidth((int) (tw*.15));
cm.getColumn(3).setPreferredWidth((int) (tw*.10));
cm.getColumn(4).setPreferredWidth((int) (tw*.19));
cm.getColumn(5).setPreferredWidth((int) (tw*.10));
cm.getColumn(6).setPreferredWidth((int) (tw*.10));
cm.getColumn(7).setPreferredWidth((int) (tw*.10));
tabla.setAutoCreateRowSorter(true);
JOptionPane.showMessageDialog(null, tw, "Table width", JOptionPane.PLAIN_MESSAGE);
}catch(Exception e){
JOptionPane.showMessageDialog(this, e.getMessage(), "Error llenando tabla de productos", JOptionPane.PLAIN_MESSAGE);
}
}
public static void main(String[]args){
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch(Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage());
}
EventQueue.invokeLater(new Runnable() {
public void run() {
Test dialog = new Test(new Dimension (Toolkit.getDefaultToolkit().getScreenSize()));
dialog.setVisible(true);
}
});
}
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
bUpdate = new javax.swing.JButton();
tablaSP = new javax.swing.JScrollPane();
tabla = new javax.swing.JTable();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setModalityType(java.awt.Dialog.ModalityType.APPLICATION_MODAL);
setSize(new java.awt.Dimension(0, 0));
bUpdate.setText("Update");
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(bUpdate, javax.swing.GroupLayout.DEFAULT_SIZE, 83, Short.MAX_VALUE)
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(bUpdate)
.addContainerGap(242, Short.MAX_VALUE))
);
tabla.setModel(new javax.swing.table.DefaultTableModel(
new Object[][]{ {},{},{},{} },
new String[]{}
));
tablaSP.setViewportView(tabla);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(tablaSP)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(tablaSP, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addContainerGap())
);
pack();
}
}
我希望它是 JDialog
,因为我需要它作为模态 Window,但我还需要让它变大一些 "responsive",因为内容 [=47] =] 可能很大。
最初的问题是您提前调用 initComponents
,即在应用您希望它具有的尺寸之前。因此,在 initComponents
components 方法中调用 pack
会将您的面板缩小到最小尺寸。
之后您更改了对话框的大小(通过调用 setSize(w,h)
),
但这并没有直接影响所涉及的组件。但是,当对话框设置为 visible
时,组件会自动调整以适应定义的大小。这不适用于您的列大小,因为您没有定义会触发此操作的 ComponentListener
(请参见下面的第二个示例)。
这导致单击 update
按钮第一次考虑组件的调整大小,因此它们被应用到列。
要解决不同大小的问题,请将构造函数中的方法调用更改为
(下面是构造函数的完整示例):
int w = (int) (Math.round(d.getWidth()) / 2);
int h = (int) (Math.round(d.getHeight()) / 2);
setPreferredSize(new Dimension(w, h));
initComponents();
您可能想从 initComponents()
方法中删除 setSize(new java.awt.Dimension(0, 0));
。
如果您想在用户手动调整对话框大小时保持列大小,请考虑添加 ComponentListener
,再举一个例子,检查此 answer
。
这也可以用作原始代码的替代解决方案, 但首先正确定义尺寸可能更清晰。
public Test(Dimension d) {
int w = (int) (Math.round(d.getWidth()) / 2);
int h = (int) (Math.round(d.getHeight()) / 2);
setPreferredSize(new Dimension(w, h));
initComponents();
setLocationRelativeTo(null);
bUpdate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cargarProductos();
}
});
this.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
cargarProductos();
}
});
}