Java scrollToReference causes exception in JEditorPane - java

I have a JEditorPane with a custom html document (not from URL) inside a JScrollPane, and a JTextField so that the user can enter text that will then be highlighted in the editor pane. In the textfield's keyPressed event, I search the document for the text, surround it with:
<a name='spot'><span style='background-color: silver'>my text</span></a>
to highlight the background, then set the new text to the JEditorPane. This all works fine, but I also want to scroll the pane to the newly highlighted text. So in the changedUpdate method of the editor pane's documentListener, I add:
pane.scrollToReference("spot");
This call throws an ArrayIndexOutOfBoundsException inside BoxView.modelToView. The method finds my "spot" reference in the text, but I'm thinking that perhaps the view hasn't been updated with the new text yet, so when it tries to scroll there, it fails.
I can't get a reference to the view, and I can't seem to find an event to listen for that signifies that the JEditorPane's view is completely updated. Any ideas?
Thanks,
Jared

JScrollPane#scrollToReference(java.lang.String reference) talking about String referennce to URL,
Scrolls the view to the given reference location (that is, the value
returned by the UL.getRef method for the URL being displayed).
then all examples around showing the following workaround
import java.io.IOException;
import java.net.URL;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
public class MyScrollToReference extends JDialog {
private static final long serialVersionUID = 1L;
public MyScrollToReference(JFrame frame, String title, boolean modal, String urlString) {
super(frame, title, modal);
try {
final URL url = MyScrollToReference.class.getResource(urlString);
final JEditorPane htmlPane = new JEditorPane(url);
htmlPane.setEditable(false);
JScrollPane scrollPane = new JScrollPane(htmlPane);
getContentPane().add(scrollPane);
htmlPane.addHyperlinkListener(new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
if (e.getURL().sameFile(url)) {
try {
htmlPane.scrollToReference(e.getURL().getRef());
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
});
} catch (IOException e) {
}
}
}

Related

how to display string as URI in java

I am a beginner in Java, I am trying to build a chatbot. The query and responses are hard coded in 2D string array chatbot[][].
This is the complete code that I have used, Two objects for JTextArea 'input and dialogue ' has been used. Object input has been attached to JPanel and is used to get the text from the user and then this is searched in the 2D string array.If it is found then the response is thrown from the same array.
Now my requirement is when the response is any URL it should be displayed as a link so that user can directly click and go to the site(http://google.com for the current scenario).Kindly suggest how this can be achieved or any modification in code is required. addText is the method that is defined to add entire conversation to dialogue text area which is non editable.
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.lang.Math;
import java.awt.Color;
import java.awt.Toolkit;
public class test implements KeyListener{
JFrame j=new JFrame("Temenos ChatBot");
JPanel p=new JPanel();
JTextArea dialog=new JTextArea(20,50); //it will contain the whole conversation(non editable)
JTextArea input=new JTextArea(1,50); //where we user input our query(editable)
JScrollPane scroll=new JScrollPane(
dialog,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
);
String[][] chatbot={
{"hi","hello","hola","ola","howdy"}, //check for query
{"hi","hello","hey"}, //provides output of the query
{"google","provide link for google","www.google.com"}, //Query
{"http://google.com"}, //response
//default
{"we can't find your query",
"(Sorry, we could not understand)"}
};
public static void main(String[]args){
new test();
}
private void icon(){
j.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("dy1MzZ-W.png")));//change the icon, paste the icon in default package
}
public test(){
j.setSize(600,400);
j.setResizable(false);
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
dialog.setEditable(false);
input.addKeyListener(this);
p.add(scroll);
p.add(input);
p.setBackground(new Color(0,150,255));
j.add(p);
j.setVisible(true);
icon();
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode()==KeyEvent.VK_ENTER){
input.setEditable(false);
//-----grab quote-----------
String quote=input.getText(); //takes whatever text user is inputting
input.setText("");
addText("->You:\t"+quote);
quote.trim();
while(
quote.charAt(quote.length()-1)=='!' ||
quote.charAt(quote.length()-1)=='.' ||
quote.charAt(quote.length()-1)=='?'
){
quote=quote.substring(0,quote.length()-1);
}
quote.trim();
byte response=0; //byte is data type that will check for response
/*
0:we're searching through chatBot[][] for matches
1:we didn't find anything
2:we did find something
*/
//-----check for matches----
int j=0;//which group we're checking
while(response==0){
if(inArray(quote.toLowerCase(),chatbot[j*2])){
response=2;
int r=(int)Math.floor(Math.random()*chatbot[(j*2)+1].length);
addText("\n->A.I.sha:\t"+chatbot[(j*2)+1][r]);
}
j++;
if(j*2==chatbot.length-1 && response==0){
response=1;
} //if it has come to end then set response to 1
}
//-----default--------------
if(response==1){
int r=(int)Math.floor(Math.random()*chatbot[chatbot.length-1].length);
addText("\n->A.I.sha:\t"+chatbot[chatbot.length-1][r]);
}
addText("\n");
}
}
public void keyReleased(KeyEvent e){
if(e.getKeyCode()==KeyEvent.VK_ENTER){
input.setEditable(true);
}
}
public void keyTyped(KeyEvent e){}
public void addText(String str){
dialog.setText(dialog.getText()+str);
}//it will add whatever text dialogue box is having
public boolean inArray(String in,String[] str){
boolean match=false;
for(int i=0;i<str.length;i++){
if(str[i].equals(in)){
match=true;
} //Searches for string 'in' in string array,if it finds return true
}
return match;
}
}
If you're making a GUI in swing, you could follow another stack overflow answer, such as this one
How to add hyperlink in JLabel
Or, you could just have java open the browser to that webpage:
// Create Desktop object
Desktop d=Desktop.getDesktop();
// Browse a URL, say google.com
d.browse(new URI("http://google.com"));
You can use the parse static method from Uri
Uri myUri = Uri.parse("http://google.com")

