2013-11-21 38 views
2

我想要创建一个程序,在桌面上用此属性绘制线条,用户可以点击线条旁边的桌面图标。 我创建样本。我创建透明框架并在此上绘制jWindow。在MouseReleased事件中配置主框架,然后保留所有创建的jwindows。我的代码创建了许多jwindow,这非常糟糕。对于画线30厘米程序创建超过400 jwindow,这会导致os非常重。 可以帮助我吗? (恕我丑的英语)在桌面上画一条线,点击可以在线左右

package PKHMain; 

    import java.awt.Color; 
    import java.awt.Dimension; 
    import java.awt.Graphics; 
    import java.awt.Graphics2D; 

import java.awt.GridBagLayout; 
import java.awt.RenderingHints; 
import java.awt.Toolkit; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.event.MouseMotionListener; 
import java.awt.geom.Ellipse2D; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JWindow; 

public class FRMMain extends JFrame implements MouseListener, MouseMotionListener { 

    public FRMMain() { 
     this.setUndecorated(true); 
     this.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height); 
     this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
     this.setLayout(null); 
     this.setBackground(new Color(0, 0, 0, 0)); 
     this.setVisible(true); 
     addMouseListener(this); 
     addMouseMotionListener(this); 
    } 

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

    @Override 
    public void mousePressed(MouseEvent event) { 
    } 

    @Override 
    public void paint(Graphics g) { 
     repaint(); 
    } 

    @Override 
    public void mouseClicked(MouseEvent event) { 
    } 

    @Override 
    public void mouseEntered(MouseEvent event) { 
    } 

    @Override 
    public void mouseExited(MouseEvent event) { 
    } 

    @Override 
    public void mouseReleased(MouseEvent event) { 
     this.dispose(); 
    } 

    @Override 
    public void mouseDragged(MouseEvent event) { 
     int x = event.getX(); 
     int y = event.getY(); 
     JWindow frame = new JWindow(); 
     frame.setBackground(new Color(0, 0, 0, 0)); 
     frame.setContentPane(new ShapedPane(x, y)); 
     frame.pack(); 
     frame.setLocation(x, y); 
     frame.setAlwaysOnTop(true); 
     frame.setVisible(true); 
    } 

    public void mouseMoved(MouseEvent event) { 
    } 

    public class ShapedPane extends JPanel { 

     public int x1; 
     public int y1; 

     public ShapedPane(int x, int y) { 
      setOpaque(false); 
      setLayout(new GridBagLayout()); 
      x1 = x; 
      y1 = y; 
     } 

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

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2 = (Graphics2D) g.create(); 
      RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      g2.setRenderingHints(hints); 
      g2.setColor(Color.red); 
      g2.fill(new Ellipse2D.Double(0, 0, getWidth(), getHeight())); 
      g2.dispose(); 
     } 
    } 
} 
+0

我的问题,很重要的是你是为什么原因是油漆()与重绘绘画(),它可以导致高度处理器消耗或无限循环 – mKorbel

+0

我删除了paint()方法,并没有改变任何东西。 –

+0

将形状列表放到FRMMain类中,并在FRMMain框架的paint方法内绘制这些形状,并且不要创建任何新窗口。 – Holger

回答

2

你与你的程序,例如触摸系统的特定行为在我的机器上,程序将不会收到任何鼠标事件,因为背景颜色的alpha值为零。将其设置为至少一个使其可以接受点击和拖动。因此,这是一种控制所需点击行为的方式,但它可能不适用于您。

这是因为它在我的机器(的Java 7和Windows 7)上运行的程序:

import java.awt.*; 
import java.awt.event.MouseEvent; 
import java.awt.geom.Ellipse2D; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.JFrame; 

public class FRMMain extends JFrame { 
    private final List<Shape> list=new ArrayList<>(); 
    private boolean paintPhase=true; 

    public FRMMain() { 
     this.setUndecorated(true); 
     final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
     this.setSize(screenSize.width, screenSize.height); 
     this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
     this.setBackground(new Color(0, 0, 0, 1)); 
     this.setOpacity(1f); 
     this.setAlwaysOnTop(true); 
     this.setVisible(true); 
     enableEvents(AWTEvent.MOUSE_EVENT_MASK|AWTEvent.MOUSE_MOTION_EVENT_MASK); 
    } 
    @Override 
    protected void processMouseEvent(MouseEvent e) { 
    if(paintPhase && e.getID()==MouseEvent.MOUSE_RELEASED) { 
     paintPhase = false; 
     // on my machine the following line is enough to enable click-through 
     setBackground(new Color(0, 0, 0, 0)); 
     // but if this doesn’t work, the following should do: 
     Area area=new Area(); 
     BasicStroke b=new BasicStroke(2f); 
     for(Shape s:list) area.add(new Area(b.createStrokedShape(s))); 
     setShape(area); 
    } 
    super.processMouseEvent(e); 
    } 
    @Override 
    protected void processMouseMotionEvent(MouseEvent event) 
    { 
    if(paintPhase && event.getID()==MouseEvent.MOUSE_DRAGGED) { 
     int x = event.getX(); 
     int y = event.getY(); 
     list.add(new Ellipse2D.Float(x, y, 8, 8)); 
     repaint(); 
    } 
    super.processMouseMotionEvent(event); 
    } 
    @Override 
    public boolean contains(int x, int y) { 
    return paintPhase; 
    } 

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

    @Override 
    public void paint(Graphics g) { 
    Graphics2D gfx=(Graphics2D)g; 
    gfx.setColor(Color.RED); 
    for(Shape s:list) gfx.draw(s); 
    } 
} 
+0

嗨Holger。感谢您的重播。 –

+0

嗨Holger。感谢您的重播。我可以画鼠标事件。我需要程序,我可以在屏幕上绘制线条,画线后屏幕上的所有对象都将可用(图标,文本...)。在你的程序中透明层留在屏幕上!我需要在画线后单独留在桌面上。 –

+0

如上所述,在我的机器上,它的工作原理与在鼠标释放时将背景alpha设置为零一样,将启用点击透明度。如果这样做对你不起作用,你可以尝试在窗口中使用'setShape',并使用列表中所有形状的复合形状。好吧,我更新了答案,以说明如何做到这一点。看看'processMouseEvent'方法... – Holger