我想逐步修改 java JFrame 设计结构,如这个简单的示例所示。在循环中,我增加了 JPanel 的首选宽度并使用方法 pack()。但显然 pack 方法被忽略了。如果我把这个包从循环中拿出来,只使用一次,那就可以了。有人知道原因和可能的解决方案吗?
public class Calculadora extends JFrame {
private JPanel pnl = new JPanel();
private boolean flag;
public Calculadora() {
JPanel pnlPrincipal = new JPanel();
pnlPrincipal.setPreferredSize(new Dimension(300, 300));
pnlPrincipal.setBackground(Color.BLACK);
JButton btnAnexo = new JButton("Anexo");
btnAnexo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (flag) {
closeAnexo();
flag = false;
} else {
openAnexo();
flag = true;
}
}
});
pnlPrincipal.add(btnAnexo);
this.pnl.setBackground(Color.WHITE);
this.pnl.setPreferredSize(new Dimension(0, 300));
this.add(pnl, BorderLayout.EAST);
this.add(pnlPrincipal, BorderLayout.CENTER);
this.pack();
this.setVisible(true);
}
private void openAnexo() {
new Thread () {
@Override
public void run() {
for (int i = pnl.getWidth(); i <= 200; i++) {
pnl.setPreferredSize(new Dimension(i, 300));
pack();
}
}
}.start();
}
private void closeAnexo() {
new Thread () {
@Override
public void run() {
for (int i = pnl.getWidth(); i >= 0; i--) {
pnl.setPreferredSize(new Dimension(i, 300));
pack();
}
}
}.start();
}
public static void main(String[] args) {
new Calculadora();
}
}
最佳答案
这里:
private void openAnexo() {
new Thread () {
@Override
public void run() {
for (int i = pnl.getWidth(); i <= 200; i++) {
pnl.setPreferredSize(new Dimension(i, 300));
pack();
}
}
}.start();
}
必须在 Event Dispatch Thread 中创建/更新 Swing 组件。话虽如此,您的线程正在阻塞 EDT,导致 GUI 变得无响应。您应该使用 SwingUtilities.invokeLater() 将此新线程与 EDT 同步。 。或者更好的是,您可以使用 Swing Timer 执行重复性任务。这是一个处理所有并发问题的便利类。
例如:
private void openAnexo() {
javax.swing.Timer timer = new javax.swing.Timer(200, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int width = pnl.getWidth();
if(width > 200) {
((javax.swing.Timer)e.getSource()).stop();
} else {
pnl.setPreferredSize(new Dimension(width + 1, 300));
Calculadora.this.pack();
}
}
});
timer.setRepeats(true);
timer.setDelay(200);
timer.start();
}
查看 How to Use Swing Timers教程以获得更好的解释。
我不知道你想用这个实现什么目的,但请注意这一点:Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? (是的,我们应该)。
关于java - 在循环中使用 JFrame.pack(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22353568/