JTextArea and its cut/copy/paste Actions
Greetings,
one of my customers wants a text editor implemented in one of my
applications. I couldn't convince him that many many text editors exist
already and that he doesn't need a new one. To no avail (sigh). He doesn't
want a separate process to handle the job so now I'm implementing a
brand new text editor (sigh again). I've decided to give him more than
he wanted for (I'm being payed by the hour for this ;-)
There's loading/saving, there's regular expression search and a whole
lot of other hulla baloo already. I stumbled upon a little inconvenience
though: through its key bindings a JTextArea implements the cut/copy/paste
features.
I want to activate those features/Actions through toolbar buttons too.
Here's my question: I got lost in the documentation. What I've found now
is this:JTextArea ta=new JTextArea();
Action[] actions= ta.getUI().getEditorKit(ta).getActions();
This can't be true: I don't believe that I have to carouse this array and
look for a nested DefaultEditorToolkit.CopyAction object ... I must be
missing something here. Any ideas anyone?
Thanks in advance for putting me on track w.r.t. that documention again.
kind regards,
Jos
[1338 byte] By [
JosAHa] at [2007-10-3 9:55:45]

> I don't believe that I have to carouse this array and look for a nested DefaultEditorToolkit.CopyAction object
1) Use the InputMap and ActionMap to get the Action directly
KeyStroke controlC = KeyStroke.getKeyStroke("control C");
Action copy = textArea.getActionMap().get(textArea.getInputMap().get(controlC));
2) Create a new Action:
Action copy = new DefaultEditorKit.CopyAction();
> > I don't believe that I have to carouse this array and look for a nested
> > DefaultEditorToolkit.CopyAction object
>
> 1) Use the InputMap and ActionMap to get the Action directly> KeyStroke controlC = KeyStroke.getKeyStroke("control C");
> Action copy = textArea.getActionMap().get(textArea.getInputMap().get(controlC));
> 2) Create a new Action:> Action copy = new DefaultEditorKit.CopyAction();
While I do understand option 1), what about option 2) then? How does
the action know about which JTextArea needs its contents to be copied?
That's one part of the docs that left me puzzled, so you hit my problem
right on its head.
On top of that: thanks a bunch; much appreciated. You answer about
every question here don't you? ;-)
kind regards,
Jos (< Swing nono)
> While I do understand option 1
Not sure, but I think that all text components share the same Action. See below why this would be possible.
> what about option 2) then? How does the action know about which JTextArea needs its contents to be copied?
The editor kit actions extend TextAction which has a method getFocusedComponent() which tracks the last JTextComponent that has (had) focus, so it even works when you click on an Action that has been added to a toolbar or menu item.
> You answer about every question here don't you? ;-)
I've learned alot from all the other members of the forum.
> How does
> the action know about which JTextArea needs its
> contents to be copied?
>
If I still remember correctly, the action acts on any text component that currently has focus.
The only disadventage of #2 is that if you need to disable/enable the action, you'll have to make sure to call setEnabled() on both instances.
> The only disadventage of #2 is that if you need to disable/enable the > action, you'll have to make sure to call setEnabled() on both instances. Good point. Learned something again.
> > what about option 2) then? How does the action know
> about which JTextArea needs its contents to be copied?
>
> The editor kit actions extend TextAction which has a method
> getFocusedComponent() which tracks the last JTextComponent
> that has (had) focus, so it even works when you click on an Action
> that has been added to a toolbar or menu item.
If that is true (and I believe you) that implies that I don't understand
focus traversal either. Suppose two nonmodal dialogs, both with a
text component in it and both with a 'copy' button that both have that
same Action object. Suppose I click the left text component (so it has
the focus now) and then click the right 'copy' button in the other dialog.
I really am a Swing nono ...
kind regards,
Jos
> Suppose I click the left text component (so it has
> the focus now) and then click the right 'copy' button
> in the other dialog.
Then the action will be performed on the left component; the system isn't foolproof. Of greater concern, I think, is what happens when you have a textfield in the same window as the textarea--for instance, if you decide to put a "quick search" field in the toolbar. Then you would have to actively manage the focus, and maybe have problems anyway. But as long as you don't get too fancy--and make sure all your dialogs are modal--you shouldn't have any problems.
Hi
I got simple problem. I want to select Image through JFileChooser and pick that path of image and put the image to panel. I wrote this code for same I am geting path in all the methods, But not image could you plz help me
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class MainClass extends JPanel implements ActionListener{
public JMenuBar manuBar=new JMenuBar();
public JMenu menu=new JMenu("File");
public JMenuItem menuItem=new JMenuItem("New");
public JFrame frame = new JFrame();
public static File selPath;
public JFileChooser ch=new JFileChooser();
public Graphics g;
public void paint(Graphics g,File selPath) {
System.out.println("In Graphics := "+selPath);
g.drawImage(createImage(selPath), 40,40,this);
}
public void launchFrame(){
frame.setJMenuBar(manuBar);
manuBar.add(menu);
menu.add(menuItem);
frame.getContentPane().add(new MainClass());
menuItem.addActionListener(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(350,200);
frame.setSize(300, 300);
frame.setVisible(true);
}
public static void main(String[] args) {
MainClass gui=new MainClass();
gui.launchFrame();
}
private Image createImage(File selPath){
BufferedImage bufferedImage = new BufferedImage(200,200,BufferedImage.TYPE_INT_RGB);
Graphics g = bufferedImage.getGraphics();
try {
System.out.println("In Try Catch :="+selPath);
bufferedImage=ImageIO.read(new FileInputStream(selPath));
//bufferedImage=ImageIO.read(new FileInputStream("C:/Documents and Settings/Santosh/My Documents/My Pictures/house.gif"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
g.drawString("My Program", 40,40);
return bufferedImage;
}
public File addFileChooser(){
ch=new JFileChooser();
int status = ch.showSaveDialog(null);
if (status == JFileChooser.APPROVE_OPTION) {
File selectedFile =ch.getSelectedFile();
selPath=ch.getSelectedFile();
selPath.getParent();
System.out.println("My path:-"+selPath);
System.out.println("Selected:-"
+ selectedFile.getParent()
+ " "
+ selectedFile.getName());
}
ch.setSize(200,200);
ch.setVisible(true);
System.out.println("Path At end:-"+selPath);
//imageBackGround(selPath.getAbsolutePath());
createImage(selPath);
return selPath;
}
public void actionPerformed(ActionEvent arg0) {
String command=arg0.getActionCommand();
if( command.equals("New") ){
System.out.println("In Side Action Listener");
addFileChooser();
frame.setVisible(true);
}
}
}
With Regards
Santosh Pathak
@san4java: please start your own thread for your question; don't clutterup this thread.kind regards,Jos
> > Suppose I click the left text component (so it has
> > the focus now) and then click the right 'copy' button
> > in the other dialog.
>
> Then the action will be performed on the left component; the system
> isn't foolproof. Of greater concern, I think, is what happens when you
> have a textfield in the same window as the textarea--for instance, if
> you decide to put a "quick search" field in the toolbar. Then you would
> have to actively manage the focus, and maybe have problems anyway.
> But as long as you don't get too fancy--and make sure all your
> dialogs are modal--you shouldn't have any problems.
So if an appliation uses multiple frames or non-modal dialogs with at
least two of them having text components in them things may go berzerk.
I think I'll use an Action wrapper that requests the focus for the text
component before delegating the stuff to the wrapped Action ...
IMHO this single Action object is a strange design in this particular scenario.
Thanks for your reply, much appreciated and,
kind regards,
Jos
> Suppose I click the left text component (so it has the focus now) and then click the right 'copy' button in the other dialog.
Easiest way to test is to write a simple demo.
import java.awt.*;
import javax.swing.*;
//import javax.swing.event.*;
import javax.swing.text.*;
public class TextAreaCopy extends JFrame
{
public TextAreaCopy()
{
createDialog(0);
createDialog(500);
}
private void createDialog(int x)
{
JDialog dialog = new JDialog();
dialog.setModal( false );
dialog.setLocation(x, 0);
JToolBar toolBar = new JToolBar();
dialog.getContentPane().add(toolBar, BorderLayout.NORTH);
JTextArea textArea1 = new JTextArea(5, 40);
JScrollPane scrollPane1 = new JScrollPane( textArea1 );
dialog.getContentPane().add(scrollPane1, BorderLayout.CENTER);
JTextArea textArea2 = new JTextArea(5, 40);
JScrollPane scrollPane2 = new JScrollPane( textArea2 );
dialog.getContentPane().add(scrollPane2, BorderLayout.SOUTH);
KeyStroke controlC = KeyStroke.getKeyStroke("control C");
Action copy1 = textArea1.getActionMap().get(textArea1.getInputMap().get(controlC));
toolBar.add( new JButton(copy1) );
dialog.pack();
dialog.setVisible( true );
}
public static void main(String[] args)
{
TextAreaCopy frame = new TextAreaCopy();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}
1) Select some text in a left text area
2) Select some text in a right text area
3) Click on the left copy button
4) Paste the text in any text area
The last text field to have focus was the "right" text field, but since you clicked on the "Left" copy button from the left dialog, the text was copied from the last text component in that dialog. So it appears the action is smart enough to remember focus by dialog.
Camickr, thank you very much for your reply and your efforts. Have a look
at your demo, augmented by me a bit; press the 'paste' button and see
the (not so funny) behaviour:import java.awt.*;
import javax.swing.*;
//import javax.swing.event.*;
import javax.swing.text.*;
public class TextAreaCopy extends JFrame
{
public TextAreaCopy()
{
createDialog(0);
createDialog(500);
}
private void createDialog(int x)
{
JDialog dialog = new JDialog();
dialog.setModal( false );
dialog.setLocation(x, 0);
JToolBar toolBar = new JToolBar();
dialog.getContentPane().add(toolBar, BorderLayout.NORTH);
JTextArea textArea1 = new JTextArea(5, 40);
JScrollPane scrollPane1 = new JScrollPane( textArea1 );
dialog.getContentPane().add(scrollPane1, BorderLayout.CENTER);
JTextArea textArea2 = new JTextArea(5, 40);
JScrollPane scrollPane2 = new JScrollPane( textArea2 );
dialog.getContentPane().add(scrollPane2, BorderLayout.SOUTH);
KeyStroke controlC = KeyStroke.getKeyStroke("control C");
Action copy1 = textArea1.getActionMap().get(textArea1.getInputMap().get(controlC));
toolBar.add( new JButton(copy1) );
KeyStroke controlP = KeyStroke.getKeyStroke("control V");
Action paste1 = textArea1.getActionMap().get(textArea1.getInputMap().get(controlP));
toolBar.add( new JButton(paste1) );
dialog.pack();
dialog.setVisible( true );
}
public static void main(String[] args)
{
TextAreaCopy frame = new TextAreaCopy();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}
kind regards,
Jos
To be honest, I can't really explain the behaviour. I just took a quick look at the JTextComponent class. It looks like a FocusListener is added to each text component. The focusGained method updates a static variable, focusedComponent. The getFocusedComponent() method simply returns the focusedComponent variable. So if we only have a single static variable both buttons should update the same text component.
Following is the code for the paste Action:
public void actionPerformed(ActionEvent e) {
JTextComponent target = getTextComponent(e);
if (target != null) {
target.paste();
}
}
The code could be modified to get the parent window of the source button and the parent window of the text component. If they are not the same, then don't do the paste. Thats all I can think of.
> The code could be modified to get the parent window of the source
> button and the parent window of the text component. If they are not the
> same, then don't do the paste. Thats all I can think of.
I don't think that would be wanted behaviour, e.g. sometimes one wants
to copy something from one JTextArea and paste it to another one. Now
a 'paste' button that visually 'belongs' to the other area pastes the text to
the original JTextArea if that was the last text component that had the focus.
(also see your example augmented by me)
thanks for thinking with me and
kind regards,
Jos
just a thought, would this do what you want
//KeyStroke controlP = KeyStroke.getKeyStroke("control V");
//Action paste1 = textArea1.getActionMap().get(textArea1.getInputMap().get(controlP));
//toolBar.add( new JButton(paste1) );
Action paste2 = new AbstractAction(){
public void actionPerformed(ActionEvent ae){
textArea2.paste();
}
};
JButton btn = new JButton(paste2);
btn.setText("paste-from-clipboard");
toolBar.add( btn );
> just a thought, would this do what you want
[ code snipped ... ]
It does exactly what I want; thanks a bunch. It's so obvious; I can't
believe I overlooked those obvious cut(), copy(), paste() methods ...
I told you I got lost in the documentation in my OP ;-)
Thanks again, your solution is just simple and elegant; much better
than mine.
kind regards,
Jos
JosAHa at 2007-7-21 13:02:18 >
