2012-06-12 191 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