2015-08-24 60 views
2

我正在嘗試創建一個圖形繪製程序,允許用戶通過將鼠標拖到屏幕上來繪製紅色像素。所以從某種意義上說,你可以把這個程序想象成微軟的畫圖程序,但只有鉛筆繪畫工具和紅色。如何實時激發MouseMotionListener事件?

不幸的是,我的程序中的mouseDragged()函數無法正常工作。它會跳過一些像素的屏幕上,如果我將我的鼠標速度太快,就像這樣:

enter image description here

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class FrameView extends JFrame { 
    JPanel panel; 
    Graphics2D drawingContext; 

    public static void main(String[] args) { 
     new FrameView(); 
    } 

    public FrameView() { 
     panel = new JPanel(); 
     panel.addMouseMotionListener(new MouseControls()); 
     panel.setBackground(Color.WHITE); 
     this.add(panel); 
     this.setSize(new Dimension(500, 500)); 
     this.setTitle("Drawing Program"); 
     this.setVisible(true); 
     drawingContext = (Graphics2D)panel.getGraphics(); 
    } 

    private class MouseControls extends MouseAdapter { 
     @Override 
     public void mouseDragged(MouseEvent e) { 
      int x = e.getX(); 
      int y = e.getY(); 

      final int WIDTH = 1; 
      final int HEIGHT = 1; 
      Shape pixel = new Rectangle(x, y, WIDTH, HEIGHT); 
      drawingContext.setColor(Color.RED); 
      drawingContext.draw(pixel); 
     } 
    } 
} 
+1

你'MouseListener'工作正常,這是它是如何工作的,它不會報告每一個像素的位置,而只是大多likel y位置更新。相反,在點之間畫線 – MadProgrammer

+1

這不是自定義繪畫在Swing中的工作原理,從不使用'getGraphics',它可以返回'null',並且當組件重新繪製時,它的任何東西都可以被擦除。請參閱[在AWT和Swing中繪畫](http://www.oracle.com/technetwork/java/painting-140037.html)和[執行自定義繪畫](http://docs.oracle.com/javase/tutorial/) uiswing/painting /)獲取更多關於如何在Swing中完成繪畫的細節 – MadProgrammer

回答

7

getGraphics不是如何在Swing繪畫作品,相反,你應該重寫paintComponent組件的方法並在那裏執行自定義繪畫。

繪畫具有破壞性,預計當調用paintComponent時,將完全重新繪製組件的當前狀態。

看一看Painting in AWT and SwingPerforming Custom Painting更多細節

至於你的「鼠標」的問題,這實際上是如何工作的,你就不會被通知每一個像素位置上的鼠標必須通過的,如果有的話,你的鼠標在屏幕上會出現可怕的差距。相反,操作系統會根據用戶輸入的移動速度以不斷增加的步幅移動鼠標。

代替繪圖的只是點,畫出它們之間的線路,例如

Hello World

注:我故意畫大點,所以你可以看到他們是被報道在那裏,你會看到所有的點(對於單拖)連接

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Line2D; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private List<List<Point>> points = new ArrayList<>(25); 
     private List<Point> activeList; 

     public TestPane() { 
      MouseAdapter ma = new MouseAdapter() { 
       @Override 
       public void mouseDragged(MouseEvent e) { 

        if (activeList != null) { 
         activeList.add(e.getPoint()); 
         repaint(); 
        } 
       } 

       @Override 
       public void mousePressed(MouseEvent e) { 
        activeList = new ArrayList<>(25); 
        points.add(activeList); 
       } 

       @Override 
       public void mouseReleased(MouseEvent e) { 
        if (activeList != null && activeList.isEmpty()) { 
         points.remove(activeList); 
        } 
        activeList = null; 
       } 

      }; 
      addMouseMotionListener(ma); 
      addMouseListener(ma); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      g2d.setColor(Color.RED); 
      for (List<Point> group : points) { 
       Point previous = null; 
       for (Point p : group) { 
        // You can get rid of this, it's simply to show 
        // where the points would actually be rendered 
        g2d.fill(new Ellipse2D.Float(p.x - 2, p.y - 2, 4, 4)); 
        if (previous != null) { 
         g2d.draw(new Line2D.Float(previous, p)); 
        } 
        previous = p; 
       } 
      } 
      g2d.dispose(); 
     } 

    } 

} 
相關問題