Just want the color of the letters to change with a little pauses (pause may vary as per the time given for a word and length of the word).
The following code works fine for me.But I think I have created a mess with my logic.I can understand, but it should be easy for my team mates to understand.
Code:
import java.awt.Color;
import java.lang.reflect.InvocationTargetException;
import java.awt.Toolkit;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Reminder
{
static JFrame frame;
Toolkit toolkit;
Timer timer;
int point=0,temp=0,hil=0,point2=0;long time1=0,time2=0;
static StyledDocument doc;
static JTextPane textpane;
String[] arr={"Tes"," hiiii"," what"," happpn"};
int i=0;
int[] a=new int[5];
public Reminder()
{
a[0]=1000;
a[1]=900;
a[2]=300;
a[3]=1500;
a[4]=1700;
ActionListener actionListener = new ActionListener()
{
public void actionPerformed(ActionEvent actionEvent)
{
point =arr[i].length();
temp=point+1;
time1=System.currentTimeMillis();
new Thread(new t1()).start();
}
};
timer = new Timer(a[i], actionListener);
timer.setInitialDelay(0);
timer.start();
}
public class t1 implements Runnable
{ /* true idea to use current time is beacuse i want to check and make
sure that the time taken since the timer started, and the present time should
not exceed the time given in the array in any case*/
public void run()
{
try
{
time2=System.currentTimeMillis();
while(time2-time1<=a[i]-200){Thread.sleep((long) (a[i] / (arr[i].length() * 4)));
if(hil<=temp-1)
{
doc.setCharacterAttributes(point2,hil, textpane.getStyle("Red"), true);}
hil++;
time2=System.currentTimeMillis();
}
doc.setCharacterAttributes(point2,point+1, textpane.getStyle("Red"), true);
point2+=point;hil=0;i++;
timer.setDelay(a[i]);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
public static void newcompo()
{
JPanel panel = new JPanel();
doc = (StyledDocument) new DefaultStyledDocument();
textpane = new JTextPane(doc);
textpane.setText("Test hiiii what happpn");
javax.swing.text.Style style = textpane.addStyle("Red", null);
StyleConstants.setForeground(style, Color.RED);
panel.add(textpane);
frame.add(panel);
frame.pack();
}
public static void main(String args[]) throws InterruptedException
, InvocationTargetException
{
SwingUtilities.invokeAndWait(new Runnable()
{
@Override
public void run()
{
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
newcompo();
Reminder aa= new Reminder();
}
});
}
}
Any suggestions?How can I simplify?
UPDATE FOR ERROR
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class KaraokeTest {
private int[] timingsArray = {1000, 900, 300, 1500};//word/letters timings
private String[] individualWordsToHighlight = {"Tes", " hiiii", " what", " happpn"};//each individual word/letters to highlight
private int count = 0;
private final JTextPane jtp = new JTextPane();
private final JButton startButton = new JButton("Start");
private final JFrame frame = new JFrame();
public KaraokeTest() {
initComponents();
}
private void initComponents() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
for (String s : individualWordsToHighlight) {
String tmp = jtp.getText();
jtp.setText(tmp + s);
}
jtp.setEditable(false);
startButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
startButton.setEnabled(false);
count = 0;
//create Arrays of individual letters and their timings
final ArrayList<String> chars = new ArrayList<>();
final ArrayList<Integer> charsTiming = new ArrayList<>();
for (String s : individualWordsToHighlight) {
for (int i = 0; i < s.length(); i++) {
chars.add(String.valueOf(s.charAt(i)));
System.out.println(String.valueOf(s.charAt(i)));
}
}
for (int x = 0; x < timingsArray.length; x++) {
for (int i = 0; i < individualWordsToHighlight[x].length(); i++) {
charsTiming.add(timingsArray[x] / individualWordsToHighlight[x].length());
System.out.println(timingsArray[x] / individualWordsToHighlight[x].length());
}
}
new Timer(1, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
if (count < charsTiming.size()) {
highlightNextWord();
//restart timer with new timings
((Timer) ae.getSource()).setInitialDelay(charsTiming.get(count));
((Timer) ae.getSource()).restart();
} else {//we are at the end of the array
reset();
((Timer) ae.getSource()).stop();//stop the timer
}
count++;//increment counter
}
}).start();
}
});
frame.add(jtp, BorderLayout.CENTER);
frame.add(startButton, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
private void reset() {
startButton.setEnabled(true);
jtp.setText("");
for (String s : individualWordsToHighlight) {
String tmp = jtp.getText();
jtp.setText(tmp + s);
}
JOptionPane.showMessageDialog(frame, "Done");
}
private void highlightNextWord() {
//we still have words to highlight
int sp = 0;
for (int i = 0; i < count + 1; i++) {//get count for number of letters in words (we add 1 because counter is only incrementd after this method is called)
sp += 1;
}
//highlight words
Style style = jtp.addStyle("RED", null);
StyleConstants.setForeground(style, Color.RED);
((StyledDocument) jtp.getDocument()).setCharacterAttributes(0, sp, style, true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new KaraokeTest();
}
});
}
}
Gives me Exception:
Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: Uncompilable source code - illegal start of type
at KaraokeTest$1.actionPerformed(KaraokeTest.java:47)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6263)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6028)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4630)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
at java.awt.Container.dispatchEventImpl(Container.java:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2475)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
OK, here is a cleaned up version of your code which should approximatively perform the same thing:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Reminder {
private static final String TEXT = "Test hiiii what happpn";
private static final String[] WORDS = TEXT.split(" ");
private JFrame frame;
private Timer timer;
private StyledDocument doc;
private JTextPane textpane;
private List<Integer> times = Arrays.asList(1000, 900, 300, 1500);
private int stringIndex = 0;
private int index = 0;
public void startColoring() {
ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
doc.setCharacterAttributes(stringIndex, 1, textpane.getStyle("Red"), true);
stringIndex++;
try {
if (stringIndex >= doc.getLength() || doc.getText(stringIndex, 1).equals(" ")) {
index++;
}
if (index < times.size()) {
double delay = times.get(index).doubleValue();
timer.setDelay((int) (delay / WORDS[index].length()));
} else {
timer.stop();
System.err.println("Timer stopped");
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
};
timer = new Timer(times.get(index), actionListener);
timer.setInitialDelay(0);
timer.start();
}
public void initUI() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
doc = new DefaultStyledDocument();
textpane = new JTextPane(doc);
textpane.setText(TEXT);
javax.swing.text.Style style = textpane.addStyle("Red", null);
StyleConstants.setForeground(style, Color.RED);
panel.add(textpane);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) throws InterruptedException, InvocationTargetException {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
Reminder reminder = new Reminder();
reminder.initUI();
reminder.startColoring();
}
});
}
}
A few tricks to help others read and understand your code:
int i, j, k;
)if(something) doSomething(); else {doSomethingElse1(); doSomethingElse2();}
on a single line)static
keyword (to the exception of constants)Your main cause for concern is that you not doing the updates related to JTextPane
on the Event Dispatch Thread
.
For a situation like this, when you really wanted to update a certain thingy from another Thread, always use EventQueue.invokeLater(...) or EvenQueue.invokeAndWait(), which can asynchronously (former)/synchronously (latter)
update your request on the EDT, though care must be taken, as invokeAndWait()
might can lead to deadlocks/run conditions
if not used in the right sense.
Here is your updated code, that might work for your expectations. Hope you can modify the code, as per your liking.
import javax.swing.*;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import java.awt.*;
import java.lang.reflect.InvocationTargetException;
/**
* Created with IntelliJ IDEA.
* User: Gagandeep Bali
* Date: 1/12/13
* Time: 5:55 PM
* To change this template use File | Settings | File Templates.
*/
public class ColouringText
{
private StyledDocument document;
private JTextPane textPane;
private String message;
private String[] parts;
private Timer timer;
private int counter;
private int start, end;
private Thread thread = new Thread()
{
@Override
public void run()
{
while (counter < parts.length)
{
final int len = parts[counter++].length();
try
{
EventQueue.invokeAndWait(new Runnable()
{
@Override
public void run()
{
document.setCharacterAttributes(
start, len, textPane.getStyle("RED"), true);
}
});
Thread.sleep(len * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch (InvocationTargetException e)
{
e.printStackTrace();
}
start += (len + 1);
}
}
};
public ColouringText()
{
document = (StyledDocument) new DefaultStyledDocument();
message = "Hello there... Joey Rohan. Had you ever thought about putting indentations before pasting your code.";
parts = message.split(" ");
counter = 0;
start = 0;
end = 6;
System.out.println("Message Length : " + message.length());
}
private void displayGUI()
{
JFrame frame = new JFrame("Colouring Text Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
textPane = new JTextPane(document);
textPane.setText(message);
Style style = textPane.addStyle("RED", null);
StyleConstants.setForeground(style, Color.RED);
contentPane.add(textPane);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
thread.start();
}
public static void main(String... args)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
new ColouringText().displayGUI();
}
});
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With