I'm using the code in this answer to provide logging functionality, and it works well! Thanks gustafc.
Sending messages to a swing JTextArea from different places
I want to use this approach and add the function: writeEntry(String, String) to write to an ArrayList that I can hopefully access from swing; i.e, click 'show' and have it write this list of word pairs to a JText element.
so adding a bit to gustafc's code.
the interface:
package com.example.logging;
public interface SimpleActivityLogger {
void logAction(String message);
void writeEntry(String s1); //*** I added this ***
}
passing it to another class as per gustafc's example:
public class SimpleComponentLogger implements SimpleActivityLogger{
private JTextComponent target;
private ArrayList data;
public SimpleComponentLogger(JTextComponent target, ArrayList data){
this.target = target;
this.data = data;
}
public void logAction(final String message){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
target.setText(String.format("%s%s%n", new Object[]{target.getText(), message}));
}
});
}
public void writeEntry(String s1){
data.add(s1);
System.out.println("data array length: " + data.size());
}
}
and then making an implementation:
// this originally extended NotesThread,
// but I assume you won't have that on your system
public class LookupIterator3 extends Thread {
private SimpleActivityLogger logger;
// Constructor that passes logger instance
public LookupIterator3(SimpleActivityLogger logger){
this.logger = logger;
}
public void doLookup(){
this.start();
}
public void run() {
String[] words = {"the", "quick", "smart", "fox", "jumps", "over", "the", "lazy", "dog"};
for(int i=0; i<words.length; i++){
synchronized(words){
try{
logger.logAction(words[i]);
words.wait(500);
}
catch(InterruptedException ie){ie.printStackTrace();}
}
logger.writeEntry(words[i]);
}
}
}
however, when I try to access the ArrayList from swing, it comes back size()=0. Here's a big chunk of swing, but you should be able to just copy and paste it:
public class MySwingTest extends JFrame {
private static final long serialVersionUID = 1L;
private JTextField filename = new JTextField();
private JTextField dir = new JTextField();
private JTextPane output, answersPane;
private JScrollPane scroller;
private SimpleComponentLogger logger;
private ArrayList answer;
public MySwingTest() {
JMenu fileMenu;
JMenuBar menuBar;
JMenuItem menuOpen, menuExit;
JButton answerButton = new JButton("show answers");
answerButton.addActionListener(new MyListener());
menuBar = new JMenuBar();
fileMenu = new JMenu("File");
menuBar.add(fileMenu);
menuOpen = new JMenuItem("open file");
menuExit = new JMenuItem("exit");
answer = new ArrayList();
output = new JTextPane();
logger = new SimpleComponentLogger(output, answer);
scroller = new JScrollPane(output, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
output.setEditable(false);
answer = new ArrayList();
answersPane = new JTextPane();
answersPane.setSize(100, 200);
answersPane.setEditable(false);
fileMenu.add(menuOpen);
fileMenu.add(menuExit);
menuOpen.addActionListener(new MyListener());
menuExit.addActionListener(new MyListener());
JPanel p = new JPanel();
p.setLayout(new GridLayout(2, 1));
p.add(filename);
p.add(dir);
Container cp = getContentPane();
cp.add(menuBar,BorderLayout.NORTH);
cp.add(p);
cp.add(scroller, BorderLayout.CENTER);
cp.add(answersPane, BorderLayout.WEST);
cp.add(answerButton, BorderLayout.SOUTH);
dir.setEditable(false);
filename.setEditable(false);
}
// Inner class listener
class MyListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String eventCommand = e.getActionCommand();
if(eventCommand.equals("exit")){
System.exit(0);
}
if(eventCommand.equals("show answers")){
String entry = (String)answer.get(0);
answersPane.setText(entry);
}
else {
LookupIterator3 lu3 = new LookupIterator3(logger);
lu3.doLookup();
}
}
}
public static void main(String[] args) {
run(new MySwingTest(), 450, 600);
}
public static void run(JFrame frame, int width, int height) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width, height);
frame.setVisible(true);
}
}
Sorry about the long question, but this is doing my head in! Any suggestions? (I know I'm going to get ragged for writing a long qn, but I don't know what I could have left out)
OK. long edit complete. Open that baby up and select "open file" from the menu. It will run without a filechooser.
The problem is actually quite simple: in your MySwingTest
constructor you have twice the line :
answer = new ArrayList();
once before you create your logger and once after. Simply drop the second call and it should work fine.
Note: it is really a bad practice to share ArrayList between your instances (responsability is spread over several classes). It would be a lot simpler if you only had your logger creating directly its own ArrayList and providing access to it with a getter. Even better, it could directly offer an access to the objects it contains (preventing the possibility for other instances to modify the content of the ArrayList).
Note 2: consider using interface-declaration over class-declaration: use List
instead of ArrayList
in order to reduce coupling.
Note 3: I would strongly encourage you tu type your collections: List<String> answer = new ArrayList<String>();