我有一个允许用户将数据输入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);
}
}
答案 0 :(得分:1)
答案 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 );
}
}