2012-01-31 61 views
4

我想讓用戶按下按鈕來啓動後臺線程。等待光標並禁用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

回答

5

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

4

禁用它的一種方法是使用玻璃窗格來阻止鼠標輸入。

例如:

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

0

添加一個字段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); 
       } 
      } 
     }); 
    } 

}