Clickable thumbnail image in a tooltip

I would like to have a special sort of tooltip appear when a user hovers the mouse cursor over a specific item in a treetable. This tooltip will be a thumbnail of a PDF that corresponds to the item in the treetable that the cursor is pointing at. In addition, I'd like the user to be able to then move the cursor over the thumbnail and click it, which should open up the full PDF in their system's default PDF reader (Acrobat, Adobe Reader, etc.).
I realize this is a tall order, but I've already done most of the work. I've discovered exactly where in my huge program that I need to have the setToolTip() method so that it can retrieve the appropriate thumbnail. In addition, since I've discovered that having Java create thumbnails from a PDF on the fly is far too difficult, I've already got things set up so there will be thumbnail JPGs pre-made. Thus, all the setToolTip() command will need to do is somehow retrieve the appropriate JPG. Now comes the hard part.
At first, it seemed easy. I tried this really convenient hack for putting an image in a tooltip, and it definitely gets the thumbnail showing up properly. However, surrounding the <img> tag with an anchor tag (...) doesn't quite seem to work. The thumbnail is surrounded by the tell-tale blue border, alright, but the image remains un-clickable. In addition, the tooltip sometimes just disappears before it's image can be clicked upon.
So I thought I might need to do something more deep than a simple html hack. I tried this more involved way of putting an image in a tooltip, but it seems that will only work for a static image. I need the image to be different depending on what's being hovered over with the mouse cursor. In addition, how do I set my method to use this 'custom version of a tooltip' rather than the built-in one?
To give a bit more context, the location where the setToolTip() method seems to work is inside of a getTreeCellRendererComponent() method, a part of a custom class that extends JPanel and implements TreeCellRenderer. I'll post the code if asked, but it will might be rather complicated and hard to follow. Any thoughts?
EDIT 10/09/2014, 4:57pm: Much of this code may be confusing, and for that, I apologize. Suffice it to say that it has to do with putting a tri-state checkbox inside of a JXTreeTable. Anyway, the parts that are important should be easy enough to pick out, I hope. As you can see, this class already extends JPanel, so I cannot have it extend JToolTip as well.
package info.chrismcgee.sky.treetable;
import info.chrismcgee.beans.OrderDetail;
import info.chrismcgee.components.ImageToolTip;
import info.chrismcgee.components.TristateCheckBox;
import info.chrismcgee.components.TristateState;
import info.chrismcgee.enums.OSType;
import java.awt.BorderLayout;
import java.io.File;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JToolTip;
import javax.swing.JTree;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;
public class SkyCheckTreeCellRenderer extends JPanel implements
TreeCellRenderer {
/**
*
*/
private static final long serialVersionUID = -2728513730497144120L;
private SkyCheckTreeSelectionModel selectionModel;
private TreeCellRenderer delegate;
private boolean showRootNodeCheckBox;
private TristateCheckBox checkBox = new TristateCheckBox("");
protected SkyCheckTreeManager.CheckBoxCustomizer checkBoxCustomer;
private String jobsFolderStr = OSType.getOSType() == OSType.MAC
? "/Volumes/ArtDept/ArtDept/JOBS"
: "//SKYFS/ArtDept/ArtDept/JOBS";
public SkyCheckTreeCellRenderer(TreeCellRenderer delegate,
SkyCheckTreeSelectionModel selectionModel,
boolean showRootNodeCheckBox) {
this.delegate = delegate;
this.selectionModel = selectionModel;
this.showRootNodeCheckBox = showRootNodeCheckBox;
setLayout(new BorderLayout());
setOpaque(false);
checkBox.setOpaque(false);
}
public JToolTip createToolTip() {
return new ImageToolTip();
}
private String getToolTipText(DefaultMutableTreeTableNode node)
{
if (node.getUserObject() instanceof OrderDetail)
{
OrderDetail od = (OrderDetail) node.getUserObject();
String thousandsFolderStr = jobsFolderStr + "/"
+ od.getOrderId().substring(0, 3) + "000-"
+ od.getOrderId().substring(0, 3) + "999/";
String productFolderStr = thousandsFolderStr + od.getOrderId()
+ " Folder/";
if (!od.getProductDetail().equals(""))
productFolderStr = thousandsFolderStr + od.getOrderId() + "/";
String img = productFolderStr + od.getOrderId() + "_THUMB.jpg";
if (!od.getProductDetail().equals(""))
img = productFolderStr + od.getOrderId() + "_" + od.getProductDetail() + "_THUMB.jpg";
if (new File(img).exists())
return "<html><img src=\"file://" + img + "\"></html>";
}
return null;
}
public JComponent getTreeCellRendererComponent(JTree tree, Object value,
boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus)
{
JComponent renderer = (JComponent) delegate.getTreeCellRendererComponent(tree, value,
selected, expanded, leaf, row, hasFocus);
if (!showRootNodeCheckBox && tree.getModel().getRoot() == value)
{
renderer.setToolTipText(getToolTipText((DefaultMutableTreeTableNode)value));
return renderer;
}
TreePath path = tree.getPathForRow(row);
if (path != null) {
if (checkBoxCustomer != null && !checkBoxCustomer.showCheckBox(path))
{
renderer.setToolTipText(getToolTipText((DefaultMutableTreeTableNode)value));
return renderer;
}
if (selectionModel.isPathSelected(path, selectionModel.isDigged()))
checkBox.getTristateModel().setState(TristateState.SELECTED);
else
checkBox.getTristateModel().setState(selectionModel.isDigged()
&& selectionModel.isPartiallySelected(path)
? TristateState.INDETERMINATE
: TristateState.DESELECTED);
}
removeAll();
add(checkBox, BorderLayout.WEST);
add(renderer, BorderLayout.CENTER);
setToolTipText(getToolTipText((DefaultMutableTreeTableNode)value));
return this;
}
}
I get that I need to somehow extend JToolTip, and that this SkyCheckTreeCellRenderer class needs to somehow reference that custom tooltip. I guess all of this is just getting so involved and complex that my simple brain is having trouble wrapping around it all. My apologies.
how do I set my method to use this 'custom version of a tooltip' rather than the built-in one?
As the example shows you need to extend the component to use the custom tool tip.
I need the image to be different depending on what's being hovered over with the mouse cursor
Then you will need to override the getToolTipText(MouseEvent) method to return a text string to represent the image you want to display.
However, surrounding the tag with an anchor tag (...) doesn't quite seem to work
You would need to use a JEditorPane if you want to respond to a hyperlink. Read the JEditorPane API for an example.
So basically I would suggest that you need to use a custom JToolTip, that uses a JEditorPane to display the appropriate Image with an appropriate Hyperlink. Here is an example that shows how to use a JLabel as an added component to a tool tip. You should be able to modify the code to use a JEditorPane.
Also, you need to extend your tree table to use this custom JToolTip.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ToolTipImage extends JToolTip
{
private Image image;
public ToolTipImage(Image image)
{
this.image = image;
setLayout( new BorderLayout() );
add( new JLabel( new ImageIcon( image) ) );
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(image.getWidth(this), image.getHeight(this));
}
private static void createAndShowGUI() throws Exception
{
final BufferedImage testImage = ImageIO.read(new File("dukewavered.gif"));
String[] columnNames = {"Column 0", "Column 1"};
Object[][] data =
{
{"Cell 0,0", "Cell 0,1"},
{"Cell 1,0", "Cell 1,1"}
};
JTable table = new JTable(data, columnNames)
{
public JToolTip createToolTip()
{
return new ToolTipImage( testImage );
}
};
// Set tool tip text so that table is registered w/ tool tip manager
table.setToolTipText(" ");
JFrame frame = new JFrame("Tool Tip Image");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new JScrollPane(table) );
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
createAndShowGUI();
}
catch(Exception e) { System.out.println(e); }
}
});
}
}
It sounds like you need to build a custom tooltip, as detailed in JToolTip.
When clicked, you should use Runtime to open your file from the commandline. The way to do this in windows is posted here. The way to do this on ubuntu is posted here

