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!
Related
I am making program which will show zoomed in picture in scrolled frame and allow user to change single pixels of buffered image. I am trying to add panel with buffered image to scrolledPane but scroll bars wont appear.
Here is my panel:
package biometria1;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class noobPanel extends JPanel implements MouseListener{
private BufferedImage background;
int scale = 8;
noobPanel self;
public noobPanel(File file){
self = this;
try {
background = ImageIO.read(file);
} catch (IOException ex) {
Logger.getLogger(noobPanel.class.getName()).log(Level.SEVERE, null, ex);
}
addMouseListener(this);
}
public BufferedImage getImage(){
return this.background;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, 0, 0, background.getWidth()*8, background.getHeight()*8, 0, 0, background.getWidth(), background.getHeight(), this);
}
#Override
public void mouseClicked(MouseEvent e) {
int x = e.getX()/scale;
int y = e.getY()/scale;
System.out.println("before:"+background.getRGB(x, y));
background.setRGB(x, y, 100);
System.out.println("after:"+background.getRGB(x, y));
self.repaint();
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void mouseEntered(MouseEvent e) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void mouseExited(MouseEvent e) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
and thats how i add this panel in frame:
File image = chooser.getSelectedFile();
obraz = new noobPanel(image);
scrollPanel= new JScrollPane(obraz);
// 8 because i scale its 8 times bigger
obraz.setPreferredSize(new Dimension(obraz.getWidth()*8, obraz.getHeight()*8));
self.setSize(860, 640);
self.add(scrollPanel);
self.pack();
self.revalidate();
self.repaint();
Could u tell me what I am doing wrong? Thanks for any advice
You never set the size of your panel (preferred or otherwise). So the new Dimension(width*8, height*8) ist still 0,0.
So you can either do what Andrew Thompson suggested and override getPreferredSize() or just set your preferred size in your panels constructor, probably after loading the image since that's what actually matters?
Oh and why do you define the scale and then not use it? I'm talking about the *8 instead of *scale.
Also: This is a little off topic but why do you keep an extra reference "self" around? Seems like unnecessary overhead... You can call all those methods without the "self." in front of them and even if you couldn't there's already the "this" keyword for that. I mean yeah it's only around 4 bytes or something but it looks odd.
I am trying to create a program that allows the user to drag and draw lines and also delete the lines after it have been drawn. Is there any ways i can do it? I have the code that draws the line but i am not sure how i could delete the lines after i have drawn it. Im looking to click any of the lines drawn and delete it with the delete button.
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Drawing {
public Drawing() {
JFrame jf=new JFrame("Free Hand Drawing Example");
Board draw=new Board();
jf.add(draw);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(600,500);
jf.setVisible(true);
}
public static void main(String a[]){
new Drawing();
}
}
class Board extends JPanel implements MouseListener,MouseMotionListener {
ArrayList<pts> list = new ArrayList<pts>();
Point start,end;
public Board() {
start=null; /*Initializing*/
end=null;
//this.setBackground(Color.BLACK);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
#Override
public void paint(Graphics g)
{ Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
super.paint(g2);
//g.setColor(Color.BLACK);
for (pts p : list)
g.drawLine((int)p.getStart().getX(), (int)p.getStart().getY(), (int)p.getEnd().getX(), (int)p.getEnd().getY());
if(start!=null)
{
g.drawLine(start.x,start.y,end.x,end.y);
}
}
#Override
public void mouseClicked(MouseEvent arg0) {}
#Override
public void mouseEntered(MouseEvent arg0) {}
#Override
public void mouseExited(MouseEvent arg0) {}
#Override
public void mousePressed(MouseEvent me) {
start = me.getPoint();
}
#Override
public void mouseReleased(MouseEvent me) {
end = me.getPoint();
pts pt = new pts(start,end);
list.add(pt);
repaint();
for(pts p : list)
{
System.out.println(p.getStart()+""+p.getEnd());
}
start = null;
end = null;
}
#Override
public void mouseDragged(MouseEvent me) {
end = me.getPoint();
repaint();
}
#Override
public void mouseMoved(MouseEvent arg0) {}
}
class pts{
Point start = null;
Point end = null;
public pts(Point start, Point end){
this.start = start;
this.end = end;
}
public Point getStart(){
return this.start;
}
public Point getEnd(){
return this.end;
}
}
There is more than one way to go about this, but one simple approach would be to add a 'delete' button with an ActionListener that clears out the list of points you have when the button is pressed. You could also associate the clearing action with something like a MouseDragged event, but that doesn't seem very user friendly.
UPDATE:
So, to delete the line when the user clicks on it, you could use a simple function like this one:
public boolean intersects(Point linePoint1,
Point linePoint2,
Point usersClickPoint) {
return new Line2D.Float(linePoint1, linePoint2).
ptLineDist(usersClickPoint) <= 0.01;//some margin of error
}
in your MousePressed method.
Side Note: The way you've chosen to interpret the mouse events is a bit strange. You record the first point on MousePressed, and the second one on MouseReleased. Why not use MouseClicked and simply keep track of the first and second clicks when drawing the line?
One approach would be to create a Line object for each line your user draws and have the object store the locations on the screen where the line is drawn. Then when in delete mode, have an onClickListener that will select a line based upon the coordinates of the click matching up to a point contained in a line. Then just delete the line (probably could redraw using the same endpoints but with the pen set to the background color). There would need to be some logic for the possible case where lines intersect and you don't want to delete a portion of the other line, but that could be solved fairly easily. Keep in mind, I'm not a big graphics programmer. This is just my idea.
Actually, i have already ask this question in here. But, i'm making mistake. I haven't already get the solution.
First, at the question before, i can get Rectangle with
Rectangle rectangle = textArea.modelToView( textArea.getCaretPostion() );
I'm also get X and Y position.
I'm creating a editor that can add new Text Area each i press Enter key. XY position with code above always give same return in every Text Area. Look my code.
import java.awt.Container;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
public class forquestion extends JFrame {
Container textAreaBox;
LinkedList<JTextComponent> textArea;
int nameTA;
public forquestion() {
int nameTA = 0;
textArea = new LinkedList<>();
textAreaBox = Box.createVerticalBox();
textAreaBox.add(Box.createVerticalGlue());
addLine();
this.add(textAreaBox);
this.setVisible(true);
}
public static void main(String[] args) {
forquestion app = new forquestion();
app.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
public void addLine () {
JTextComponent temp_ta = createTextComponent();
textArea.add(temp_ta);
textAreaBox.add(textArea.getLast());
textAreaBox.add(Box.createVerticalGlue());
}
protected JTextComponent createTextComponent() {
JTextArea ta = new JTextArea("test");
/*if (count%2==0)
ta.setForeground(Color.red);
else
ta.setForeground(Color.GREEN);*/
ta.setFont(new Font("Courier New",Font.PLAIN,16));
ta.setLineWrap(true);
ta.setWrapStyleWord(true);
ta.setName(Integer.toString(nameTA));
nameTA+=1;
basicKey("ENTER", enter, ta);
ta.addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent ev) {
try {
taMousePressed(ev);
} catch (BadLocationException ex) {
Logger.getLogger(forquestion.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
return ta;
}
public void basicKey(String s, Action a, JTextArea ta) {
ta.getInputMap().put(KeyStroke.getKeyStroke(s), s);
ta.getActionMap().put(s, a);
}
Action enter = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
addLine();
}
};
private void taMousePressed(java.awt.event.MouseEvent ev) throws BadLocationException {
int now_focus = Integer.parseInt(ev.getComponent().getName());
int _caret;
_caret = textArea.get(now_focus).getCaretPosition();
Rectangle rectangle = textArea.get(now_focus).modelToView(_caret);
double x = rectangle.getX();
//int xc = textArea.get(now_focus).getLocation().x;
double y = rectangle.getY();
//int yc = textArea.get(now_focus).getLocation().y;
//double h = rectangle.getHeight();
//double w = rectangle.getWidth();
System.out.println(x);
System.out.println(y);
//System.out.println(xc);
//System.out.println(yc);
//System.out.println(h);
//System.out.println(w);
System.out.println("");
}
}
My code will print XY position each time you press a Text Area. But, the display always same in every text area. (Try to make many Text Area and give some text) Btw, it just simple code. You need change the window frame size for update the new text area after you press enter key..hahaha.
So, my question is: How can i get the XY position of caret (text cursor) in any Text Area. I want to display JPopmenu there. :)
I hope this question clear for you. Thx before.
The Rectangle reported back is relative to the text area, where it's 0x0 position is the top, left corner of the component.
If you use something like...
popup.show(textArea.get(now_focus), rectangle.x, rectangle.y + rectangle.height);
Where popup is a JPopupMenu, it will make the required translations to the screen itself.
Now. Having said that. Personally, I would prefer to use the popup API support provided by Swing. This is going to mean needing to create a custom component that extends from JTextArea to achieve it...
public class MyPopupTextArea extends JTextArea {
/*...*/
public Point getPopupLocation(MouseEvent evt) {
Rectangle rectangle = textArea.get(now_focus).modelToView(_caret);
Point p = rectangle.getLoction();
p.y += rectangle.height;
return p;
}
}
Then, based on your needs, you can use setComponentPopup to provide a shared instance of the JPopupMenu or, if required, create a custom JPopupMenu for each instance of the custom editor and use setComponentPopup as you see fit...no messing about with mouse listeners ;)
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) {
}
}
}
I want to write a little code which react to a mouse click. But it seems the only way is to listen to clicks on Java components. A direct listener to all clicks would be great.
Is there actually a possibility to implement this in Java?
Thanks in advance!
Update:
Found out, that it would need a hook via JNI with some C coding.
More information on
http://www.jotschi.de/?p=90
Best regards,
fnst
It's perfectly possible if you are willing to use a third party library - JNativeHook
It provides these functionality using JNI which is otherwise not possible in pure java apps.
Don´t think so, because of the sandbox you´re running in.
some food for thought: use Point in Java to detect where the click occurs. http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Point.html
admittedly, ive only used it once before for detecting rows in a table something like, but it seems the closest to what ive found answering your qn.:
public void mouseClicked(MouseEvent e) {
JTable target = (JTable)e.getSource();
//get the coordinates of the mouse click
Point p = e.getPoint();
//get the row index that contains that coordinate
row= target.rowAtPoint(p);
}
im sorry if this isn't what you're looking for, but otherwise, clicking on components is the only way to go. whats the alternative- clicking on containers? well that just doesn't make any sense does it?
As far as I know, there is not easy way to accomplish what you want. But what you want could be done.. Well for modern way to accomplish this task, I suggest you examine java.awt.Dialog show method..
package mouseclickevent;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.MenuComponent;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.lang.reflect.Method;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class FrmEvent extends JFrame {
public FrmEvent(){
JPanel panel = new JPanel();
getContentPane().add(panel);
JButton btn = new JButton("Test");
panel.add(btn);
panel.add(new JTextField("Test"));
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
FrmEvent frm = new FrmEvent();
frm.setBounds(300,300, 200, 200);
frm.show();
}
});
}
private void consumeEvents() {
try {
if (Thread.currentThread().getClass().getName().endsWith(
"EventDispatchThread")) {
EventQueue eq = null;
eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
if (eq == null) {
return;
}
while (isVisible() || isShowing()) {
AWTEvent event = eq.getNextEvent();
Object src = event.getSource();
Class kActiveEvent= Class.forName("java.awt.ActiveEvent");
if (kActiveEvent != null) {
if (kActiveEvent.isInstance(event)) {
Method m;
Class types[] = {};
Object args[] = {};
m = kActiveEvent.getMethod("dispatch", types);
if (m != null) {
m.invoke(event, args);
continue;
}
}
}
dispatchEvent(src, event);
}
}
}
catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
private void dispatchEvent(Object src, AWTEvent event) {
if (event.getID()== MouseEvent.MOUSE_CLICKED) {
System.out.println("mouseClicked");
}
if (src instanceof Component) {
( (Component) src).dispatchEvent(event);
} else if (src instanceof MenuComponent) {
( (MenuComponent) src).dispatchEvent(event);
}
}
public void show(){
super.show();
consumeEvents();
}
public static void main(String[] args) {
FrmEvent frm = new FrmEvent();
frm.setBounds(300,300, 200, 200);
frm.show();
}
}