请注意,这是一个关于这种方法问题的更理论性的问题,因为我试图理解潜在的机制 - 真正的好奇心。对于实际的实现,我可能会使用不同的东西。
假设我们在拆分窗格中有以下框架。分割窗格的右侧有一个按钮,用于滑出左侧的面板并在其位置显示另一个面板(此处我使用覆盖布局使其看起来更平滑)。代码如下:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.OverlayLayout;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Main {
JPanel panel;
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
public void makeUI() {
panel = new JPanel();
panel.setBackground(Color.RED);
panel.setLocation(0,0);
JPanel panel3 = new JPanel();
panel3.setBackground(Color.BLUE);
panel3.setMinimumSize(new Dimension(100,400));
JPanel panelContainer = new JPanel();
panelContainer.setLayout(new OverlayLayout(panelContainer));
panelContainer.add(panel);
panelContainer.add(panel3);
JButton button = new JButton("slide out");
// Slide out the red panel to reveal blue
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
((JButton) e.getSource()).setEnabled(false);
new Timer(1, new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.setLocation(panel.getX() - 1, 0);
if (panel.getX() + panel.getWidth() == 0) {
((Timer) e.getSource()).stop();
panel.setVisible(false);
System.out.println("Timer stopped");
}
}
}).start();
}
});
JFrame frame = new JFrame("Sliding Panel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setLayout(null);
splitPane.setDividerLocation(100);
splitPane.setLeftComponent(panelContainer);
JPanel panel2 = new JPanel();
panel2.add(button);
// panel2.add(button2);
panel2.setMinimumSize(new Dimension(200,400));
splitPane.setRightComponent(panel2);
frame.setContentPane(splitPane);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Main().makeUI();
}
});
}
}
现在,如果我添加一个反转动画的按钮,通过将位置设置为(-panel.getWidth(), 0)
然后增加x坐标,则会失败。理论上,代码是相同的,唯一的区别在于起始位置,结束位置和增量。但它不再起作用。
JButton button2 = new JButton("slide in");
button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
((JButton) e.getSource()).setEnabled(false);
panel.setVisible(true);
panel.setLocation(-panel.getWidth(),0);
System.out.println(panel.getX()); // gives -99, which is about right
new Timer(1, new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println(panel.getX()); // starts from 0
panel.setLocation(panel.getX() + 1, 0);
System.out.println(panel.getX()); // keeps increasing until forcibly stopped
if (panel.getX() == 0) {
((Timer) e.getSource()).stop();
System.out.println("Timer stopped");
}
}
}).start();
}
});
更确切地说,问题在于new Timer(...)
行。根据控制台日志记录,设置位置将X坐标置于-99,但两行之后将其置于0,当增量出现时,它将继续为无穷大。
也许我误解了计时器是如何工作的,但是在阅读了它和JPanels的文档后,我仍然不明白为什么这样的方法不起作用。更不用说JPanels的负坐标几乎没有。
提前感谢您的所有解释!
编辑(27.07.2016)
@camick的回答让它发挥作用,但我仍然没有低于它它,虽然它帮助我缩小了一点问题:
为什么在将位置设置为负值后重新完成布局?是什么导致它重新完成?
答案 0 :(得分:1)
理论上代码是相同的,唯一的区别在于开始位置,结束位置和增量
实际上它不一样。
您可以使用面板的可见性进行游戏,逻辑会根据您单击的按钮而有所不同。我猜测setVisible(true)语句正在调用正在重置组件位置的布局管理器。
无需更改面板的可见性。摆脱setVisible(...)
两个陈述。
此外,您可能希望保持按钮启用,您可以重复测试滑入/滑出,而无需重新启动程序。
编辑:
如果是这种情况,为什么getX()给出-99
因为在执行该语句时尚未完成布局。
代码并不总是按顺序执行。有时,Swing方法将使用SwingUtiltites.invokeLater()在Event Dispatch Thread(EDT)的末尾添加代码。
这很容易验证。只需按如下方式更改代码,即可查看调用布局的时间。
JPanel panelContainer = new JPanel()
{
@Override
public void doLayout()
{
System.out.println("layout");
super.doLayout();
}
};