5

I have in my app a chat component which has a JTextArea on it. Now, how can I add an ActionListener-like event for a specific text (like student://xxxx)?

So when I click on that text (student://xxxx) something will happen. Thank you.

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Claudiu C
  • 95
  • 1
  • 1
  • 11

3 Answers3

10

Here try this small program, try to click at the start of student://, that will pop up a message Dialog

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TextAreaExample extends JFrame
{
    private JTextArea tarea =  new JTextArea(10, 10);
    private JTextField tfield = new JTextField(10);

    private void createAndDisplayGUI()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        tarea.setText("Hello there\n");
        tarea.append("Hello student://");
        JScrollPane scroll = new JScrollPane(tarea);

        tfield.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                tarea.append(tfield.getText() + "\n");
            }
        });

        tarea.addMouseListener(new MouseAdapter()
        {
            public void mouseClicked(MouseEvent me)
            {
                int x = me.getX();
                int y = me.getY();
                System.out.println("X : " + x);
                System.out.println("Y : " + y);
                int startOffset = tarea.viewToModel(new Point(x, y));
                System.out.println("Start Offset : " + startOffset);
                String text = tarea.getText();
                int searchLocation = text.indexOf("student://", startOffset);
                System.out.println("Search Location : " + searchLocation);
                if (searchLocation == startOffset)
                    JOptionPane.showMessageDialog(TextAreaExample.this, "BINGO you found me.");
            }
        });

        getContentPane().add(scroll, BorderLayout.CENTER);
        getContentPane().add(tfield, BorderLayout.PAGE_END);
        pack();
        setLocationByPlatform(true);
        setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new TextAreaExample().createAndDisplayGUI();
            }
        });
    }
}
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
2

No, don't even consider this since ActionListeners are for JButtons or anything else derived from AbstractButton but not for JTextComponents (except for JTextFields). Perhaps you want a MouseListener.

Having said this, perhaps you'll be better off with two text components, a JTextArea to display all responses, including the user's, and right below this in a BorderLayout.SOUTH type of position, a JTextField to allow the user to enter text into the chat. Then give that JTextField an ActionListener (this is legal) so that "enter" will actuate the listener.

Edit 1
You state:

Well I have that jtextfield , the text in it is being sent to the server and server sends the message to all clients which appears in the JTextArea. But my problem is here: I want to popup a window when someone clicks on a student://id text .

Yeah, looking at your comments, my vote is for you to display the chats not in a JTextArea but rather in a JList, one with a SelectionListener. You can then respond easily to mouse click events, and will more easily get useful information from the "line" clicked on (if you fill the JList with smart objects). You will need to write a custom cell renderer that allows multiple lines of text to be displayed, probably one that shows a JTextArea, but the tutorial on JLists will get you started on this.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Yes you are right mouselistener might work but how can I perform an action with it when I click on a text that looks like student://id ? – Claudiu C May 05 '12 at 14:31
  • @user1266039: why do you want this behavior? What is the overall goal of this? I'm not saying that what you request can't be done, but it would require a bit of work, and the behavior sounds a bit funny as most chat applications that I'm familiar with don't have this functionality. – Hovercraft Full Of Eels May 05 '12 at 14:35
  • 1
    I strongly suspect OP want the chat to be something like a hyperlink :-) – COD3BOY May 05 '12 at 14:39
  • @user1266039: you may in fact want to display the chat in a JList and not a JTextArea. This will make clicking on "lines" and getting information much easier. – Hovercraft Full Of Eels May 05 '12 at 14:39
  • Well I have that jtextfield , the text in it is being sent to the server and server sends the message to all clients which appears in the JTextArea. But my problem is here: I want to popup a window when someone clicks on a student://id text . – Claudiu C May 05 '12 at 14:41
  • http://stackoverflow.com/users/977676/sanjay is right, more like a hyperlink that will popup a new window, based on the id from student://id ; – Claudiu C May 05 '12 at 14:44
  • Can your advice be applied to a line of text like: "hello check this guy student://12223 . Is he from our University? " . – Claudiu C May 05 '12 at 14:48
  • @user1266039 : you can use the [modelToView()...1](http://docs.oracle.com/javase/7/docs/api/javax/swing/text/JTextComponent.html#modelToView(int)) and [viewToModel(...)](http://docs.oracle.com/javase/7/docs/api/javax/swing/text/JTextComponent.html#viewToModel(java.awt.Point)), to do things on the specified Co-ordinates of the `JTextArea` – nIcE cOw May 05 '12 at 14:48
  • @user1266039: yes you can do as Nice Cow suggests, but again, why not use a JList and allow you to encapsulate each chat String as a smart object? Your JList would hold objects, of say the ChatLine class, and these objects would have a method, `getChatter()` that returns the ChatUser who sent the line. Go object-oriented all the way! – Hovercraft Full Of Eels May 05 '12 at 14:51
1

Is hitting ENTER instead of mouse-click ok?

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class StudentID extends JFrame implements ActionListener
{
    private static final String progname = "StudentID 0.1";

    private JTextField student;
    private JTextArea feedback;
    private JButton exit;

    public StudentID ()
    {
        super (progname);
        JPanel mainpanel = new JPanel ();
        mainpanel.setLayout (new BorderLayout ());
        this.getContentPane ().add (mainpanel);

        student = new JTextField ("student://");
        exit = new JButton ("exit");
        student.addActionListener (this);
        exit.addActionListener (this);
        feedback = new JTextArea ();
        mainpanel.add (student, BorderLayout.NORTH);
        mainpanel.add (feedback, BorderLayout.CENTER);
        mainpanel.add (exit, BorderLayout.SOUTH);

        setSize (400, 400);
        setLocation (100, 100);
        setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        setVisible (true);
    }

    public void actionPerformed (final ActionEvent e)
    {
        SwingWorker worker = new SwingWorker () 
        {
            protected String doInBackground () throws InterruptedException 
            {
                String cmd = e.getActionCommand ();
                if (cmd.equals ("exit"))
                {
                    System.exit (0);
                }
                else if (cmd.matches ("student://[0-9]+")) 
                {
                    feedback.setText ("student found: " + cmd.replaceAll ("student://([0-9]+)", "$1"));
                }
                else
                {
                    feedback.setText ("cmd: " + cmd);
                }
                return "done";
            }
            protected void done () 
            {
                feedback.setText (feedback.getText () + "\ndone");
            }
        };
        worker.execute ();
    }

    public static void main (final String args[])
    {
        Runnable runner = new Runnable () 
        {
            public void run () 
            {
                new StudentID ();
            }
        };
        EventQueue.invokeLater (runner);
    }
}
user unknown
  • 35,537
  • 11
  • 75
  • 121