我希望我的 jframe 根据 x 坐标更改其大小和内容。最初,jframe 出现在“主要区域”(x <= 1400)中,并在 jframe 的内容窗格中添加了一个大小为 500x500 的面板。
Desired:当它被拖动并离开“主要区域”并进入“次要区域”时,所有内容都将从内容窗格中删除,面板被包裹到大小为 200x200 的 jscrollpane 中,并将 jscrollpane 添加到内容窗格中。当 jframe 离开“辅助区域”时,jscrollpane 会从内容窗格中删除,并且面板会重新添加。
实际的: 结果不稳定。当 jframe 离开主要区域时,我可以看到一些翻转。滚动条出现,但框架改变了它的大小,但随后立即调整回原来的大小。在 changeSizeAndContent invokeLater 代码块中的可运行文件内的断点处停止(实际上不是一个好的做法)会带来所需的结果,条件断点也是如此。
发生了一些我不明白的 Swing 多线程。我可以看到 EDT 调用 EventQueue 的 dispatchEvent 并且由 changeSizeAndContent 中的可运行对象触发的 COMPONENT_RESIZED(新的,正确的大小)事件之后是 COMPONENT_MOVED(旧的,现在不正确的大小)事件,它们引用了具有旧大小的组件。
尝试使用 Java 8 和 11。
package Jna;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
/* 0------------------1200-1400--------->
* +---------------+
* | SECONDARY |
* +--------------------+---+ |
* | PRIMARY | B | x: 1200- |
* | x: 0-1400 | U | |
* | | F | |
* | | F | |
* | | E | |
* | | R | |
* | +---+-----------+
* | |
* +------------------------+
*/
public class FrameDemo3 {
static final JPanel panel;
static final JScrollPane jsp;
static {
panel = getInitializedPanel();
jsp = getInitilalizedJScrollPane();
}
static boolean isPrimaryZone = true;
static boolean isCurrentPrimaryZone = true;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGUI());
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("FrameDemo");
frame.addComponentListener(new ComponentAdapter() {
@Override
public void componentMoved(ComponentEvent e) {
int x = frame.getX();
if (x > 1400) {
isCurrentPrimaryZone = false;
} else if (x < 1200) {
isCurrentPrimaryZone = true;
}
if (isPrimaryZone != isCurrentPrimaryZone) {
isPrimaryZone = isCurrentPrimaryZone;
changeSizeAndContent(frame);
}
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
public static void changeSizeAndContent(JFrame frame) {
if (isPrimaryZone) {
SwingUtilities.invokeLater(() -> {
frame.getContentPane().removeAll();
frame.getContentPane().add(panel);
frame.pack();
});
} else {
SwingUtilities.invokeLater(() -> {
frame.getContentPane().removeAll();
frame.getContentPane().add(jsp);
frame.pack();
});
}
}
private static JPanel getInitializedPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBackground(Color.WHITE);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
panel.add(new JLabel(getLabelText(i, j)), getConstraints(i, j));
}
}
panel.setPreferredSize(new Dimension(500, 500));
return panel;
}
private static JScrollPane getInitilalizedJScrollPane() {
JScrollPane jsp = new JScrollPane(panel,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
jsp.setPreferredSize(new Dimension(200, 200));
return jsp;
}
static GridBagConstraints getConstraints(int gridX, int gridY) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = gridX;
gbc.gridx = gridY;
gbc.ipady = 40;
gbc.ipadx = 40;
return gbc;
}
static String getLabelText(int gridX, int gridY) {
StringBuilder sb = new StringBuilder("EXAMPLE ")
.append(gridX)
.append(',')
.append(gridY);
return sb.toString();
}
}