Reputation: 6337
I instantiated a button of my class like so:
linkBtn = new LinkButton(
new URI("http://www.example.com"),
"Click me");
Nothing happens when I click it, so I want to add an action listener something like this:
linkBtn.addActionListener(SOMETHING);
I tried things like this:
linkBtn.addActionListener(new LinkButton.OpenUrlAction());
That gives the following error:
an enclosing instance that contains LinkButton.OpenUrlAction is required
I haven't found the right syntax yet.
Here's my class that extends JButton:
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URI;
import javax.swing.JButton;
public class LinkButton extends JButton
implements ActionListener {
/** The target or href of this link. */
private URI target;
final static private String defaultText = "<HTML>Click the <FONT color=\"#000099\"><U>link</U></FONT>"
+ " to go to the website.</HTML>";
public LinkButton(URI target, String text) {
super(text);
this.target = target;
//this.setText(text);
this.setToolTipText(target.toString());
}
public LinkButton(URI target) {
this( target, target.toString() );
}
public void actionPerformed(ActionEvent e) {
open(target);
}
class OpenUrlAction implements ActionListener {
@Override public void actionPerformed(ActionEvent e) {
open(target);
}
}
private static void open(URI uri) {
if (Desktop.isDesktopSupported()) {
try {
Desktop.getDesktop().browse(uri);
} catch (IOException e) { /* TODO: error handling */ }
} else { /* TODO: error handling */ }
}
}
Upvotes: 0
Views: 2438
Reputation: 347314
I'm open to suggestions. I don't like my program structure either...
The answer's provided so far are all excellent.
Hovercraft has suggest the use of Action
s, which would simply the structure of your code.
For example...
import java.awt.Desktop;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class LinkButtonExample {
public static void main(String[] args) {
new LinkButtonExample();
}
public LinkButtonExample() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(new JButton(new OpenURLAction(new URL("http://stackoverflow.com/"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
});
}
public class OpenURLAction extends AbstractAction {
private URL url;
public OpenURLAction(URL url) {
this("<HTML>Click the <FONT color=\\\"#000099\\\"><U>link</U></FONT> to go to the website.</HTML>", url);
}
public OpenURLAction(String text, URL url) {
putValue(NAME, text);
setURL(url);
}
public void setURL(URL url) {
this.url = url;
setEnabled(
url != null
&& Desktop.isDesktopSupported()
&& Desktop.getDesktop().isSupported(Desktop.Action.BROWSE));
putValue(SHORT_DESCRIPTION, url == null ? null : url.toString());
}
public URL getURL() {
return url;
}
@Override
public void actionPerformed(ActionEvent e) {
if (isEnabled()) {
URL url = getURL();
if (url != null && Desktop.isDesktopSupported()
&& Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
try {
Desktop.getDesktop().browse(url.toURI());
} catch ( IOException | URISyntaxException ex) {
ex.printStackTrace();
}
}
}
}
}
}
Check out How to use Actions for more details
Upvotes: 2
Reputation: 14413
I don't understand why you extends a JButton
but you can add by default this listener in constructor.
public LinkButton(URI target, String text) {
super(text);
this.target = target;
//this.setText(text);
this.setToolTipText(target.toString());
this.addActionListener(this);
//this.addActionListener(new OpenUrlAction());
}
Or you can do this.
linkBtn.addActionListener(linkBtn.new OpenUrlAction());
outerObject.new InnerClass()
Or you can modify your inner class with a constructor injection
class OpenUrlAction implements ActionListener{
private URI target;
OpenUrlAction(URI target){
this.target=target;
}
@Override
public void actionPerformed(ActionEvent evt){
open(this.target);
}
}
In client code:
`linkBtn.addActionListener(linkBtn.new OpenUrlAction(lninkBtn.getTarget)); // or the target that you want`
Upvotes: 2
Reputation: 285405
You could do this:
linkBtn.addActionListener(linkBtn.new OpenUrlAction());
But your program structure makes me wince. Myself I'd try to get Actions separate from views. I also much prefer extension by composition rather than inheritance.
Upvotes: 2
Reputation: 6337
Here what I came up with so far. I added this method to my LinkButton class:
public void init() {
this.addActionListener(this);
}
Then I added this code to add the action listener:
linkBtnDonate.init();
It's working. I'm open to other suggestions.
Upvotes: 0