更改卡片布局中带有滑动效果的卡片布局中的当前卡片
我试图更改当前卡片布局中可见的幻灯片效果。但我在幻灯片的开头看到一个轻弹,我无法调试/解决。我怎样才能避免轻弹?更改卡片布局中带有滑动效果的卡片布局中的当前卡片
下面是示例代码重现错误:
import java.awt.CardLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new CardLayout());
JLabel label1 = new JLabel("Harry Joy");
panel.add(label1, "1");
JLabel label2 = new JLabel("Harsh Raval");
panel.add(label2, "2");
frame.add(panel);
frame.pack();
frame.setVisible(true);
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
e.printStackTrace();
}
label2.setLocation(label1.getX() + 10 - label1.getWidth(), label1.getY());
label1.setLocation(label1.getX() + 10, label1.getY());
label2.setVisible(true);
}
label2.setVisible(false);
CardLayout cl = (CardLayout)panel.getLayout();
cl.next(panel);
}
}
在这里,在第一label1
( “哈里喜悦”)被显示。然后我制作label2
(“Harsh Raval”)可见,并尝试更改两者的位置以提供滑动效果。但是,这里发生的事情是第一次两个标签都显示在彼此的顶部,然后开始滑动。我怎么能阻止这个,我的意思是把两个标签放在一起?如果你运行一次,你可以更好地了解我的意思。
主要问题是您正在踩CardLayout的脚趾。 CardLayout两个管理范围(位置和大小),以及您的组件的可见性,使您的循环在这里:
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
e.printStackTrace();
}
label2.setLocation(label1.getX() + 10 - label1.getWidth(), label1.getY());
label1.setLocation(label1.getX() + 10, label1.getY());
label2.setVisible(true);
}
是什么呢CardLayout发生冲突。默认情况下,CardLayout将自动显示您添加的第一个组件,并隐藏所有其他组件。它还将所有组件的边界设置为相同的边界。
在第一次迭代中,LABEL2变化的可见性(从false
到true
)最终触发您CardLayout来再进行你的组件的布局,将所有组件的边界来这就是为什么同样的边界结束你看到了重叠。 CardLayout并不意味着可以同时看到多个组件。
请注意,您正在美国东部时间(事件调度线程)运行这是一个坏主意。它会导致死锁和不可预知的行为(例如你在这里看到的那个)。
在我的应用程序中,我使用'SwingUtilities.invokeLater(..)'并面临同样的问题。所以我不认为这是由于我在美国东部时间以外运行。关于将label2的可见性设置为true:我这样做是因为如果我不这样做,那么我不会看到label2滑动,只有先滑出,然后最后显示label2,而不是我需要的情况。我尝试删除'setVisible(true)'行,并且效果很好,完全没有重叠,但正如我所说的那样,第一个标签只有滑出效果,第二个标签没有效果。所以看起来问题在于设置label2的可见性。 – 2012-07-05 12:48:31
@HarryJoy我在'SwingUtilities.invokeLater()'中运行了上面显示的那个例子,因为你会阻塞EDT,所以你不会看到任何东西,这意味着“Paint事件”不能被处理。重叠也可能不会发生,因为'label2'的可见性改变触发了要执行的布局,而且在将来EventQueue事件中也会发生,所以您的问题与您在EDT上运行的事实以及可见性改变标签2。考虑使用摆动计时器来做滑动效果。 – 2012-07-05 12:57:21
好的。我想我必须告诉你我到底有什么:首先,我创建一个框架和我的自定义面板,它具有CardLayout,使此框架可见。我在main方法和'SwingUtilities.invokeLater()'中执行这个操作。然后,我启动一个用于更改组件位置的'java.swing.Timer',这个例子中的循环内部实际上是'Timer'的'ActionLerformed()'ActionListener'方法的内部。这是你的建议吗? – 2012-07-05 13:06:09
同样的事情发生在这个例子中。当你从最后一个组件滑到第一个时,有时候会看到和我一样的问题。在本例中,正确地看到它会增加监听器类中的计时器延迟。我很想知道这个原因,如果可能的话,这个解决方案。 – 2012-07-05 12:12:38
一些意见和可能是评论仅供
与
Thread.sleep
想法是正确的,但只从Runnable.Thread
开始为Swing GUI有
Swing Timer
,Swing Timer
确保移动任何(没有闪烁已经)可见JComponents
铺设标准LayoutManager
但在这(我的代码示例)的情况下,我再次使用Swing的计时器,也不是所有的事件将在美国东部时间来完成,从Runnable的生活自己的生活调用,而不影响挥杆事件的其余部分,GUI EI,
通知这个问题是基于AWT嵌套/继承,例如用于JComboBoxes弹出(调整大小,并用的doLayout())不工作
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ShakingButtonDemo implements Runnable {
private JButton button;
private JRadioButton radioWholeButton;
private JRadioButton radioTextOnly;
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new ShakingButtonDemo());
}
@Override
public void run() {
radioWholeButton = new JRadioButton("The whole button");
radioTextOnly = new JRadioButton("Button text only");
radioWholeButton.setSelected(true);
ButtonGroup bg = new ButtonGroup();
bg.add(radioWholeButton);
bg.add(radioTextOnly);
button = new JButton(" Shake with this Button ");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
shakeButton(radioWholeButton.isSelected());
}
});
JPanel p1 = new JPanel();
p1.setBorder(BorderFactory.createTitledBorder("Shake Options"));
p1.setLayout(new GridLayout(0, 1));
p1.add(radioWholeButton);
p1.add(radioTextOnly);
JPanel p2 = new JPanel();
p2.setLayout(new GridLayout(0, 1));
p2.add(button);
JFrame frame = new JFrame();
frame.setTitle("Shaking Button Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(p1, BorderLayout.NORTH);
frame.add(p2, BorderLayout.SOUTH);
frame.setSize(240, 160);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void shakeButton(final boolean shakeWholeButton) {
final Point point = button.getLocation();
final Insets margin = button.getMargin();
final int delay = 75;
Runnable r = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 30; i++) {
try {
if (shakeWholeButton) {
moveButton(new Point(point.x + 5, point.y));
Thread.sleep(delay);
moveButton(point);
Thread.sleep(delay);
moveButton(new Point(point.x - 5, point.y));
Thread.sleep(delay);
moveButton(point);
Thread.sleep(delay);
} else {// text only
setButtonMargin(new Insets(margin.top, margin.left + 3, margin.bottom, margin.right - 2));
Thread.sleep(delay);
setButtonMargin(margin);
Thread.sleep(delay);
setButtonMargin(new Insets(margin.top, margin.left - 2, margin.bottom, margin.right + 3));
Thread.sleep(delay);
setButtonMargin(margin);
Thread.sleep(delay);
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
};
Thread t = new Thread(r);
t.start();
}
private void moveButton(final Point p) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
button.setLocation(p);
}
});
}
private void setButtonMargin(final Insets margin) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
button.setMargin(margin);
}
});
}
}
* “这里是SSCCE:” *嗯。没有。一个SSCCE需要一个格式良好的类和一个'main()'(除非是一个applet)。 – 2012-07-05 11:50:40
@AndrewThompson更新:) – 2012-07-05 11:51:43
这不是一个SSCCE,因为没有主要和没有进口。只有当EDT用完时,你的例子才“有效”,这是一个坏主意。 – 2012-07-05 11:52:20