I have a large JTextArea where users can input a bunch of text. My program allows users to select some text and create smaller JTextAreas with the selected text for closer analysis (editing, etc).
The users can update the larger or smaller JTextAreas and when they do, I want the other to update to this new text as well.
My problem is getting the text in the large JTextArea and the smaller ones to reference each other. Is there a good way of doing this? I am having a difficult time splitting up the large text area and using document listeners at the same time. It becomes difficult when there is an overlap of text from the smaller text areas..
ex.
"large text area"
Hello. My name is Matthieu and I am getting frustrated with all these text boxes :p.
"smaller text areas"
Hello.
all these text boxes :p.
text boxes :p.
if I change "text boxes" to "apple" in 2, then box 3 and the full text should update accordingly!
This is probably not what you want to hear, but that sounds like a very bad idea... The first reason is the fact that it is very complicated to manage in the code and design. The second reason is that it makes it more complex for the user to use...
If you really want to implement it this way, I would say the best way would be to keep a list of snippets that are being edited, and add an item to that list that contains the starting index, the original text and which textbox it is being edited in.
Then whenever any changes are made in any textbox, run a method to make the changes to all the textboxes and also updates all the items in the list with updated original text and starting indexes.
I honestly can't see a simple way to do this, and the more textboxes you have, the slower it will get as well.
A much better design in my opinion would be something like a JEditorpane to just display the text (As the big textbox) showing the static text, with a single textbox that displays the selected text and allows editing. This makes the coding pretty trivial, but (Possibly even more importantly), it makes the user interface much simpler and cleaner.
Without knowing exactly why you need this, i can't be sure that the second way would be better, but I would rather use a simpler app as a user.
This could be very difficult, depending on what you want the end result to be. It looks to me like you'd need to track the selection beginning and ending along with each of the boxes. As the text is changed in #2, you could replace the original long text starting at the #2 start index and ending at the end index. That could be ok.
Where I see a problem is if you do something like insert "dumb" in the middle of #2. How would you handle that in #3? Would you shift the start index of #3 to compensate, or would you shift the text that #3 is referencing so it says "dumb test b"?
Before you code this more, I think you should logically work through what you want to happen for, at the least:
inserting characters
deleting characters
changing characters
And probably handle it on a character by character basis with your listeners. It all depends on what you want the end result to be.
All you need to do is subclass the JTextArea and use an interface. The interface can be used to let the sub text areas know that the main text area has been updated.
You will need two subclasses. One will be the main text area, the other will be for the sub panels. Have the sub panels implement an interface so when the parent is updated, they receive the data. Then they can process it how they choose.
The sub text areas are registered with the main text area
Here is a working example:
Main.java
This runs the demo
package Text;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
/**
*
* #author dvargo
*/
public class Main
{
public static void main(String [] args)
{
//build the main text area
JFrame mainFrame = new JFrame();
mainFrame.setSize(700,700);
mainFrame.setTitle("Main Frame");
mainFrame.setLayout(new GridLayout());
//build a sub text area
JFrame subFrameA = new JFrame();
subFrameA.setTitle("Sub Frame A");
subFrameA.setSize(300,300);
subFrameA.setLayout(new GridLayout());
subFrameA.setLocation(mainFrame.getX() + mainFrame.getWidth() + 25, mainFrame.getY());
//build another sub text area
JFrame subFrameB = new JFrame();
subFrameB.setTitle("Sub Frame b");
subFrameB.setSize(300,300);
subFrameB.setLayout(new GridLayout());
subFrameB.setLocation(subFrameA.getX() + subFrameA.getWidth() + 50, subFrameA.getY());
//this is the main text area. Anything typed into here will be sent to the sub text areas
TextField mainTextField = new TextField("Type here and text will appear in the sub frames!!!");
//this sub text area will just mirror the main text area
SubTextField subTextFieldA = new SubTextField();
//this sub text area will add a "-" to the begining of every line
SubTextField subTextFieldB = new SubTextField()
{
#Override
public void update(String text, char lastPressedChar)
{
super.update("- " + text.replace("\n", "\n- "),lastPressedChar);
}
};
//register the sub text areas with the main text areas
mainTextField.register(subTextFieldA);
mainTextField.register(subTextFieldB);
//add them to their frames
mainFrame.add(new JScrollPane(mainTextField));
subFrameA.add(new JScrollPane(subTextFieldA));
subFrameB.add(new JScrollPane(subTextFieldB));
//make everything visible
mainFrame.setVisible(true);
subFrameA.setVisible(true);
subFrameB.setVisible(true);
}
}
I_SubTextField.java
Interface for all sub text areas to implement
package Text;
/**
* Interface to implement to be notified when the text has changed
* #author dvargo
*/
public interface I_SubTextField
{
public void update(String text, char lastChar);
}
TextField.java
Use this as your main text area
package Text;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTextArea;
/**
* Text area
* #author dvargo
*/
public class TextField extends JTextArea
{
//holds all registered sub text areas that are registered for updates
List < I_SubTextField > registeredSubTextAreas = new ArrayList < I_SubTextField > ();
/**
* Default constructor
*/
public TextField()
{
this("");
}
/**
* Constructor
* #param text Sets this text area to display this text
*/
public TextField(String text)
{
super(text);
addListener();
}
/**
* Registers a sub text area to get updates when this text area is updated
* #param subTextArea
*/
public void register(I_SubTextField subTextArea)
{
registeredSubTextAreas.add(subTextArea);
}
/**
* Unregisters a sub text area to stop receiving updates
* #param subTextField
*/
public void unRegister(I_SubTextField subTextField)
{
registeredSubTextAreas.remove(subTextField);
}
/**
* Notifies all registered classes when the data in the main window has changed
*/
private void addListener()
{
addKeyListener(new java.awt.event.KeyAdapter()
{
public void keyReleased(java.awt.event.KeyEvent evt)
{
for (I_SubTextField registeredField : registeredSubTextAreas)
{
registeredField.update(TextField.this.getText(), evt.getKeyChar());
}
}
});
}
}
SubTextField.java
Use this for all sub text areas
package Text;
/**
* Represents a sub text area. This can be registered with a TextField to be notified
* when the data has been updated
* #author dvargo
*/
public class SubTextField extends TextField implements I_SubTextField
{
/**
* Default constructor
*/
public SubTextField()
{
super();
}
/**
* Constructor
* #param text Text to display in the text area
*/
public SubTextField(String text)
{
super(text);
}
/**
* Called when the parent TextField is updated. Handle the text as you want
* #param text The text for the main parent
* #param lastPressedChar The last char the user pressed
*/
public void update(String text, char lastPressedChar)
{
setText(text);
}
}
Notice that the SubTextField is a sub class of TextField so you can register additional SubTextFields to a SubTextField.
You can set them up to register with each other and send the unprocessed text to each other. Then each SubTextField can process the text the way it wants. All y ou need to do is override the update()
I would use the same model (Document) in all the text areas. Try to override the View used in JTextArea to show only desired fragment. (See PlainView sources).
Related
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 a TableViewer with a ComboBoxCellEditor. When I click into the cell, first I get a text box (similar to the TextCellEditor) with an arrow next to it. If I click the arrow, I get the drop down list with the values I put into it.
Is there any way for me to skip the text box step? I want it to open up the combo box right away when I click/traverse into the cell. Hand in hand with this is that I also don't want to allow any options other than the ones in the list.
I thought maybe this behavior is controlled by a style, but the only styles I found were
/**
* The list is dropped down when the activation is done through the mouse
*/
public static final int DROP_DOWN_ON_MOUSE_ACTIVATION = 1;
/**
* The list is dropped down when the activation is done through the keyboard
*/
public static final int DROP_DOWN_ON_KEY_ACTIVATION = 1 << 1;
/**
* The list is dropped down when the activation is done without
* ui-interaction
*/
public static final int DROP_DOWN_ON_PROGRAMMATIC_ACTIVATION = 1 << 2;
/**
* The list is dropped down when the activation is done by traversing from
* cell to cell
*/
public static final int DROP_DOWN_ON_TRAVERSE_ACTIVATION = 1 << 3;
and they didn't seem to be relevant. In fact, I set all of them, and I wasn't able to get the functionality I'm looking for.
How can I have the dropbox show without having the accompanying text box?
It's possible to change the styling of the underlying Combo widget by using the constructor:
ComboBoxCellEditor(Composite parent, String[] items, int style)
and passing SWT.READ_ONLY as style
I'm writing a program in java language and I want to make some changes in one part of my JOptionPane.showInputDialog. My dialog is this :
JOptionPane.showInputDialog("Total Amount Deposited:\t\t" +
totalAmount + "\n Enter Coin Value \n" + "(Enter 1 to stop)");
and I want to make the part that is saying (Enter 1 to stop) a little bit smaller than the other parts.
I'm beginner in java language (roughly 2 months :D) and don't have any other experience. so, please keep your answers simple. thanks in advance.
A JOptionPane will display the text in a JLabel, which supports basic HTML. So you will need to wrap your text string in HTML, then you can use different fonts, colors or whatever.
Simple example:
String text = "<html>Normal text <b>and bold text</b></html>";
JOptionPane.showInputDialog(text);
You can also use Font.pointSize() or Font.size() from java.awt.Font.
Create a String = "the text"
put in a label pa
use setFont();
Quick example :
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Test extends JFrame {
public static void main(String[] args)
{
String a = "(enter 1 to stop)";
JLabel pa = new JLabel();
JFrame fr = new JFrame();
fr.setSize(200,200);
pa.setText(a);
pa.setFont(pa.getFont().deriveFont(11.0f)); //change the font size from here
fr.add(pa);
fr.setVisible(true);
}
}
For JDK 8.x, I find the following works to enlarge the font size of most portions of the built-in JOptionPane.showInputDialog, especially buttons, textboxes and comboboxes.
It is mostly generic, except for the two parts I want to be bold font.
It even allows for exceptions (think of it as an "all except" strategy) when you want to enlarge 99% of the pieces of an input dialog, except for one or two pieces.
Sorry for the bad formatting, but the "Code Sample" tool messed up everything and I don't have time to fix it.
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.swing.*;
/**
* Changes the font size used in JOptionPane.showInputDialogs to make them more
* ADA section 508 compliant by making the text size larger, which is very nice
* for older people and anyone else with vision problems.
*
* #param fontSize
* - size of the font in pixels
*/
private static void makeDialogsEasierToSee(int fontSize)
{
// This next one is very strange; but, without it,
// any subsequent attempt to set InternalFrame.titleFont will
// be ignored, so resist the temptation to remove it.
JDialog.setDefaultLookAndFeelDecorated(true);
// define normal and bold fonts that we will use to override the defaults
Font normalFont = new Font(Font.MONOSPACED, Font.PLAIN, fontSize);
Font boldFont = normalFont.deriveFont(Font.BOLD);
// get a list of objects that we can try to adjust font size and style for
List<Map.Entry<Object, Object>> entries = new ArrayList<>(UIManager.getLookAndFeelDefaults().entrySet());
// System.out.println(entries.size());
// remove anything that does NOT involve font selection
entries.removeIf(filter -> filter.getKey().toString().indexOf(".font") == -1);
// System.out.println(entries.size());
// Define a list of font sections of the screen that we do NOT want to
// enlarge/bold.
// The following is specific to jKarel so we do not obscure the display of
// "beeper piles" on the maps.
List<String> exempt = Arrays.asList("Panel.font");
// remove anything on the exempt list
entries.removeIf(filter -> exempt.contains(filter.getKey().toString()));
// System.out.println(entries.size());
// optional: sort the final list
Collections.sort(entries, Comparator.comparing(e -> Objects.toString(e.getKey())));
// apply normal font to all font objects that survived the filters
for (Map.Entry<Object, Object> entry : entries)
{
String key = entry.getKey().toString();
// System.out.println(key);
UIManager.put(key, normalFont);
}
UIManager.put("Label.font", boldFont);
UIManager.put("InternalFrame.titleFont", boldFont);
}
You basically have two straightforward options - Switch to JDialog or use HTML.
JOptionPane is intended for simple messages or interaction with the users. JDialog is a better choice if you want to break out of the canned use cases, and as you get more complex you will probably eventually have to switch to it.
To meet your immediate use case, you can send in an html message. The rules are:
You must begin and end with <html></html> tags. Put them in the middle and nothing happens.
You must remove all "\n"'s in your code. They don't work in html
anyway and the JPanel tries to use each line, as defined by \n's as a
separate html doc. Switch to
int totalAmount = 345; //for testing
String message = "<html>"
+ "Total Amount Deposited: " + totalAmount
+ "<br> Enter Coin Value "
+ "<br><span style='font-size:10'>(Enter 1 to stop)</span>"
+ "</html>";
JOptionPane.showInputDialog(message);
I'm finding the amount of helpful documentation/tutorials on the internet are lacking when it comes to the topic of JTextPanes. I'm trying to do a simple text processor, and I want it to be able to select a font family from a JComboBox that populates itself based on the fonts a user has installed on their system. However, no matter what I try with experimenting, I can't figure out how to make it work.
What I have is a toolbar class that is built off of a JTextPane. Currently, it has a bunch of style buttons that work to set alignment and bold, italics and underline.
Here's my code:
/**
* The StyleBar is used to customize styles in a Styled Document. It will take a
* JTextPane as an argument for its constructor and then all actions to be taken
* will affect the text in it.
*
* #author Andrew
*/
public class StyleBar extends JToolBar {
private JLabel fontLbl;
private JComboBox fontBox;
// ...Irrelevant stuff to the problem at hand.
/**
* The initEvents method is used to initialize the necessary events for the
* tool bar to actually do its job. It establishes the focus listener to the
* buttons on the bar, and gives each one its individual functionality. It
* also establishes the Font Selection interface.
*/
public void initEvents() {
//For each item in the tool bar, add the focus listener as well as the
//formatting listeners:
boldFormat.addActionListener(new StyledEditorKit.BoldAction()); //boldFormat is
boldFormat.addActionListener(resetFocus); //a JButton
//Ditto for my italicsFormat and underlineFormat button(s) in the toolbar
leftAlign.addActionListener(new StyledEditorKit.AlignmentAction(null,
StyleConstants.ALIGN_LEFT));
leftAlign.addActionListener(resetFocus); //This listener just resets focus
//back onto the TextPane.
//Ditto for my right and centerAlign buttons
//Set up the Font list, and add a listener to the combo box
buildFontMenu();
}
/**
* The buildFontMenu detects all of the SYstem's available fonts and adds
* them to the Font Selection box.
*/
public void buildFontMenu(){
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
final String[] fontNames = ge.getAvailableFontFamilyNames();
for (int i = 0; i < fontNames.length; i++){
//What do I do here to take the entry at String[i] and make it so that when
//the user selects it it sets the font Family in a similar way to that of
//pressing the boldFormat button or the leftAlign button?
}
}
//Everything else is irrelevant
So to sum up my problem: I have no idea how to properly set the listener to the ComboBox such that a) it's sensitive to the individual font selected and b) somehow uses StyledEditorKit.FontFamilyAction to make life easy?
Slash, if I'm approaching anything about this the wrong way, I'd love to hear the right way. As I said, my sources on the internet aren't very clear on the subject.
Thanks so much!
StyledEditorTest puts the Actions in a JToolBar, but the idea is the same. See also Charles Bell's HTMLDocumentEditor, mentioned here. For example,
bar.add(new StyledEditorKit.FontFamilyAction("Serif", Font.SERIF));
bar.add(new StyledEditorKit.FontFamilyAction("SansSerif", Font.SANS_SERIF));
Addendum: As you are using JComboBox, you can forward the event to the corresponding StyledEditorKit Action, which operates on the current selection by default.
JComboBox combo = new JComboBox();
combo.addItem("Serif");
combo.addItem("Sans");
combo.addActionListener(new ActionListener() {
Action serif = new StyledEditorKit.FontFamilyAction("Serif", Font.SERIF);
Action sans = new StyledEditorKit.FontFamilyAction("Sans", Font.SANS_SERIF);
#Override
public void actionPerformed(ActionEvent e) {
if ("Sans".equals(e.getActionCommand())) {
sans.actionPerformed(e);
} else {
serif.actionPerformed(e);
}
}
});
This may be a bit late, but I found myself stuck on the similar problem, and although the previous answer does help, here is a more complete answer for when you want to use all the fonts available on your computer..
Where "fonts" is a string array containing all the desired fonts to be used in your program
final JComboBox jcb = new JComboBox(fonts);
final Action [] actions = new Action[fonts.length];
for (int i = 0; i < actions.length; i++)
{
actions[i] = new StyledEditorKit.FontFamilyAction(fonts[i], fonts[i]);
}
jcb.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
for (int i = 0; i < actions.length; i++)
{
if (fonts[i].equals((String)jcb.getSelectedItem()))
{
actions[i].actionPerformed(event);
break;
}
}
}
});
I'm trying to make JTextField display dots when its content is longer then display area. I would like to have the same behaviour like in JTable, where when I resize column the text inside changes - when its to long only begining of it is displayed and then there are three dots (to see what I have in mind please run first example from this link and change column size - I'm not allowed to post images because I'm new here;) )
Is is possible? Only solution that I have in mind is extending JTextField with a class that will have additional field oryginalText and will behave like that (didn't test it, it's just a proposal, dimension of the JtextField will not change):
import javax.swing.JTextField;
public class MyTextField extends JTextField {
private String oryginalText;
private int length;
#Override
public void setText(String text) {
oryginalText = text;
if (oryginalText.length() > length)
super.setText(oryginalText.substring(0, length - 2) + "..");
else
super.setText(oryginalText);
}
}
any ideas?
Over your idea of extending JTextField and storing the original (non trimmed) value:
Show the textfield as disabled (or not editable) and with trimmed text. When the user clics the textfield make it enabled/editable and show the whole original text.
Then again when the user press enter or the focus exits of the textfield: disable/not editable and trimmed text.