How to provide Functionalty for Changing the Background Color of Text Parts in HTML Editor built with HTMLEditorKit

My problem is as follows:
I want to enable the user of my little HTML editor to switch between
different background colors for the text being entered. I first tried
to use CSS styles for that purpose. The different styles define
different background colors and through a JComboBox the user could
switch between these styles. Upon selection of a style in the
respective position inside the HTMLDocument a new HTML element of type
<span class="style"> would be entered.
Unfortunately I could not manage to get this work. The span elements
were simply not created (see my question regarding this problem).
In between I took a look at the class StyledEditorKit.ForegroundAction
to learn how this functions. Upon execution it simply modifies the
input attributes of the StyledEditorKit in use setting a new
foreground color. Text that is entered afterwards is displayed with
the new foreground color. And when writing the HTML code into a file,
the text is automagically enclosed in <font color=".."> ... </font>
HTML elements. And all that even works on selected text which might
run over multiple paragraphs. In this case obviously the affected
text inside all affected paragraphs is enclosed into <font ...> HTML tags.
I want to accomplish the same functionality for setting the background
color on arbitrary chunks of text. But surprisingly this does not seem
to be so easy:-(
I didn't find a predefined action class for that purpose similar to the
StyledEditorKit.foregroundAction in the Java 7 JDK. Creating
such a class does not seem to be complex; it's almost the same as the
ForegroundAction with the actionPerformed method changed to set the
background instead of the foreground attribute.
But how to create valid HTML code that sets a specific background
color for parts of the contained text?
Until now I don't know which part of the HTMLEditorKit performs the
creation of all the <font> elements for text in the HTMLDocument that
has the foreground attribute set. I think from the existing code
creating the <font> elements it should not be too hard to derive an
implementation that creates <span style="background-color:...">
elements instead of <font> elements for setting the background color
for arbitrary regions of text. Or is all this already available and I
only didn't notice? Any help would be appreciated!
In between I made a significant step forward and thanks to a piece of code found here
I managed to create valid <span> elements. In the span elements I use the class attribute to assign a predefined style.
Here's my code:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleContext;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
public class SimpleEditor extends JFrame {
private static final long serialVersionUID = 1L;
private final JTextPane textPane;
private final HTMLEditorKit edtKit;
private final HTMLDocument doc;
private final StyleSheet predefStyles;
public static void main(String[] args) throws BadLocationException, IOException {
final SimpleEditor editor = new SimpleEditor();
editor.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
editor.setVisible(true);
}
public SimpleEditor() throws BadLocationException, IOException {
super("Very Simple HTML Editor");
textPane = new JTextPane();
edtKit = new HTMLEditorKit();
textPane.setEditorKit(edtKit);
predefStyles = new StyleSheet();
predefStyles.addRule(".MyStyle1 { color:#cc0000; background-color:silver }\n" +
".MyStyle2 { color:#0000cc; background-color:aqua }");
doc = new HTMLDocument(predefStyles);
textPane.setDocument(doc);
final Container content = getContentPane();
content.add(textPane, BorderLayout.CENTER);
content.add(createToolBar(), BorderLayout.NORTH);
setJMenuBar(createMenuBar());
setSize(500, 240);
}
private JToolBar createToolBar() {
final Vector<String> styleNames = new Vector<String>();
final Enumeration<?> names = predefStyles.getStyleNames();
while (names.hasMoreElements()) {
styleNames.add((String) names.nextElement());
}
final DefaultComboBoxModel<String> stylesModel =
new DefaultComboBoxModel<String>(styleNames);
final JComboBox<String> cbStyleSel = new JComboBox<String>(stylesModel);
final JToolBar bar = new JToolBar();
Action dumpAction = null;
for (final Action act : edtKit.getActions()) {
if (act.getValue(Action.NAME).equals("dump-model")) {
dumpAction = act;
break;
}
}
bar.add(dumpAction);
cbStyleSel.setEditable(false);
cbStyleSel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
e.getSource();
#SuppressWarnings("unchecked")
final JComboBox<CondStyle> cboStyleSel = (JComboBox<CondStyle>) e.getSource();
final String selItem = (String) cboStyleSel.getSelectedItem();
final MutableAttributeSet divAttributes = new SimpleAttributeSet();
if (selItem.equals("default")) {
// This does not work!
final Style defStyle = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
divAttributes.addAttribute(HTML.Tag.CONTENT, defStyle);
textPane.setCharacterAttributes(divAttributes, true);
} else {
divAttributes.addAttribute(HTML.Attribute.CLASS, selItem.substring(1));
final MutableAttributeSet tagAttributes = new SimpleAttributeSet();
tagAttributes.addAttribute(HTML.Tag.SPAN, divAttributes);
textPane.setCharacterAttributes(tagAttributes, false);
}
textPane.requestFocusInWindow();
}
});
bar.add(cbStyleSel);
return bar;
}
/**
* Extracts the style attributes except the style's name
* #param aStyle The style to be processed
* #return The visual attributes extracted from the style
*/
AttributeSet extractStyleAttribs(Style aStyle) {
final MutableAttributeSet attribs = new SimpleAttributeSet();
final Enumeration<?> attribNames = aStyle.getAttributeNames();
while (attribNames.hasMoreElements()) {
final Object attribName = attribNames.nextElement();
if (attribName == Style.NameAttribute) {
continue;
}
attribs.addAttribute(attribName, aStyle.getAttribute(attribName));
}
return attribs;
}
private JMenuBar createMenuBar() {
final JMenuBar menubar = new JMenuBar();
final JMenu mnuFile = new JMenu("File");
menubar.add(mnuFile);
final SaveAction actSave = new SaveAction();
mnuFile.add(actSave);
return menubar;
}
class SaveAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public SaveAction() {
super("Save");
}
#Override
public void actionPerformed(ActionEvent ev) {
final JFileChooser chooser = new JFileChooser();
if (chooser.showSaveDialog(SimpleEditor.this) != JFileChooser.APPROVE_OPTION)
return;
final File file = chooser.getSelectedFile();
if (file == null)
return;
FileWriter writer = null;
try {
writer = new FileWriter(file);
textPane.write(writer);
} catch (final IOException ex) {
JOptionPane.showMessageDialog(SimpleEditor.this,
"File Not Saved", "ERROR",
JOptionPane.ERROR_MESSAGE);
} finally {
if (writer != null) {
try {
writer.close();
} catch (final IOException x) {
}
}
}
}
}
}
So far so good! My only problem with this solution is that I couldn't manage to implement the switch back from text enclosed in <span> elements to "normal" text, i.e. text that is not placed inside of <span> elements.
This should be no big deal but unfortunately I couldn't figure out how I can accomplish that. Any ideas would be very welcome!
I got it! And it's sooo simple;-)
To switch back from the styled text entry using <span> elements I only had to remove the HTML.Tag.SPAN attribute from the input attributes of the current text. This is accomplished as follows:
edtKit.getInputAttributes().removeAttribute(HTML.Tag.SPAN);
So the code for the ActionListener in the example code I posted in my (updated) question now looks as follows:
cbStyleSel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
e.getSource();
#SuppressWarnings("unchecked")
final JComboBox<CondStyle> cboStyleSel = (JComboBox<CondStyle>) e.getSource();
final String selItem = (String) cboStyleSel.getSelectedItem();
if (selItem.equals("default")) {
edtKit.getInputAttributes().removeAttribute(HTML.Tag.SPAN);
} else {
final MutableAttributeSet divAttributes = new SimpleAttributeSet();
divAttributes.addAttribute(HTML.Attribute.CLASS, selItem.substring(1));
final MutableAttributeSet tagAttributes = new SimpleAttributeSet();
tagAttributes.addAttribute(HTML.Tag.SPAN, divAttributes);
textPane.setCharacterAttributes(tagAttributes, false);
}
textPane.requestFocusInWindow();
}
});
I had posted multiple questions regarding my problems implementing that functionality (see here, and here) but got no answers. Maybe the issue was too trivial;-)

