1

数日前、マウスホイールをスクロールすると画面上のテキストの色が変わるプログラムに関する質問を投稿しました。残念ながら、特に有用であるにはあまりにも多くのコードが投稿された、うまくまとめられていない質問でした。

いくつかの応答がありました。そのうちの 1 つは、問題を修正したものを投稿したユーザーのごみ箱からのものでした (このページの下部にある、MouseWheelMotion イベント中にウィンドウが空白になる) が、すべてのクラスの説明を読んだ彼が投稿したプログラムで私が知らなかったことと、その実行を経験したこと なぜ彼が私のものとは異なる効果を達成するのか理解できません。

彼はすべてのマウスホイールの動きを記録しているようですが、私のものは最初の動きだけです。また、プログラムが大きすぎて効果を再現できなかったという意見もありました。

以下は、同じ効果を引き出す非常に単純化されたバージョンです (願っています)。

質問:マウス ホイール イベントの処理中に画面が空白になる問題を修正する 2 つのプログラムの根本的な違いは何ですか?

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.LinkedList;
import javax.swing.JFrame;

public class WheelPrinter implements MouseWheelListener, Runnable {

    JFrame frame;
    LinkedList colorList;
    int colorCount;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        WheelPrinter w = new WheelPrinter();
        w.run();
    }

    public WheelPrinter() {
        frame = new JFrame();
        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addMouseWheelListener(this);
        frame.setVisible(true);
        frame.setBackground(Color.WHITE);
        colorList = new LinkedList();
        colorList.add(Color.BLACK);
        colorList.add(Color.BLUE);
        colorList.add(Color.YELLOW);
        colorList.add(Color.GREEN);
        colorList.add(Color.PINK);
    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
        colorChange();
    }

    @Override
    public void run() {
        while(true) {
            draw(frame.getGraphics());
            try {
                Thread.sleep(20);
            } catch (Exception ex) {

            }
        }
    }

    public void draw(Graphics g) {
        g.setColor(frame.getBackground());
        g.fillRect(0,0,frame.getWidth(),frame.getHeight());
        g.setFont(new Font("sansserif", Font.BOLD, 32));
        g.setColor(frame.getForeground());
        g.drawString("yes", 50, 50);
    }

    public void colorChange() {
                colorCount++;
        if (colorCount > 4) {
            colorCount = 0;
        }


        frame.setForeground((Color) colorList.get(colorCount));
    }

    }

(私のコードを実行してみると、マウス ホイールを強く回してみると、さらに明白になります)

4

2 に答える 2

1

基本的な違いは、間違ったスレッドからGraphicsオブジェクトを操作しようとしていて、その時点でのGraphicsオブジェクトの状態について何も知らないことです。

SwingでGraphicsオブジェクトを操作する一般的に正しい方法は、paintComponent(Graphics)メソッドをオーバーライドするカスタムコンポーネントを作成することです。そのメソッド内で描画を行います。

colorChange()メソッドはrepaint()、を呼び出すことによってコンポーネントにそれ自体を再描画するように指示できます。これにより、最終的paintComponent(Graphics)には正しいスレッドで正しい時刻にが呼び出されます。

こちらのチュートリアルを参照してください

于 2012-06-13T00:34:38.183 に答える
1
  1. while(true) {切れ目のない無限ループです。フェ

  2. 遅延Swing Timerの代わりに使用Runnable#ThreadThread.Sleep()

  3. に直接ではなく、JPanelまたはにペイントします。JComponentJFrame

  4. へのすべての塗装はSwing JComponentpaintComponent()

  5. 詳細については、2D グラフィックスのチュートリアルを参照してください

編集

ここに画像の説明を入力

ここに画像の説明を入力

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseWheelEvent;
import java.util.LinkedList;
import java.util.Queue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
 * based on example by @trashgod
 * 
 * @see http://stackoverflow.com/a/10970892/230513
 */
public class ColorWheel extends JPanel {

    private static final int N = 32;
    private static final long serialVersionUID = 1L;
    private final Queue<Color> clut = new LinkedList<Color>();
    private final JLabel label = new JLabel();

    public ColorWheel() {
        for (int i = 0; i < N; i++) {
            clut.add(Color.getHSBColor((float) i / N, 1, 1));
        }
        //clut.add(Color.BLACK);
        //clut.add(Color.BLUE);
        //clut.add(Color.YELLOW);
        //clut.add(Color.GREEN);
        //clut.add(Color.PINK);
        label.setFont(label.getFont().deriveFont(36f));
        label.setForeground(clut.peek());
        label.setText("@see http://stackoverflow.com/a/10970892/230513");
        setBackground(Color.white);
        add(label);
        label.addMouseWheelListener(new MouseAdapter() {

            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                label.setForeground(clut.peek());
                clut.add(clut.remove());
            }
        });
    }

    @Override
    public Dimension getPreferredSize() {
        int w = SwingUtilities.computeStringWidth(label.getFontMetrics(
                label.getFont()), label.getText());
        return new Dimension(w + 20, 80);
    }

    private void display() {
        JFrame f = new JFrame("ColorWheel");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ColorWheel().display();
            }
        });
    }
}
于 2012-06-12T18:58:06.553 に答える