I made a simple program in Java that contains only one text area and a button. The button is suppose to add a "text". However, it doesn't work for me.
On a side note: I'm trying to keep my functions as short as possible. (I don't want a function with too many line of codes)
First, I create the JFrame
private static void createFrame()
{
//Build JFrame
JFrame frame = new JFrame("Text Frame");
frame.setLayout(null);
frame.setSize(500,400);
Container contentPane = frame.getContentPane();
contentPane.add(textScrollPane());
contentPane.add(buttonAddText());
//Set Frame Visible
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Then the TextArea and the Scrollpane (for adding scrollbar)
private static JTextArea textArea()
{
JTextArea output = new JTextArea();
output.setLineWrap(true); // Text return to line, so no horizontal scrollbar
output.setForeground(Color.BLACK);
output.setBackground(Color.WHITE);
return output;
}
private static JScrollPane textScrollPane()
{
JScrollPane scrollPane2 = new JScrollPane(textArea());
scrollPane2.setBounds(0, 0, 490, 250);
return scrollPane2;
}
And finally, the button
private static JButton buttonAddText()
{
JButton testbutton = new JButton("TEST");
testbutton.setBounds(20, 280, 138, 36);
testbutton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e)
{
//action listener here
textArea().insert("TEXT",0);
System.out.println("Button Tested!");
}
});
return testbutton;
}
When I click on the button, it doesn't do anything.
I just want a text to be added in the JTextArea. Did I forget something?
textArea() is returning a new JTextArea everytime it is called. Therefore your buttonAddText() function is calling textArea() and adding text to a newly created text area that is not contained in the scroll pane.
You need to pass a reference of the text area to the textScrollPane() and the buttonAddText() functions.
Something like this would work:
JTextArea jta = textArea();
contentPane.add(textScrollPane(jta));
contentPane.add(buttonAddText(jta));
Change textScrollPane() and buttonAddText() so that they accept a JTextArea parameter and don't call textArea() in these functions anymore to create new text areas. Instead use the JTextArea object which is passed into the functions.
Related
I made a program and I want to add a JScrollPane to a JTextArea (but it doesn't show up).
Here's the code (or at least everything that has to deal with the JTextArea / JScrollPane, the whole code is a lot):
static JPanel contentPane; // This one got initialised in the constructor
static JTextArea tarMessages;
public void addTextArea{
tarMessages = new JTextArea();
tarMessages.setForeground(Color.WHITE);
tarMessages.setBackground(new Color(0, 0, 0, 0));
tarMessages.setEditable(false);
tarMessages.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
tarMessages.setBounds(600, 124, 200, 192);
tarMessages.setOpaque(false);
/*DefaultCaret dlcMessages = (DefaultCaret)tarMessages.getCaret();
dlcMessages.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);*/
tarMessages.addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e) {
requestFocus();
}
});
JScrollPane scpMessages = new JScrollPane(tarMessages);
scpMessages.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scpMessages.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scpMessages.setPreferredSize(new Dimension(10, 192));
scpMessages.setEnabled(true);
contentPane.add(scpMessages);
contentPane.add(tarMessages);
}
Thank you for helping. Have nice holidays.
JScrollPane scpMessages = new JScrollPane(tarMessages);
...
contentPane.add(scpMessages);
contentPane.add(tarMessages);
A Swing component can only have a single parent.
First you add the text area to the scroll pane, which is correct.
But then you remove it from the scroll pane when you add it to the content pane.
Get rid of:
///contentPane.add(tarMessages);
Also, when you create the text area use code like:
tarMessages = new JTextArea(5, 20);
This will specify the rows/columns of the text area so it can size itself appropriately.
Don't use setBounds(...)
Im trying to display to the user some text:
JTextField warningComponent = new JTextField(VERY_LONG_TEXT_NOENTERS);
warningComponent.setEditable(false);
but the window size is changed according to the text size. I want to set the window to be 30 X 40 all the time regardless of the warning text length.
And i want the warning text to be adjusted to the window size (maybe the user will have to scroll to see the end)
How do i do it?
Maybe i should use other swing component?
I tried most of the methods in JTextField class.
Thanks.
I add it to JPanel
Then the default layout manager should be a FlowLayout which will respect the preferred size of the text field.
To give a suggestion for the preferred size of the text field you need to do:
JTextField warningComponent = new JTextField(VERY_LONG_TEXT_NOENTERS, 20);
The second parameter will give a suggestion on how to size the text field to make approximately 20 characters visible at one time. You will then need to use the arrow keys to see the remaining characters.
And i want the warning text to be adjusted to the window size
If you want the textfield to resize according to the frame size and not the frame size following the dimension of the textfield, you may make use of specific layout to achieve that:
Using BorderLayout:
class MainPanel extends JPanel{
private JTextField txt;
public MainPanel(){
setLayout(new BorderLayout());
setPreferredSize(new Dimension(30, 40));
txt = new JTextField();
txt.setHorizontalAlignment(JTextField.HORIZONTAL);
add(txt);
}
}
Runner class to run to codes:
class TextFieldRunner{
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
JFrame frame = new JFrame("Text Runner");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
You can try JScrollPane in your application, JScrollPane is scroll-able horizontally and vertically as you wish. And add JTextArea to JScrollPane. JTextField is not scroll-able.
Here is a small example:
JScrollPane scrollPane = new JScrollPane();
JTextArea textArea = new JTextArea();
scrollPane.add(textArea);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
This is the values for the scroll policy:
VERTICAL_SCROLLBAR_AS_NEEDED
VERTICAL_SCROLLBAR_NEVER
VERTICAL_SCROLLBAR_ALWAYS
HORIZONTAL_SCROLLBAR_AS_NEEDED
HORIZONTAL_SCROLLBAR_NEVER
HORIZONTAL_SCROLLBAR_ALWAYS
I'm very new to Java and I'm trying to create a small program that reverses text (That part I've figured out).
Where I'm getting stuck on is my GUI, my envisioned plan for the gui is a window with a centered text field for user input then under it in the directly middle of the window a button that reverses the text from the above text box and outputs it in a text box below the button.
Right now I'm using JTextField boxes and after trying to make them look the way I want I'm getting the feeling that there's an easier way to do it, but I don't know it.
Here's my GUI class:
public class ReverseTextGUI extends ReverseRun implements ActionListener {
public static JFrame frame;
private JPanel northFlowLayoutPanel;
private JPanel centerFlowLayoutPanel;
private JPanel southFlowLayoutPanel;
private final JButton reverse = new JButton("Reverse");
private final JTextField userInput = new JTextField(50);
private final JTextField reverseOutput = new JTextField(50);
public void actionPerformed(ActionEvent e) {
reverse.addActionListener((ActionListener) reverse);
reverse.setActionCommand("Reverse");
if ("algorithm".equals(e.getActionCommand())) {
System.out.println("test");
}
}
public void initUI() {
northFlowLayoutPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
northFlowLayoutPanel.add(userInput);
userInput.setPreferredSize(new Dimension(150,100));
centerFlowLayoutPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
centerFlowLayoutPanel.add(reverse);
southFlowLayoutPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
southFlowLayoutPanel.setBorder(BorderFactory.createTitledBorder("Output text"));
southFlowLayoutPanel.add(reverseOutput);
reverseOutput.setPreferredSize(new Dimension(150,100));
JFrame frame = new JFrame("Backwardizer");
frame.setLayout(new BorderLayout()); // This is the default layout
frame.add(northFlowLayoutPanel, BorderLayout.PAGE_START);
frame.add(centerFlowLayoutPanel, BorderLayout.CENTER);
frame.add(southFlowLayoutPanel, BorderLayout.PAGE_END);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setSize(750, 500);
}
Any ideas how to either move the cursor to the start of the box (it shows up in the middle as of now) or a better way to accomplish what I'm trying to do?
For the reversing aspect, you can add the text from the first box to a string builder
StringBuilder rev = new StringBuilder(firstBox.getText());
String reversedText = rev.reverse().toString();
secondBox.setText(reversedText);
Something along those line should get the desired result if you nest it in the button action.
Any ideas how to either move the cursor to the start of the box (it shows up in the middle as of now) or a better way to accomplish what I'm trying to do?
JTextField#setCaretPosition, call this AFTER you've updated the text of the field
Make the field readonly, JTextField#setEditable and pass it false
Additionally, you could use a JList or JTextArea if you want to store multiple rows/lines of text
You should also avoid using setPreferredSize, see Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? for more details
I have created a JScrollPane with a JPanel inside it and I want to add JPanel/JLabel/Other objects after pressing the button. For example after three button presses I want to get something like this:
I tried myJPane.add(testLabel) with testlabel.setBounds()but no result, I don't want to use GridLayout because of the unchangeable sizes. I would like it if the added objects had different sizes - adjusted to the text content.
What should I use for it and how?
Thanks in advance.
Best regards,
Tom.
Here is a JPanel inside a JScrollPane that adds JLabels to it when pressing the button:
public class Example extends JFrame {
public Example() {
JPanel boxPanel = new JPanel();
boxPanel.setLayout(new BoxLayout(boxPanel, BoxLayout.PAGE_AXIS));
JTextField textField = new JTextField(20);
JButton sendButton = new JButton("Send");
sendButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JLabel label = new JLabel(textField.getText());
label.setOpaque(true);
label.setBackground(Color.RED);
boxPanel.add(label);
boxPanel.add(Box.createRigidArea(new Dimension(0,5)));
textField.setText("");
boxPanel.revalidate();
// pack();
}
});
JPanel southPanel = new JPanel();
southPanel.add(textField);
southPanel.add(sendButton);
add(new JScrollPane(boxPanel));
add(southPanel, BorderLayout.PAGE_END);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new Example();
}
}
The BoxLayout will stack the labels on top of each other.
Notes:
setOpaque(true) must be called on label for it to honor the background color.
Box.createRigidArea is used for creating gaps. Use it as you wish.
The call to revalidate() is imperative in order to display the new components immediately.
Calling pack() (on the JFrame) will resize it each time to fit all the new components. I just put it there for demonstration since the initial frame size is too small to display the initial components added.
I will use a BoxLayout, creating a vertical box, and after each button action, it will add a new JPanel to this box.
Example:
public class YourChat extends JPanel{
private JScrollPane sc;
private Box bv;
public YourChat(){
bv = Box.createVerticalBox();
sc = new JScrollPane(bv);
//your functions (panel creation, addition of listeners, etc)
add(sc);
}
//panel customized to have red backgroud
private class MyPanel extends JPanel(){
private JLabel label=new JLabel();
public MyPanel(String text){
setBackgroundColor(Color.red);
add(label);
}
}
//inside the action listener
public void actionPerformed(ActionEvent e) {
sc.add(new MyPanel(textField.getText()));
textField.setText("");
}
}
For extra information check on:
[https://docs.oracle.com/javase/tutorial/uiswing/layout/box.html]
See also the example
[http://www.java2s.com/Code/Java/Swing-JFC/VerticalandhorizontalBoxLayouts.htm]
Use BoxLayout if you want only add vertically, otherwise you can use FlowLayout for both directions.
This is the code I am struggling with. It is refusing to amend the JTextArea with the new text. I create the window and set it to visible in the main function of the project.
Thanks ahead.
EDIT:
By refusing, I mean the JTextArea will simply not display the text. It just stays empty. I'm not getting and error or exception. It is all logical.
class Window extends JFrame{
protected JTextArea text;
public Window() {
setTitle("Create a list of names");
setSize(500,400);
Container containerPane = getContentPane();
JPanel jp = new JPanel();
text = new JTextArea(10,50);
text.setPreferredSize(new Dimension(256,256) );
text.setEditable(false);
JScrollPane scrollText = new JScrollPane(text);
scrollText.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
jp.add(scrollText);
containerPane.add(jp, BorderLayout.CENTER);
text.append("Test");
}
public static void main(String[] args) {
Window w = new Window();
w.setVisible(true);
}
}
The column width of 50 is greater than the width of the frame so the added text appears offscreen. Reduce its value to fit the parent window
textArea = new JTextArea(10, 35);
Don't use setPrerredSize. Let the layout manager do its job and call pack after all components have been added.