等待光标并禁用java应用程序

问题描述:

我想让用户按下按钮来启动后台线程。等待光标并禁用java应用程序

虽然线程处理,我想两件事情:

1)WAIT_CURSOR应显示。

2)应用程序不应响应鼠标事件。 “

根据setCursor documentation”当此组件的contains方法对当前光标位置返回true时,将显示此光标图像,并且此组件可见,可显示并启用。“。

我想我的应用程序,而这个后台线程处理被禁用。

任何想法如何获得我想要的功能?

import java.awt.Component; 
import java.awt.Cursor; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class WaitCursor extends JFrame 
{ 
    private static final long serialVersionUID = 1L; 

    public WaitCursor() 
    { 
     setResizable(false); 

     setName(getClass().getSimpleName()); 
     setTitle("My Frame"); 
     setSize(300, 300); 

     getContentPane().add(new MyButtonPanel()); 

    } 

    private class MyButtonPanel extends JPanel 
    { 

     private static final long serialVersionUID = 1L; 

     public MyButtonPanel() 
     { 
      JButton btnStart = new JButton("Start"); 
      btnStart.addActionListener(new BtnStartActionListener()); 
      add(btnStart); 
     } 

     private class BtnStartActionListener implements ActionListener 
     { 
      public void actionPerformed(ActionEvent e) 
      { 
       // Change to WAIT_CURSOR 
       Component root = SwingUtilities.getRoot((JButton) e.getSource()); 
       JOptionPane.showMessageDialog(root, "Wait 10 seconds"); 
       root.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 

       // TODO: Disabling the root component prevents the WAIT_CURSOR from being displayed 
       root.setEnabled(false); 
       new Thread(new TimeKiller(root)).start(); 
      } 
     } 
    } 

    private class TimeKiller implements Runnable 
    { 
     Component _root; 

     public TimeKiller(Component root) 
     { 
      _root = root; 
     } 

     public void run() 
     { 
      try 
      { 
       Thread.sleep(10 * 1000); 
      } 
      catch (InterruptedException e) 
      { 
       // Ignore it 
      } 
      // Change back to DEFAULT CURSOR 
      JOptionPane.showMessageDialog(_root, "Done waiting"); 
      _root.setCursor(Cursor.getDefaultCursor()); 
      _root.setEnabled(true); 
     } 
    } 

    private static void createAndShowGUI() 
    { 
     // Create and set up the window. 
     WaitCursor frame = new WaitCursor(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       try 
       { 
        createAndShowGUI(); 
       } 
       catch (Exception e) 
       { 
        e.printStackTrace(); 
        System.exit(0); 
       } 
      } 
     }); 
    } 

} 
+0

请参阅编辑回答。 – 2012-01-31 03:14:54

issue 065 from Javaspecialists.eu完全回答你的问题。

+0

谢谢!您指向我的页面非常有用,内容丰富。我最终使用了它所描述的方法,并对它的工作方式感到满意。我尝试使用KeyboardFocusManager.setCurrentKeyboardFocusManager(doNothingKeyboardFocusMgr)添加对键盘的支持;不幸的是,我的应用程序弹出了不再接收键盘输入的对话框。我认为它与KeyboardFocusManager有关。我会在这里发布解决方案,如果/当我弄明白的时候。 – bigleftie 2012-02-01 21:04:57

+0

解决方案:在显示WAIT_CURSOR时,我使用glassPane.addKeyListener(aDoNothingKeyListener)完全阻止所有忽略活动,而不是KeyboardFocusManager。 – bigleftie 2012-03-17 23:17:14

禁用它的一种方法是使用玻璃窗格来阻止鼠标输入。

例如:

