I want to have words inside a Jlabel text that are clickable, and I want to register a MouseListener for each word or getting the clicked word (otherwise). The image below demonstrate what I want. Is this possible ?!
No, you can only make the whole JLabel clickable. But you can put several JLabels next to each other of course, making only a few clickable (and different in appearance).
You could also use HTML, e.g. in a JEditorPane, and make certain words clickable via HTML, if that suits your needs. I found something about that here, and this is how it could look like for you:
JEditorPane jep = new JEditorPane("text/html", "Click <a href='pdf'>here</a> to display a PDF file. For more information click <a href='info'>here</a>.");
jep.setEditable(false);
jep.setOpaque(false);
jep.addHyperlinkListener(new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent hle) {
if (HyperlinkEvent.EventType.ACTIVATED.equals(hle.getEventType())) {
if (hle.getDescription().equalsIgnoreCase("pdf")) {
// display PDF
} else if (hle.getDescription().equalsIgnoreCase("info")) {
// display information
}
}
}
});
Related
Well, I decided to edit everything. So, the code goes like this:
public void actionPerformed(ActionEvent e) {
if (!uiCreator.getTextArea().getText().equalsIgnoreCase("Beggining text")) {
JOptionPane.showMessageDialog(null, "You must have main method first", "Error",
JOptionPane.ERROR_MESSAGE);
} else {
n = Integer.valueOf(JOptionPane.showInputDialog("..."));
l = Integer.valueOf(JOptionPane.showInputDialog("..."));
uiCreator.getTextArea()
.setText("Beggining text with few additions");
On the code above, I made it to check if JTextArea contains text that is needed and if it doesn't it will show an error message. If it does it will set a text with few more words.
Now. I also have more JButtons. So if one is clicked, it will also do the same thing. Check the text and if it meets all conditions, set new modified text. But, now, my problem comes here. I have this:
public void actionPerformed(ActionEvent e) {
if (!uiCreator.getTextArea().getText()
.equalsIgnoreCase("Beggining text with few additions")) {
JOptionPane.showMessageDialog(null, "Error, you don't have main or JFrame inside main", "Error",
JOptionPane.ERROR_MESSAGE);
} else {
uiCreator.getTextArea()
.setText("Beggining text with even more additions");
}
Which checks if JTextArea had "Beggining text with few additions" and if it did, change the text to Beggining text with even more additions. I have few more buttons that do the same thing. Now, I would like to know a way to let setText(some text) method be used regardless is there Beggining text with few additions or Beggining text with even more additions.
Don't use setText(...) to keep replacing all the text.
Instead you can use methods like:
replaceSelection(...);
getDocument().insertString(...);
to change part of the text or insert new text.
I'm trying to make a text area record that every time the button is press, it means that it has been recorded and should be showing record1, record2, record3, etc. on it.
My goal is that, every button is pressed it will add text to the text area with different text label so that no redundancy.
I tried it with my own with this:
private void btnReqstRefreshActionPerformed(java.awt.event.ActionEvent evt) {
JLabel labelthis = new JLabel("record1");
label.setSize(label.getPreferredSize());
TextArea1.add(label);
TextArea1.revalidate();
TextArea1.repaint();
}
I know it is wrong, but is it possible?
text area is like a mini text editor - you add text to it not other components. Instead of adding labels - just add the text. Something like:
TextArea1.setText(TextArea1.getText() + "record1")
This should append record1 to the existing text in the text area.
According to my experience this is possible.
`private void btnReqstRefreshActionPerformed(java.awt.event.ActionEvent evt) {
i++;//i class level variable(static) to avoid redundancy
//labelThis initialized earlier should be accessible here
String oldText = labelThis.getText().toString();
oldText += "record "+i;
labelThis.setSize(labelThis.getPreferredSize());
TextArea1.add(labelThis);
TextArea1.revalidate();
TextArea1.repaint();
}`
I have grid layout witch some fields added like that:
private Component userDetailsTab(final User user) {
final GridLayout details = new GridLayout(2, 1);
details.setMargin(true);
details.setSpacing(true);
details.addComponent(createDetailLabel(Messages.User_Name));
final Component username = createDetailValue(user.getName());
details.addComponent(username);
...
I have also Layout click listener which replace labels on text field, it looks like that:
final TextField tf = new TextField();
details.addListener(new LayoutClickListener() {
private static final long serialVersionUID = -7374243623325736476L;
#Override
public void layoutClick(LayoutClickEvent event) {
Component com = event.getChildComponent();
if (event.getChildComponent() instanceof Label) {
Label label = (Label)event.getChildComponent();
details.replaceComponent(com, tf);
tf.setValue(label.getValue());
}
}
});
In future I want to enable click on label, edit it and write changes to database after clicking somewhere else (on different label for example).
Now when I click on 1st label and then on 2nd label, effect is: 1st has value of 2nd and 2nd is text field witch value of 2nd. Why it's going that way? What should i do to after clicking on 1st and then 2nd get 1st label witch value of 1st?
You don't need to swap between Labels and TextFields, you can just use a TextField and style it look like a Label when it's not focused.
When I tried to create click-to-edit labels, it created a ton of extra work for me. I'd discourage it (and do as Patton suggests in the comments).
However, if you're going to insist on trying to create in-place editing, you will want to do the following:
Create a new class that extends a layout (e.g. HorizontalLayout), which can swap out a label for a text field
use LayoutClickListener to removeComponent(myLabel) and addComponent(myTextField)
use BlurListener to swap back to the label
use ValueChangeListener on the text field to copy its value to the label
This is a still a bad idea because:
Users cannot see affordances as easily (they can't tell what's editable)
Users cannot use the keyboard to tab to the field they want to edit
It adds unncessary complexity (maintenance time, etc).
I would recommend, if you want in-place editing, just show the text field, and save the new value with the BlurListener.
My swing app contains a JEditorPane which lets users edit text in a WYSIWYG fashion, including toolbar buttons for bold, italic, and setting fonts, etc.
The content type on the JEditorPane is text/html
The problem: Users want to be able to type tab characters in the editor pane, close the edit dialog (saving HTML text to persistent storage) and see their tabs rendered. However, HTML treats all whitespace runs as a single space.
public class NoteTest {
public static void main(String[] args) {
final JEditorPane editPane1 = new JEditorPane("text/html", "Try typing some tabs");
editPane1.setPreferredSize(new Dimension(400, 300));
JOptionPane.showMessageDialog(null, new JScrollPane(editPane1));
JOptionPane.showMessageDialog(null, new JScrollPane(new JEditorPane("text/html", editPane1.getText()))); // where did the tabs go?
}
}
After typing tabs in the first JEditorPane, we get the HTML text from it, and pass it to a second JEditorPane, which renders the tabs as spaces.
How can I render these tabs? Should I be saving the user-entered content as RTF instead of HTML? Should I parse the HTML and build an HTML table with rows and cells (ugh). Or is there some way to tell swing to render the tab characters as tabs?
For better help sooner, post an SSCCE. This SSCCE does not show the behavior you describe.
Note the 'tab' between the n & g of typin g.
import java.awt.Dimension;
import javax.swing.*;
public class NoteTest {
public static void main(String[] args) {
final JEditorPane editPane1 = new JEditorPane("text/html", "Try typing some tabs");
editPane1.setPreferredSize(new Dimension(400, 300));
JOptionPane.showMessageDialog(null, new JScrollPane(editPane1));
JOptionPane.showMessageDialog(null, new JScrollPane(new JEditorPane("text/html", editPane1.getText()))); // where did the tabs go?
}
}
There were some tabs at the end that disappeared, but that makes sense, since tabs are not supported in HTML correctly unless included in a pre element. I'm guessing that the Swing HTML parsing ignores them as redundant.
What if you use < PRE > < /PRE > tags for the text and for the tab char?
I am looking for a way to put example text into a swing JTextField and have it grayed out. The example text should then disappear as soon as any thing is entered into that text field. Some what similar to what stackoverflow does when a user is posting a question with the title field.
I would like it if it was already a extended implementation of JTextField so that I can just drop it in as a simple replacement. Anything from swingx would work. I guess if there is not an easy way to do this my option will probably be to override the paint method of JTextField do something that way maybe.
Thanks
The Text Prompt class provides the required functionality without using a custom JTextField.
It allows you to specify a prompt that is displayed when the text field is empty. As soon as you type text the prompt is removed.
The prompt is actually a JLabel so you can customize the font, style, colour, transparency etc..:
JTextField tf7 = new JTextField(10);
TextPrompt tp7 = new TextPrompt("First Name", tf7);
tp7.setForeground( Color.RED );
Some examples of customizing the look of the prompt:
If you can use external librairies, the Swing components from Jide software have what you are looking for; it's called LabeledTextField (javadoc) and it's part of the JIDE Common Layer (Open Source Project) - which is free. It's doing what mklhmnn suggested.
How about initialize the text field with default text and give it a focus listener such that when focus is gained, if the text .equals the default text, call selectAll() on the JTextField.
Rather than overriding, put a value in the field and add a KeyListener that would remove the value when a key stroke is registered. Maybe also have it change the foreground.
You could wrap this up into your own custom JTextField class that would take the default text in a constructor.
private JLabel l;
JPromptTextField(String prompt) {
l = new JLabel(prompt, SwingConstants.CENTER);
l.setForeground(Color.GRAY);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (this.getText().length() == 0) {
// Reshape the label if needed, then paint
final Rectangle mine = this.getBounds();
final Rectangle its = l.getBounds();
boolean resized = (mine.width != its.width) || (mine.height != its.height);
boolean moved = (mine.x != its.x) || (mine.y != its.y);
if (resized || moved)
l.setBounds(mine);
l.paint(g);
}
}
You can't do that with a plain text field, but you can put a disabled JLabel on top of the JTextField and hide it if the text field gets the focus.
Do it like this:
Define the string with the initial text you like and set up your TextField:
String initialText = "Enter your initial text here";
jTextField1.setText(initialText);
Add a Focus Listener to your TextField, which selects the entire contents of the TextField if it still has the initial value. Anything you may type in will replace the entire contents, since it is selected.
jTextField1.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
if (jTextField1.getText().equals(initialText)) {
jTextField1.selectAll();
}
}
});