How to change the mouse pointer to finger pointer in swing?

In html when we create a hyperlink and point over it ,then it automatically changes to a finger pointer.
So I was wondering can we achieve the same in java swings.
Suppose I have a label on clicking which a new form pops-up.But I want that when the user points over the label it should change to finger pointer,showing that something will pop-up if its clicked.In this way we can differentiate that label with normal labels on the form i guess :).
But how to do something like this?
You can set cursor of JLabel to Cursor.HAND_CURSOR using below code :
JLabel label = new JLabel("https://stackoverflow.com");
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
go to the properties of the button or the label and scroll down you will find a column of cursor you can change to hand or whatever you want
As said you'd want to call the setCursor() method on the JLabel and set it to Cursor.Hand_CURSOR to further this you can also underline the text to make it an HTML look alike link if you want :):
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URI;
import javax.swing.JLabel;
/**
*
* #author ludovicianul
*/
public class URLLabel extends JLabel {
private String url;
public URLLabel() {
this("","");
}
public URLLabel(String label, String url) {
super(label);
this.url = url;
setForeground(Color.BLUE.darker());
setCursor(
new Cursor(Cursor.HAND_CURSOR));
addMouseListener(
new URLOpenAdapter());
}
public void setURL(String url) {
this.url = url;
}
//this is used to underline the text
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.blue);
Insets insets = getInsets();
int left = insets.left;
if (getIcon() != null) {
left += getIcon().getIconWidth() + getIconTextGap();
}
g.drawLine(left, getHeight() - 1 - insets.bottom, (int) getPreferredSize().getWidth()
- insets.right, getHeight() - 1 - insets.bottom);
}
private class URLOpenAdapter extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
if (Desktop.isDesktopSupported()) {
try {
Desktop.getDesktop().browse(new URI(url));
} catch (Throwable t) {
//
}
}
}
}
}
Reference:
CREATING A URL JLABEL IN SWING
Hossein Mobasher
answer is good and mine answer is very late but i just want to add up you can also use it like this below.
JLabel label = new JLabel("http://stackoverflow.com");
label.setCursor(Cursor.HAND);
It will also work i have tried it in Java 1.8
ButtonName.SetCursor(new Cursor(12));
This one works definitely!

