My goal is to implement blue coloring of keywords written by user into JTextPane. This is how my code look like:
private class DocumentHandler implements DocumentListener {
#Override
public void changedUpdate(DocumentEvent ev) {
}
#Override
public void insertUpdate(DocumentEvent ev) {
highlight();
}
#Override
public void removeUpdate(DocumentEvent ev) {
highlight();
}
private void highlight() {
String code = codePane.getText();
SimpleAttributeSet defSet = new SimpleAttributeSet();
StyleConstants.setForeground(defSet, Color.BLACK);
doc.setCharacterAttributes(0, code.length(), defSet, true);
SimpleAttributeSet set = new SimpleAttributeSet();
StyleConstants.setForeground(set, Color.BLUE);
for (String keyword : keywords) {
Pattern pattern = Pattern.compile(keyword + "(\\[\\])*");
Matcher matcher = pattern.matcher(code);
while (matcher.find()) {
//Just for test
System.out.print("Start index: " + matcher.start());
System.out.print(" End index: " + matcher.end());
System.out.println(" Found: " + matcher.group());
doc.setCharacterAttributes(matcher.start(), keyword.length(), set, true);
}
}
}
}
After typing anything into pane I get:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Attempt to mutate in notification
at javax.swing.text.AbstractDocument.writeLock(AbstractDocument.java:1338)
at javax.swing.text.DefaultStyledDocument.setCharacterAttributes(DefaultStyledDocument.java:500)
at jnotepad.MainPanel$DocumentHandler.highlight(MainPanel.java:121)
at jnotepad.MainPanel$DocumentHandler.insertUpdate(MainPanel.java:108)
at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:202)
at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:749)
How to solve my problem? Maybe I should use something other than DocumentListener?
You need to invoke changes to the document from the Event Dispatcher Thread.
Try this:
private void highlight() {
Runnable doHighlight = new Runnable() {
#Override
public void run() {
// your highlight code
}
};
SwingUtilities.invokeLater(doHighlight);
}
I had the same problem, I solved it by using this:
expiration_timeTF.getDocument().addDocumentListener(
new DocumentListener() {
#Override
public void removeUpdate(DocumentEvent e) {
System.out.println("remove");
}
private void assistDateText() {
Runnable doAssist = new Runnable() {
#Override
public void run() {
// when input "2013",will add to "2013-";when
// input "2013-10",will add to "2013-10-"
String input = expiration_timeTF.getText();
if (input.matches("^[0-9]{4}")) {
expiration_timeTF.setText(input + "-");
} else if (input.matches("^[0-9]{4}-[0-9]{2}")) {
expiration_timeTF.setText(input + "-");
}
}
};
SwingUtilities.invokeLater(doAssist);
}
#Override
public void insertUpdate(DocumentEvent e) {
// System.out.println("insert");
assistDateText();
}
#Override
public void changedUpdate(DocumentEvent e) {
// System.out.println("change");
}
});
Related
I have have implementaed a plugin project and want to use TestNG tab for runner purpose in this application. I have a solution for JUnit but in TestNG still I am stuck. Please help out from this situation. Kindly find the JUnit configuration tab code in below:
public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
new JUnitLaunchConfigurationTab(),
new JavaArgumentsTab(),
new JavaClasspathTab(),
new JavaJRETab(),
new SourceLookupTab(),
new EnvironmentTab(),
new CommonTab()
};
setTabs(tabs);
}
Please suggest.
****First create TestTab.java class by extend AbstractLaunchConfigurationTab******
private ILaunchConfigurationDialog fLaunchConfigurationDialog;
private final TestNGMainTab testngLaunchTab;
private Button runInUIThread;
/**
* Constructor to create a new junit test tab
*/
public TestTab() {
this.testngLaunchTab = new TestNGMainTab();
}
public void createControl(Composite parent) {
testngLaunchTab.createControl(parent);
Composite composite = (Composite) getControl();
createSpacer(composite);
createRunInUIThreadGroup(composite);
}
private void createRunInUIThreadGroup(Composite comp) {
runInUIThread = new Button(comp, SWT.CHECK);
runInUIThread.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
updateLaunchConfigurationDialog();
}
});
runInUIThread.setText(PDEUIMessages.PDEJUnitLaunchConfigurationTab_Run_Tests_In_UI_Thread);
GridDataFactory.fillDefaults().span(2, 0).grab(true, false).applyTo(runInUIThread);
}
private void createSpacer(Composite comp) {
Label label = new Label(comp, SWT.NONE);
GridDataFactory.fillDefaults().span(3, 0).applyTo(label);
}
public void initializeFrom(ILaunchConfiguration config) {
testngLaunchTab.initializeFrom(config);
updateRunInUIThreadGroup(config);
}
private void updateRunInUIThreadGroup(ILaunchConfiguration config) {
boolean shouldRunInUIThread = true;
try {
shouldRunInUIThread = config.getAttribute(IPDELauncherConstants.RUN_IN_UI_THREAD, true);
} catch (CoreException ce) {
}
runInUIThread.setSelection(shouldRunInUIThread);
}
public void performApply(ILaunchConfigurationWorkingCopy config) {
testngLaunchTab.performApply(config);
boolean selection = runInUIThread.getSelection();
config.setAttribute(IPDELauncherConstants.RUN_IN_UI_THREAD, selection);
}
#Override
public String getId() {
return IPDELauncherConstants.TAB_TEST_ID;
}
#Override
public void activated(ILaunchConfigurationWorkingCopy workingCopy) {
testngLaunchTab.activated(workingCopy);
}
#Override
public boolean canSave() {
return testngLaunchTab.canSave();
}
#Override
public void deactivated(ILaunchConfigurationWorkingCopy workingCopy) {
testngLaunchTab.deactivated(workingCopy);
}
#Override
public void dispose() {
testngLaunchTab.dispose();
}
#Override
public String getErrorMessage() {
return testngLaunchTab.getErrorMessage();
}
#Override
public Image getImage() {
return testngLaunchTab.getImage();
}
#Override
public String getMessage() {
return testngLaunchTab.getMessage();
}
public String getName() {
return testngLaunchTab.getName();
}
#Override
public boolean isValid(ILaunchConfiguration config) {
return testngLaunchTab.isValid(config);
}
public void setDefaults(ILaunchConfigurationWorkingCopy config) {
testngLaunchTab.setDefaults(config);
}
#Override
public void setLaunchConfigurationDialog(ILaunchConfigurationDialog dialog) {
testngLaunchTab.setLaunchConfigurationDialog(dialog);
this.fLaunchConfigurationDialog = dialog;
}
*** create Interface ITestNGPluginLauncherConstants*****
public interface ITestNGPluginLauncherConstants {
String LEGACY_UI_TEST_APPLICATION =
"org.testng.eclipse.runtime.legacytestapplication";
String NON_UI_THREAD_APPLICATION =
"org.testng.eclipse.runtime.nonuithreadtestapplication";
String UI_TEST_APPLICATION =
"org.testng.eclipse.runtime.uitestapplication";
String CORE_TEST_APPLICATION =
"org.testng.eclipse.runtime.coretestapplication";
String TestNGProgramBlock_headless = "No application [Headless]";
String TAB_PLUGIN_TESTNG_MAIN_ID =
"org.testng.eclipse.plugin.launch.tab.main";
}
****create class PluginTestNGMainTab.java*****
public class TestNGPluginTabGroup extends
AbstractLaunchConfigurationTabGroup {
public TestNGPluginTabGroup() {
}
public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
new TestTab(),
new PluginTestNGMainTab(),
new JavaArgumentsTab(),
new PluginsTab(false),
new JavaArgumentsTab(),
new PluginsTab(),
new TracingTab(),
new ConfigurationTab(true),
new TracingTab(),
new EnvironmentTab(),
new CommonTab()
};
setTabs(tabs);
}
}
**** create class TestNGProgramBlock.java extends ProgramBlock*****
public TestNGProgramBlock(AbstractLauncherTab tab) {
super(tab);
}
public void setDefaults(ILaunchConfigurationWorkingCopy config) {
if (!LauncherUtils.requiresUI(config))
config.setAttribute(IPDELauncherConstants.APPLICATION,
ITestNGPluginLauncherConstants.CORE_TEST_APPLICATION);
else
super.setDefaults(config);
}
protected String[] getApplicationNames() {
TreeSet result = new TreeSet();
result.add(ITestNGPluginLauncherConstants.TestNGProgramBlock_headless);
String[] appNames = super.getApplicationNames();
for (int i = 0; i < appNames.length; i++) {
result.add(appNames[i]);
}
return appNames;
}
protected void initializeApplicationSection(ILaunchConfiguration config)
throws CoreException {
String application =
config.getAttribute(IPDELauncherConstants.APPLICATION, (String)null);
if(ITestNGPluginLauncherConstants.CORE_TEST_APPLICATION.
equals(application))
fApplicationCombo.setText(ITestNGPluginLauncherConstants.
TestNGProgramBlock_headless);
else
super.initializeApplicationSection(config);
}
protected void saveApplicationSection(ILaunchConfigurationWorkingCopy config)
{
if(fApplicationCombo.getText().equals(ITestNGPluginLauncherConstants.
TestNGPogramBlock_headless)){
String appName = fApplicationCombo.isEnabled() ?
ITestNGPluginLauncherConstants.CORE_TEST_APPLICATION : null;
config.setAttribute(IPDELauncherConstants.APPLICATION, appName);
config.setAttribute(IPDELauncherConstants.APP_TO_TEST, (String)null);
}
}
}
I've code like this:
public main() {
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(700, 500);
//tabbed pane
add(tb);
}
public JTextArea txtArea() {
JTextArea area = new JTextArea();
String st = String.valueOf(tab);
area.setName(st);
return area;
}
public static void main (String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new main();
}
});
}
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if(source==mnew) {
tab++;
tb.add("Untitled-"+tab,new JPanel().add(txtArea()));
int s = tb.getSelectedIndex();
s = tb.getTabCount()-1;
tb.setSelectedIndex(s);
}
if(source==save) {
int s = tb.getSelectedIndex()+1;
}
Every click on the "New" menu item, code creates new tab with new panel and textarea (it's similar to a lot of text editors like notepad++).
After clicked "Save" in menu bar I want to get text from focused jtextarea.
Please help.
Add a document listener to the text area.
public JTextArea txtArea() {
JTextArea area = new JTextArea();
tstDocumentListener dcL = new tstDocumentListener();
area.getDocument().addDocumentListener(dcL);
String st = String.valueOf(tab);
area.setName(st);
return area;
}
tstDocumentListener
public class tstDocumentListener implements DocumentListener
{
public void changedUpdate(DocumentEvent e) {}
public void removeUpdate(DocumentEvent e)
{
String newString = "";
int lengthMe = e.getDocument().getLength();
try
{
newString = e.getDocument().getText(0,lengthMe);
System.out.println(newString);
}
catch(Exception exp)
{
System.out.println("Error");
}
}
public void insertUpdate(DocumentEvent e)
{
String newString = "";
int lengthMe = e.getDocument().getLength();
try
{
newString = e.getDocument().getText(0,lengthMe);
System.out.println(newString);
}
catch(Exception exp)
{
System.out.println("Error");
}
}
}
Edit
As for getting the text when you gain or lose focus on the text area
public JTextArea txtArea() {
JTextArea area = new JTextArea();
CustomFocusListener cFL = new CustomFocusListener();
area.addFocusListener(cFL);
String st = String.valueOf(tab);
area.setName(st);
return area;
}
CustomFocusListener
public class CustomFocusListener implements FocusListener
{
#Override
public void focusGained(FocusEvent e)
{
String parseMe = "";
JTextArea src;
try
{
src = (JTextArea)e.getSource();
parseMe = src.getText();
System.out.println(parseMe);
}
catch (ClassCastException ignored)
{
}
}
#Override
public void focusLost(FocusEvent e)
{
String parseMe = "";
JTextArea src;
try
{
src = (JTextArea)e.getSource();
parseMe = src.getText();
System.out.println(parseMe);
}
catch (ClassCastException ignored)
{
}
}
}
Currently I'm using this code but it's not working properly , when i remove 1 or 2 or 3 digit out of 17 but success icon still visible.
#Override
public void keyReleased(KeyEvent e) {
if(Strings.isNullOrEmpty(txtVID.getText())){
lblIDValidation.setIcon(null);
isVIDValid= false;
}
}
#Override
public void keyPressed(KeyEvent e) {
if(txtVID.getText().length()==16 || txtVID.getText().length()==12 || txtVID.getText().length()==17){
lblIDValidation.setIcon(createImageIcon(CommonUtil.success));
isVIDValid= true;
return;
}
lblIDValidation.setIcon(createImageIcon(CommonUtil.danger));
isVIDValid= false;
}
A KeyListener is a poor choice, generally, but espcially for text components, apart from not guaranteeing the order in which key events might be delivered to your listener, which could change the behavior on different platforms, they don't take into account what happens when you use setText or the user pastes text into the field.
A better choice is to use a DocumentListener, for example
JTextField field = new JTextField(20);
field.getDocument().addDocumentListener(new DocumentListener() {
public void verify() {
int length = field.getText().trim().length();
if (length >= 16 && length <= 17) {
field.setBackground(null);
} else {
field.setBackground(Color.RED);
}
}
#Override
public void insertUpdate(DocumentEvent e) {
verify();
}
#Override
public void removeUpdate(DocumentEvent e) {
verify();
}
#Override
public void changedUpdate(DocumentEvent e) {
verify();
}
});
field.setText(" ");
field.setText(null);
See Listening for Changes on a Document for more details
Now it's working fine....If anyone have problem to use this code just comment below.
lblIDValidation.setIcon(null);
txtVID.getDocument().addDocumentListener(new DocumentListener() {
public void verify() {
int length = txtVID.getText().trim().length();
if (length == 17 || length == 13) {
lblIDValidation.setIcon(createImageIcon(CommonUtil.success));
isVIDValid= true;
} else {
lblIDValidation.setIcon(createImageIcon(CommonUtil.danger));
isVIDValid= false;
}
}
#Override
public void insertUpdate(DocumentEvent e) {
verify();
}
#Override
public void removeUpdate(DocumentEvent e) {
verify();
}
#Override
public void changedUpdate(DocumentEvent e) {
verify();
}
});
txtVID.setText(null);
I'm using a indicator progress set to -1.0 to show some loading while loginprocess is running.
But when I press the Enter button and start my executor with the loginProcess, my interface stays freezed even if I use Plataform.runLater to set visible my ProgressIndicator.
My button event:
public void initManager(final LoginManager loginManager) {
btnEntrar.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
String email = loginTxtField.getText().trim();
String token = tokenTxtField.getText().trim();
if (email.equals("")) {
Platform.runLater(new Runnable() {
public void run() {
Dialog.showError("Erro", "Digite o e-mail");
}
});
return;
}
try {
Future future = loginProcess(email, token);
showLoginLoading(future);
future.get();
if (!loginGatewayFailed && !loginTargetAppFailed) {
Login loginTargetApp = new Login(email, null, null);
loginManager.autheticated(loginTargetApp, loginGateway, gateway, file);
} else {
if (loginTargetAppFailed) {
Platform.runLater(new Runnable() {
public void run() {
Dialog.showError("Erro", loginTargetAppFailedCause);
}
});
} else {
if (loginGatewayFailed) {
Platform.runLater(new Runnable() {
public void run() {
Dialog.showError("Erro", loginGatewayFailedCause);
}
});
}
}
}
} catch (final Exception ex) {
Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, ex.getMessage());
Platform.runLater(new Runnable() {
public void run() {
Dialog.showError("Erro", ex.getMessage());
}
});
}
}
});
}
My loginProcess:
public Future<?> loginProcess(String email, String token) throws Exception {
// MY PROCESS
return Executors.newSingleThreadExecutor().submit(new LoginTask(this, email, token));
} catch (Exception e) {
Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, e.getMessage());
throw e;
}
}
method showLoginLoading:
private void showLoginLoading(Future future) {
while (!future.isDone()) {
Platform.runLater(new Runnable() {
#Override
public void run() {
progressInd.setVisible(true);
// progressInd.setProgress(-1.0);
}
});
}
}
The problem was in thread management. I was trying to execute the login instructions in the same thread that the main FX view runs.
I figured it out using the Platform.isFxApplicationThread(); It returns true if the calling thread is the JavaFX Application Thread.
To fix my problem i just needed to create a new thread to run all my login instructions as you can see in bellow example:
public void initManager(final LoginManager loginManager) {
btnEntrar.setOnAction(new EventHandler<ActionEvent>() {
boolean mainThread = Platform.isFxApplicationThread();
System.out.println("This is the main Thread: " + mainThread);
Platform.runLater(new Runnable() {
#Override
public void run() {
progressInd.setVisible(true);
}
});
new Thread() {
public void run() {
boolean mainThread = Platform.isFxApplicationThread();
System.out.println("This is the main Thread: " + mainThread);
String email = loginTxtField.getText().trim();
String token = tokenTxtField.getText().trim();
if (email.equals("")) {
Platform.runLater(new Runnable() {
public void run() {
Dialog.showError("Erro", "Digite o e-mail");
}
});
return;
}
try {
Future future = loginProcess(email, token);
// showLoginLoading(future);
future.get();
if (!loginGatewayFailed && !loginTargetAppFailed) {
Login loginTargetApp = new Login(email, null, null);
loginManager.autheticated(loginTargetApp, loginGateway, gateway, file);
} else {
if (loginTargetAppFailed) {
Platform.runLater(new Runnable() {
public void run() {
Dialog.showError("Erro", loginTargetAppFailedCause);
}
});
} else {
if (loginGatewayFailed) {
Platform.runLater(new Runnable() {
public void run() {
Dialog.showError("Erro", loginGatewayFailedCause);
}
});
}
}
}
} catch (final Exception ex) {
Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, ex.getMessage());
Platform.runLater(new Runnable() {
public void run() {
Dialog.showError("Erro", ex.getMessage());
}
});
}
}
}.start();
});
}
How can i use the callme(input); to get launched with a new thread?
/* We send username and password for register and load a heavy load */
public class button3 implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String input = output.getText();
if (input.length()<=0)
{
JOptionPane.showMessageDialog(null, "Empty....");
} else {
callme(input);
}
}
}
public static String callme() { //heavy loads... starts, which freezed the button
return "Did you called me?";
}
Try 1: but getting failed (output1 does not get the returned text results):
/* We send username and password for register and nat mapping */
public class button3 implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String input = output.getText();
if (input.length()<=0)
{
JOptionPane.showMessageDialog(null, "Empty....");
} else {
new Thread(new Runnable() {
public void run() {
try {
output1.setText( callme(output.getText()) );
} catch(Exception t) {
}
}
}).start();
}
}
}
Try 2: Also tried this, did not returns output1 = callme();
new Thread(new Runnable() {
public void run() {
final String result = callme(output.getText());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
output1.setText( result );
} catch(Exception t) {
}
}
});
}
}).start();
new Thread(new Runnable() {
public void run() {
try {
callme(input);
} catch(Exception t) {
// appropriate error reporting here
}
}
}).start();
Note that input must be declared as final.
Also, consider using invokeLater(Runnable) from Swing Utilities
Try this:
public class button3 implements ActionListener {
public void actionPerformed(ActionEvent e) {
final String input = output.getText();
if ( input.length() <= 0 ) {
JOptionPane.showMessageDialog(null, "Empty....");
}
else {
Thread t = new Thread(new Runnable() {
public void run() {
callme(input);
}
});
t.start();
}
}
public static String callme(String input) {}
}
If you modify swing controls inside your method you should use
new Thread(new Runnable() {
#Override
public void run() {
final String result = callme(input);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
output1.setText( result );
} catch(Exception t) {
}
}
});
}
}).start();
If you need the return value, you should really be using a Callable with an ExecutorService which will give you back a Future that you can use the retrieve the value later on.
See:
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html