2

我有一个程序允许用户将数据输入到 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);
    }

}
4

2 回答 2

1

也许您可以使用进度监视器 API

于 2013-09-17T09:25:28.657 回答
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 );
       }

}

于 2013-09-20T14:55:34.410 回答