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(「ハリー・ジョイ」)が表示されます。次に、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 (Event Dispatching Thread) から実行していることに注意してください。これは本当に悪い考えです。デッドロックや予測不能な動作 (ここに表示されているものなど) が発生する可能性があります。

于 2012-07-05T12:35:35.973 に答える
2

いくつかのコメントとコメントのみである可能性があります

  • のアイデアThread.sleepは正しいですが、Runnable.Thread

  • Swing GUIにはSwing Timer

  • Swing TimerJComponents標準で敷設された目に見えるもののいずれかを(すでにちらつくことなく)移動することを保証しますLayoutManager

しかし、この(私のコード例)の場合、私は再びSwing Timerを使用しており、残りの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 に答える
2

これはhttp://java-sl.com/tip_slider.htmlでしょうか?

于 2012-07-05T12:09:26.010 に答える