Java: Strange behavior of JEditorPane wrapped inside JScrollPane

I'm trying to build a simple help system to my software.
The help system built from JEditorPane(Loaded with HTML file) wrapped inside of JScrollPane, inside of the same window there is a JLabel.
When the user move the mouse over the JEditorPane on a specific word - more explanations appear in the JLabel.
I succeed doing it, but the problem is, that for some reason it work just on the beginning of the text.(the HTML file is long and must be scrolled...)
After i scroll down the page and hover over a word, it throw me BadLocationException.
On the code below there is a JEditorPane wrapped inside JScrollPane.
When the user move the mouse it print the current letter which the mouse point on.(on the help system i find the value of the word by this position and print explanations to the JLabel according to it)
But, as i said it work just on the beginning of the text.
Why ?
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.Point;
import java.io.IOException;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.text.BadLocationException;
public class JEditorPaneTestApp extends JFrame {
private JEditorPane editorPan;
private JScrollPane scrollPan;
public JEditorPaneTestApp() {
super();
try {
editorPan = new javax.swing.JEditorPane("file:///path/toHTML/file/helpFile.html");
}
catch (IOException e) {e.printStackTrace();}
scrollPan = new JScrollPane(editorPan);
this.add(scrollPan);
editorPan.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseMoved(java.awt.event.MouseEvent evt) {
Point p = new Point(evt.getX(), evt.getY());
int pos = editorPan.viewToModel(p);
try {
System.out.println(editorPan.getText(pos--, pos).charAt(0));
}
catch (BadLocationException e1) {
System.out.println("Invalid location");/* e1.printStackTrace();*/
}
}
});
scrollPan.setViewportView(editorPan);
this.add(scrollPan);
//
this.getContentPane().setLayout(new LayoutManager() {
#Override public Dimension preferredLayoutSize(Container arg0) {return null;}
#Override public Dimension minimumLayoutSize(Container arg0) {return null;}
#Override public void removeLayoutComponent(Component arg0) {}
#Override public void addLayoutComponent(String arg0, Component arg1) {}
#Override public void layoutContainer(Container conter) {
scrollPan.setBounds(0, 0, conter.getWidth(), conter.getHeight());
}
});
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
JEditorPaneTestApp test = new JEditorPaneTestApp();
}
}
Thanks
System.out.println(editorPan.getText(pos--, pos).charAt(0));
should be:
System.out.println(editorPan.getText(pos--, 1).charAt(0));

Categories

Resources