Java 鼠标滚轮闪烁,更多关于为什么

Java 鼠标滚轮闪烁,更多关于为什么,java,swing,graphics,mousewheel,mouselistener,Java,Swing,Graphics,Mousewheel,Mouselistener,几天前,我发布了一个关于一个程序的问题,该程序在鼠标滚轮滚动时导致屏幕上的文本改变颜色。不幸的是,这是一个拼凑得很糟糕的问题,发布的代码太多,没有什么特别有用的 我有几个回复,其中一个来自用户垃圾狗,他发布了一些解决问题的东西(可以在这里的页面底部找到:),然而,在阅读了他发布的程序中所有我不知道的东西的类描述并经历了它的执行之后,我不明白为什么他的实现了与我不同的效果 他似乎记录了鼠标滚轮的每一个动作,而我只记录最初的动作。还有一些人评论说,他们无法复制我的程序的效果,可能是因为它太大了 下面

几天前,我发布了一个关于一个程序的问题,该程序在鼠标滚轮滚动时导致屏幕上的文本改变颜色。不幸的是,这是一个拼凑得很糟糕的问题,发布的代码太多,没有什么特别有用的

我有几个回复,其中一个来自用户垃圾狗,他发布了一些解决问题的东西(可以在这里的页面底部找到:),然而,在阅读了他发布的程序中所有我不知道的东西的类描述并经历了它的执行之后,我不明白为什么他的实现了与我不同的效果

他似乎记录了鼠标滚轮的每一个动作,而我只记录最初的动作。还有一些人评论说,他们无法复制我的程序的效果,可能是因为它太大了

下面是一个极其简化的版本,仍然会产生相同的效果(我希望如此)

问题:在处理鼠标滚轮事件时,修复屏幕变空白的两个程序之间的根本区别是什么

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));
    }

    }
(如果你试着运行我的代码,试着使劲转动你的鼠标滚轮,它会变得更加明显)

  • while(true){
    是无止境的循环,没有中断

  • 使用
    Swing Timer
    而不是
    Runnable#Thread
    延迟
    Thread.Sleep()

  • 绘制到
    JPanel
    JComponent
    ,而不是直接绘制到
    JFrame

  • 应在
    paintComponent()中完成对
    Swing JComponent
    的所有绘制

  • 更多关于

  • 编辑

    导入java.awt.Color;
    导入java.awt.Dimension;
    导入java.awt.EventQueue;
    导入java.awt.event.MouseAdapter;
    导入java.awt.event.mouseweelEvent;
    导入java.util.LinkedList;
    导入java.util.Queue;
    导入javax.swing.JFrame;
    导入javax.swing.JLabel;
    导入javax.swing.JPanel;
    导入javax.swing.SwingUtilities;
    /**
    *基于@trashgod的例子
    * 
    *@见http://stackoverflow.com/a/10970892/230513
    */
    公共类ColorWheel扩展了JPanel{
    专用静态最终整数N=32;
    私有静态最终长serialVersionUID=1L;
    private final Queue clut=new LinkedList();
    专用最终JLabel标签=新JLabel();
    公共色轮(){
    对于(int i=0;i
    根本区别在于,您试图从错误的线程与图形对象交互,而不知道图形对象当时的状态

    在Swing中与图形对象交互的通常正确方法是创建一个自定义组件,该组件将覆盖
    paintComponent(Graphics)
    方法。在该方法中进行绘图

    您的colorChange()方法可以通过调用
    repaint()
    ,告诉组件重新绘制自己,这最终将导致在正确的时间在正确的线程上调用
    paintComponent(Graphics)


    非常感谢!f.e.代表什么?如果没有一段时间的循环让它继续运行和绘图,程序难道不会保持打开和收听吗?啊,我真的看不出有什么理由为图形而烦恼,特别是在你链接了@trashgood的伟大示例的情况下,除了一些小的更改,对这个wo的健康不重要rld,请在这里查看我的编辑
    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();
                }
            });
        }
    }