1

我正在尝试使用幻灯片效果更改卡片布局中当前可见的内容。但是我在幻灯片的开头看到了一个我无法调试/解决的轻弹。我怎样才能避免那种轻弹?

这是重现错误的示例代码:

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显示(“Harry Joy”)。然后我使label2(“Harsh Raval”)可见并尝试更改两者的位置以提供幻灯片效果。但是这里发生的是第一次两个标签都显示在彼此的顶部,然后它开始滑动。我怎么能阻止这种情况,我的意思是把两个标签放在一起显示?如果您运行一次,您可以更好地理解我的意思。

4

3 回答 3

3

主要问题是你踩到了 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 的可见性发生变化(从falsetrue),最终触发您的 CardLayout 重新执行组件的布局,将所有组件的边界设置为相同的边界,这就是您看到重叠的原因。CardLayout 并不是要让多个组件同时可见。

请注意,您是在 EDT(事件调度线程)上运行所有这些,这确实是一个坏主意。它可能导致死锁和不可预知的行为(例如您在此处看到的行为)。

于 2012-07-05T12:35:35.973 回答
2

可能是这个http://java-sl.com/tip_slider.html

于 2012-07-05T12:09:26.010 回答
2

一些评论,可能只是评论

  • 想法Thread.sleep是正确的,但只是从Runnable.Thread

  • Swing GUI 在那里Swing Timer

  • Swing Timer保证按JComponents标准移动任何可见的(不闪烁)LayoutManager

但在这个(我的代码示例)案例中,我再次使用 Swing Timer,也不是所有事件都将在 EDT 上完成,方法是从 Runnable 调用自己的生活而不影响其余的 Swing 事件 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);
            }
        });
    }
}
于 2012-07-05T13:45:39.320 回答