使用计时器更新jframe组件的位置

时间:2012-05-08 19:46:02

标签: java swing jframe mouseevent jlabel

我正在尝试制作一个使用标签来追逐用户鼠标的程序,我有两个问题:

首先,标签的位置由整个计算机屏幕的坐标而不仅仅是窗口来判断。

其次,当计时器使用repaint()时,标签在应用程序期间不会移动。

private JPanel contentPane;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                MouseFollowDisplay frame = new MouseFollowDisplay();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */
public MouseFollowDisplay() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);

    final JLabel lblNewLabel = new JLabel("RUN!");
    lblNewLabel.setRequestFocusEnabled(false);
    lblNewLabel.setLocation(new Point(5, 5));
    lblNewLabel.setBounds(10, 11, 31, 23);
    contentPane.add(lblNewLabel);

    contentPane.addMouseListener(new MouseAdapter() {

        int DELAY = 500;

        ActionListener MouseDetect = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub

                PointerInfo a = MouseInfo.getPointerInfo();
                Point b = a.getLocation();
                int x = (int) b.getX();
                int y = (int) b.getY();
                System.out.println(x + "," + y); 

                int lx = lblNewLabel.getX();
                int ly = lblNewLabel.getY();

                if (lx <= x+5 && lx >= x-5 && ly <= y+5 && ly >= y-5){
                    DetectMouse.stop();
                    JOptionPane.showMessageDialog(null, "You Lose!");
                }else{
                    lx = -((lx - x) * 5) / (Math.abs(lx - x));
                    ly = -((ly - y) * 5) / (Math.abs(ly - y));
                    lblNewLabel.repaint(lx, ly, 31, 23);
                }

                if (DELAY >= 150) {
                    DELAY -= 5;
                    DetectMouse.setDelay(DELAY);
                }
            }
        };

        Timer DetectMouse = new Timer(DELAY, MouseDetect);

        public void mouseClicked(MouseEvent arg0) {
            if (DetectMouse.isRunning()){
                DetectMouse.stop();
                DELAY = 500;
            }
            else{
                DetectMouse.start();    
            }
        }   
    });
}

}

1 个答案:

答案 0 :(得分:2)

lblNewLabel.repaint(lx, ly, 31, 23)

通话不会移动您的标签。请参阅该重绘方法的javadoc

  

如果组件正在显示,则将指定的区域添加到脏区列表。在调度了所有当前挂起的事件后,将重新绘制该组件。

您需要做的是调整标签的位置,然后重新绘制面板(标签的旧区域和新区域)。

更好的方法是null布局拥有您自己的JComponentJPanel,您可以覆盖paintComponent方法并使用Graphics#drawString绘制该字符串方法。在这种情况下,请不要忘记致电super.paintComponent以避免文本多次出现(例如,请参阅this SO question,了解如果您忘记致电super.paintComponent会发生什么事情)