import java.awt.Cursor; 
import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.MouseAdapter; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class WaitCursor2 extends JPanel { 

    private static final int PREF_W = 400; 
    private static final int PREF_H = PREF_W; 
    private JComponent glassPane; 
    private JButton runBackgroundProcBtn; 
    private JTextArea textarea = new JTextArea(15, 30); 

    public WaitCursor2(JComponent glassPane) { 
     this.glassPane = glassPane; 
     glassPane.setFocusable(true); 
     glassPane.addMouseListener(new MouseAdapter() { 
     }); // so it will trap mouse events. 

     add(new JTextField(10)); 
     add(runBackgroundProcBtn = new JButton(new AbstractAction(
      "Run Background Process") { 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      runBackgroundProcessAction(); 
     } 
     })); 
     add(new JScrollPane(textarea)); 
    } 

    private void runBackgroundProcessAction() { 
     disableSystem(true); 
     glassPane.setVisible(true); 
     new SwingWorker<Void, Void>() { 
     @Override 
     protected Void doInBackground() throws Exception { 
      long sleepTime = 5000; 
      Thread.sleep(sleepTime); 
      return null; 
     } 

     @Override 
     protected void done() { 
      disableSystem(false); 
     } 
     }.execute(); 
    } 

    public void disableSystem(boolean disable) { 
     glassPane.setVisible(disable); 
     runBackgroundProcBtn.setEnabled(!disable); 
     if (disable) { 
     System.out.println("started"); 
     glassPane.requestFocusInWindow(); // so can't add text to text components 
     glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 
     } else { 
     System.out.println("done"); 
     glassPane.setCursor(Cursor.getDefaultCursor()); 
     } 
    } 

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

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("WaitCursor2"); 
     WaitCursor2 mainPanel = new WaitCursor2((JComponent) frame.getGlassPane()); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

的玻璃板将捕获鼠标事件,如果将其设置可见和给予的MouseListener。如果它被设置为不可见,它将失去他的能力。同样,如果您将它设置为可对焦并将焦点对准,它将从文本组件中提取插入符号。

+1

使用glassPane.requestFocusInWindow()将焦点移动到窗口(并从任何可能已有的文本组件中移出),但此方法不会阻止具有WAIT_CURSOR的窗口中的键盘活动。使用TAB键,用户可以导航到窗口中的任何文本字段并输入文本。我使用glassPane.addKeyListener(aDoNothingKeyListener)在显示WAIT_CURSOR时完全阻止所有忽略活动。 – bigleftie 2012-03-17 23:21:35

添加一个字段current_active和在方法的actionPerformed,做一个简单的检查。虽然它不是完美的,但对于简单的应用程序,我认为这是做的伎俩。解决你的两个要求的粗略方法。 :-)希望它也适用于你。

import java.awt.Component; 
import java.awt.Cursor; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 


public class WaitCursor extends JFrame 
{ 
    private static boolean current_active = false; 

    public WaitCursor() 
    { 
     setResizable(false); 

     setName(getClass().getSimpleName()); 
     setTitle("My Frame"); 
     setSize(300, 300); 

     getContentPane().add(new MyButtonPanel()); 
    } 

    private class MyButtonPanel extends JPanel 
    { 

     public MyButtonPanel() 
     { 
      JButton btnStart = new JButton("Start"); 
      btnStart.addActionListener(new BtnStartActionListener()); 
      add(btnStart); 
     } 

     private class BtnStartActionListener implements ActionListener 
     { 



      // change to wait_cursor 
      public void actionPerformed(ActionEvent e) 
      { 
       if (!current_active) 
       { 
        Component root = SwingUtilities.getRoot((JButton) e.getSource()); 
        JOptionPane.showMessageDialog(root, "Wait 10 seconds"); 
        root.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 

        // TODO: Disabling the root component prevents the WAIT_CURSOR from being displayed 
        //root.setEnabled(false); 
        current_active = true; 
        new Thread(new TimeKiller(root)).start(); 

       } 
      } 
     } 
    } 

    private class TimeKiller implements Runnable 
    { 
     Component m_root; 

     public TimeKiller(Component p_root) 
     { 
      m_root = p_root; 

     }  

     @Override 
     public void run() 
     { 
      try 
      { 
       Thread.sleep(10 * 1000);     
      } 
      catch (InterruptedException e) 
      { 
       //Ignore it 
      } 
      // Change back to DEFAULT CURSOR 
      JOptionPane.showMessageDialog(m_root, "Done waiting"); 
      m_root.setCursor(Cursor.getDefaultCursor()); 
      current_active = false; 
     } 

    } 

    // create and setup the window. 
    public static void createAndShowGUI() 
    { 
     WaitCursor frame = new WaitCursor(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 

    } 

    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       try 
       { 
        createAndShowGUI(); 
       } 
       catch (Exception e) 
       { 
        e.printStackTrace(); 
        System.exit(0); 
       } 
      } 
     }); 
    } 

}