2012-06-12 254 views
1

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

我有几个回复,其中一个来自用户trashdog,他发布了一些可以解决问题的东西(可以在此页面的底部找到:Window going blank during MouseWheelMotion event),但是已经阅读了所有东西的类描述我在他发布的程序中并不知道他的执行情况,我不明白他为什么会实现与我的不同效果。

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

下面是一个非常简化的版本仍然引起相同的效果(我希望)。

问题:两者有什么方案正在处理的鼠标滚轮事件时,修复屏幕一片空白的根本区别?

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

    } 

(尝试旋转你的鼠标滚轮真的很难,如果你尝试运行我的代码,它会变得更加明显)

回答

1
  1. while(true) {是无穷的循环,不休息; F.E.

  2. 使用Swing Timer代替Runnable#Thread通过Thread.Sleep()

  3. 漆推迟到JPanelJComponent,不能直接把JFrame

  4. 都画到Swing JComponentpaintComponent()

  5. 完成更多在2D Graphics tutorial

编辑

enter image description here

enter image description here

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(); 
      } 
     }); 
    } 
} 
+0

非常感谢!什么是f.e.代表?并且不会让程序保持打开状态并听取是否有一段时间循环继续执行并绘图? –

+0

aaaach,真的我看不出理由打扰图形,特别是在你通过@trashgod链接了很好的例子,比一些小的变化,对于这个世界非常重要的东西,请参阅我的编辑在这里 – mKorbel

1

根本不同的是,你正试图与之交互图形从错误的线程,并在不知道状态的任何对象图形对象在当时。

与在Swing一个图形对象交互的一般正确的方法是通过使该覆盖paintComponent(Graphics)方法的定制组件。在该方法内部进行绘图。

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

See tutorial here