JTextArea在大型粘贴上冻结UI

时间:2013-09-17 08:14:14

标签: java swing copy-paste jtextarea nonblocking

我有一个允许用户将数据输入JTextArea的程序。然后解析并处理数据以供进一步使用。

虽然我很清楚使用非阻塞文件丢弃的可能性,而且我已经提供了它,但是一些用户也可能会粘贴大块数据。粘贴大约100MB的文本时,整个GUI会挂起大约20-30秒。

在不阻止GUI的情况下,接受如此庞大的数据块的最佳方法是什么?保持JTextArea不是必需的。

如果无法避免阻止GUI:是否有办法捕获并延迟粘贴事件以更新GUI,并显示一条消息:“处理粘贴命令”并继续进行?

代码示例:

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JTextArea;
import java.awt.BorderLayout;


public class JTextAreaExample {

    private JFrame frame;

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

    /**
     * Create the application.
     */
    public JTextAreaExample() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JTextArea textArea = new JTextArea();
        frame.getContentPane().add(textArea, BorderLayout.CENTER);
    }

}

2 个答案:

答案 0 :(得分:1)

可以使用Progress monitor API

答案 1 :(得分:0)

我想分享一个简单的例子我的“解决方案”(感谢Andrew Thompson的提示)。即使这可能没有真正做任何事情,也应该明白这一点。

保持GUI响应正在按预期工作大部分。在没有进一步措施的情况下(实际上必须使用滑动窗口),无法避免在实际更新JTextArea文本时挂起GUI,但这超出了本示例的范围。处理复制缓冲区时不会阻止GUI,这就是问题所在。

import java.awt.EventQueue;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;

import java.awt.BorderLayout;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;


public class JTextAreaExample {

    private JFrame frame;
    private static JTextArea textArea;

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

    /**
     * Create the application.
     */
    public JTextAreaExample() {
        JTextAreaExample.textArea = new JTextArea();
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.getContentPane().add(textArea, BorderLayout.CENTER);
        textArea.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK), "ctrlvpressed");
        textArea.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0), "ctrlvpressed");
        CustomPasteAction cpa = new CustomPasteAction("Custom Paste Action", null, "A custom paste action", KeyEvent.VK_V);
        textArea.getActionMap().put("ctrlvpressed", cpa);
    }

    public static final JTextArea getTextArea() {
        return textArea;
    }

}

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.IOException;

import javax.swing.AbstractAction;
import javax.swing.ImageIcon;

public class CustomPasteAction extends AbstractAction implements ClipboardOwner {

    /** */
    private static final long serialVersionUID = 1L;

    public CustomPasteAction(String text, ImageIcon icon,
                                             String desc, Integer mnemonic) {
        super(text, icon);
        putValue(SHORT_DESCRIPTION, desc);
        putValue(MNEMONIC_KEY, mnemonic);
    }

    public CustomPasteAction() {
        super("Custom Paste Action", null);
        putValue(SHORT_DESCRIPTION, "My custom paste action");
        putValue(MNEMONIC_KEY, KeyEvent.VK_V);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        new Thread(new Runnable() {
        public void run() {

            String temp = new CustomPasteAction().getClipboardContents();
            System.out.println("Processing: " + temp);
            JTextAreaExample.getTextArea().setText(temp);

        }
    }).start();
    }

    @Override
    public void lostOwnership(Clipboard clipboard, Transferable contents) {
        // do nothing
    }

    /**
      * Get the String residing on the clipboard.
      *
      * @return any text found on the Clipboard; if none found, return an
      * empty String.
      */
      public String getClipboardContents() {
        String result = "";
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        //odd: the Object param of getContents is not currently used
        Transferable contents = null;
        try {
            contents = clipboard.getContents(null);
        } catch(IllegalStateException ise) {
            ise.printStackTrace();
        }
        boolean hasTransferableText =
          (contents != null) &&
          contents.isDataFlavorSupported(DataFlavor.stringFlavor)
        ;
        if ( hasTransferableText ) {
          try {
            result = (String)contents.getTransferData(DataFlavor.stringFlavor);
          }
          catch (UnsupportedFlavorException ex){
            //highly unlikely since we are using a standard DataFlavor
            System.out.println(ex);
            ex.printStackTrace();
          }
          catch (IOException ex) {
            System.out.println(ex);
            ex.printStackTrace();
          }
        }
        return result;
      }

      /**
       * Place a String on the clipboard, and make this class the
       * owner of the Clipboard's contents.
       */
       public void setClipboardContents( String aString ){
         StringSelection stringSelection = new StringSelection( aString );
         Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
         clipboard.setContents( stringSelection, this );
       }

}