So I am creating a program that changes the JTextField depending on what the user Chooses. So its pretty much like a Word Document with fonts(from a JComboBox), sizes, and attributes(Bold...etc). Obviously mine is very small and only works with a single line(A JTextField). The Problem i'm getting is that After I've written some things down into the field with specific attributes and I want to add more words down with different attributes, it changes the whole text field rather than just the new part I added. I know the problem with it is
Writer.addKeyListener(new KeyAdapter() {
#Override
public void keyTyped(KeyEvent e) {
if((e.getKeyChar() >= e.VK_A && e.getKeyChar()<= e.VK_Z) || (e.getKeyChar() >= 'a' && e.getKeyChar()<='z')|| e.getKeyChar() == '\b' ) // Checks to make sure No Numbers
{
Writer.setEditable(true);
}
else
{
Writer.setEditable(false);
}
if(font.equals("Arial"))
{
if(size.equals("8"))
{
setSize = 8;
}
else if(size.equals("10"))
{
setSize = 10;
}
else if(size.equals("12"))
{
setSize = 12;
}
if(color.equals("Black"))
{
setColor = Color.BLACK;
}
else if(color.equals("Blue"))
{
setColor = Color.BLUE;
}
else if(color.equals("Red"))
{
setColor = Color.red;
}
Font font = new Font("Arial", setAttribute, setSize);
Writer.setFont(font); // I Know that this sets the font everytime, so i'm pretty sure this is where my problem is.
Writer.setForeground(setColor);
}
Any ideas on how I can make the Change so it newly entered characters can have different fonts than the previous characters.
JComponents for styled text - How to Use Editor Panes and Text Panes, examples here, here, some of examples on this forum
JTextFields allow the use of HTML. It might take a bit of work to parse and insert new html code, but you might be able to do it that way.
There's a list of WYSIWYG text editors for Java here. I especially like metaphase editor, based on Charles Bell's HTMLDocumentEditor.
Related
I'm working on a Java GUI project in NetBeans and have two different JPanels with JTables and a JTextField that the user can type into in order to search for items in the JTable.
It looks like this
.
When the user types into the JTextField the KeyTyped event is called which calls my filterSearchResults() method. This method makes a new TableRowSorter for each of the 4 JTables I am working with every time it is called (I know it's inefficient but I am just shooting for something that works at the moment).
The search function works perfectly for the first two tables (jTable1 and jTable2) but does absolutely nothing for the second two even though it seems I'm doing the exact same process for both.
The tables are contained in jScrollPanes which are in jTabbedPanes in different tabs.
Here is what the GUI hierarchy looks like.
For jTable1 and jTable2 the table updates based on the search query entered in the text field and it looks like this
When the user types into the text field for the other 2 tables nothing happens. I was under the impression that there was no need to call an update function for the tables and I don't believe that there is an update function called for JTable1 and JTable2 at any point.
I can't explain the discrepancy and I don't know why the filtering doesn't appear on the finalMaleGroupsTable and finalFemaleGroupsTable. The filtering function is as follows:
//UPDATE JTABLE FROM SEARCH FILTER
void filterSearchResults(int x){
firstRowSorter = new TableRowSorter<>(jTable1.getModel());
secondRowSorter = new TableRowSorter<>(jTable2.getModel());
thirdRowSorter = new TableRowSorter<>(finalMaleGroupsTable.getModel());
fourthRowSorter = new TableRowSorter<>(finalFemaleGroupsTable.getModel());
String text = jTextField1.getText();
jTable1.setRowSorter(firstRowSorter);
if (text.trim().length() == 0) {
firstRowSorter.setRowFilter(null);
} else {
firstRowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
}
jTable2.setRowSorter(secondRowSorter);
if (text.trim().length() == 0) {
secondRowSorter.setRowFilter(null);
} else {
secondRowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
}
text = jTextField5.getText();
finalMaleGroupsTable.setRowSorter(thirdRowSorter);
if (text.trim().length() == 0) {
thirdRowSorter.setRowFilter(null);
} else {
thirdRowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
}
finalFemaleGroupsTable.setRowSorter(fourthRowSorter);
if (text.trim().length() == 0) {
fourthRowSorter.setRowFilter(null);
} else {
fourthRowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
}
}
Thank you for your help.
So i have been trying to print a method onto a Jpanel with no success, the method works on the console but i cant get it to print to the Jpanel, I am fairly new to Java, so if you have any advice could you keep it fairly simple :D. I have tried several solutions to similar questions on here to no avail here is the Code.
public class fizzbuzz {
private static MouseEvent fizzBuzz() {
String fizz = "Fizz";
String buzz = "Buzz";
String fB = "Fizz buzz";
int num = 0;
while(num <= 100) {
num++;
if (num % 3 == 0 && num % 5 != 0) {
System.out.println (fizz);
}
else if (num % 5 == 0 && num % 3 != 0) {
System.out.println (buzz);
}
else if (num % 3 == 0 && num % 5 == 0){
System.out.println (fB);
}
else {
System.out.println(num);
}
}
return null;
}
public static void ShowGUI(String[] args) {
JPanel displayPanel = new JPanel();
JButton okButton = new JButton("Start count");
okButton.setFont(new Font("Malina Light", Font.TRUETYPE_FONT, 14));
final JLabel Jlab = new JLabel();
okButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Jlab.getToolTipText(fizzBuzz());
}
});
JPanel content = new JPanel();
content.setLayout(new BorderLayout());
content.add(displayPanel, BorderLayout.CENTER);
content.add(okButton, BorderLayout.SOUTH);
content.add(Jlab, BorderLayout.NORTH);
JFrame window = new JFrame("Gui test");
window.setContentPane(content);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(250, 250);
window.setLocation(100, 100);
window.setVisible(true);;
}
public static void main(String[]args){
//fizzBuzz();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ShowGUI(args);
}
});
}
}
Here:
Jlab.getToolTipText(fizzBuzz());
that is absolute nonsense. This call will invoke your static method, yes. But beyond that it does nothing to get text into your JLabel.
The javadoc for getToolTipText() says:
Returns the tooltip location in this component's coordinate system.
Hint: try jLabel.setText("some string"); instead.
And then: decide what you want to do: either you want to print to the console (as your fizzBuzz() method does) or you update UI elements.
Beyond that: read about java naming conventions. Class names go UpperCase, and variables/fields go camelCase. By deviating from such standards you make reading your source code much harder.
And the real answer is: don't just call some method because you maybe assume it makes sense. When you write code, each character, each keyword, each and every thing do matter. Don't write something down that you do not understand. Instead - read the corresponding documentation for example. Learning Swing UIs by trial/error will not work - that stuff is simply too complicated to get right. Thus: start reading here for example to learn how to work with JLabels.
First of all:
private static MouseEvent fizzBuzz() {
What is the point of the above method signature? Why would you ever return a MouseEvent. The method has nothing to do with a mouse.
So i have been trying to print a method onto a Jpanel with no success
Where? I don't see any logic in your code that attempts to do this. In any case you don't display text on the panel, you display text in a component that you add to the panel.
So start by reading the Swing Tutorial for Swing basics.
Start with the section on How to Use Text Areas. There is demo code you can download that shows you how to append text to a text area.
You can then try the section on How to Write a MouseListener. Again the demo code shows how to add text to the text area when a MouseEvent is generated.
Using these two examples should help you better structure your code and allow you to append text to a text area instead of use System.out.println(...).
I would like to know the best way to approach what I am trying to achieve, I can't figure out the logical path I should take.
I have a JTextField and a JTextButton, when input is added to the JTextField and either enter or the button is pressed, it will display on the JTextArea. Now, what I want is to choose when and what the JTextArea and Button do.
For example I want default Enter & Button to display next append text in my code. Then when a case is presented I want the JTextField to only accept either int or string and then once completed, I want it to go back to default.
I don't know if what I am trying to do is logical or best practice...
The idea behind this is, I have a story text based gui game. I want it to display text to the JTextArea and when Enter or button is pressed to display the next line of text and when in the story it requires user input, the JTextArea will look for that input.
So far I have an EventListener and ActionListener which submits what I type from JTextField to JTextArea, but that is about it.
Thanks for your assistance! I have solved my issue, not sure if this is the "Best Solution". I combined your solution with a bit of tweaking.
In this instance, buttonState is an int which can be changed throughout my code by calling a constructor "setButtonState". I could have made buttonState a static to make things easier, but thought I could keep things clean.
enterButton.addActionListener(new ActionListener()
{ //This is used so when the enter screen button is pressed, it will submit text from text field to text area.
public void actionPerformed(ActionEvent e) {
String text = inputTextField.getText();
InputTextFieldEvent event = new InputTextFieldEvent(this, text);
if (buttonState == 0) //Displays all text in JTextField to JTextArea, mostly for testing purposes.
{
if (textInputListener != null) {
textInputListener.setInputListenerOccurred(event);
}
}
if (buttonState == 1) //Only accepts string for answer
{
if (inputTextField.getText().matches("[a-zA-Z]+"))
{
textInputListener.setInputListenerOccurred(event);
}
else
{
getAppendMainTextArea("You have entered an invalid input, only letters are allowed.");
}
}
if (buttonState == 2) //Only accepts int for answer
{
if (inputTextField.getText().matches("[0-9]+"))
{
textInputListener.setInputListenerOccurred(event);
}
else
{
getAppendMainTextArea("You have entered an invalid input, only numbers are allowed.");
}
}
}
});
I'm developing a small calculator widget that keeps a running log of calculations. It's supposed to scroll to the bottom of the log every time a new entry is added. This part seems to be working fine.
The problem is, when I press a calculator button that does not add to the log, the log pane always scrolls back to the top, and the scrollbar disappears. How can I keep it from doing this?
The code that adds to the log is:
private JTextPane logArea; //This is placed inside a JScrollPane
private void log(String m, SimpleAttributeSet a) {
int len = logArea.getDocument().getLength();
logArea.setEditable(true);
logArea.setCaretPosition(len);
logArea.setCharacterAttributes(a, false);
logArea.replaceSelection(m);
logArea.scrollRectToVisible(new Rectangle(0,logArea.getBounds(null).height,1,1));
logArea.setEditable(false);
}
The code that seems to be messing with the scroll is:
private void addDigit(char digit) {
if (clearDisplayBeforeDigit) {
clearNumDisplay();
}
if (numInDisplay.getText().length() < maxNumDigits) {
if (digit == '.') { //Point
if (!hasPoint) { //Only one point allowed
hasPoint = true;
String newText = numInDisplay.getText() + ".";
numInDisplay.setText(newText);
}
} else { //New digit
String newText = numInDisplay.getText() + digit;
numInDisplay.setText(newText);
}
}
}
The code you think is causing the problem doesn't even reference the logArea, so why would you think this causes the problem?
You don't need to use the scrollRectToVisible(...) method. The setCaretPosition(...) should do the trick. Although you should get the length of the document and invoke that method AFTER you update the document.
Check out Text Area Scrolling for more information.
Edit:
I also don't see any reason for changing the editability of the text area.
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();
}
}
});