Recently I've been trying to make a program that takes in a double in the form of a string. It then parses that to a double which goes to another class to be divided to a quarter or a half and then returns that output to a label.
I've been having an issue where when I click a button to actually submit what is inside the text field, the label doesn't change.
I've tried a lot of trial and error and I know I can change the text after doing new JLabel("test") for example. However, there seems to be an issue with my action listener for when the button is pushed. I can't tell if it's not seeing the button as being pushed.
NOTE: I am new to awt event things and swing as a whole, I usually operate just using the output terminal of visual studio code where it's just text and no graphics.
import javax.swing.*;
import java.awt.event.*;
import java.awt.Font;
import java.awt.Dimension;
public class MoneySorterRunner {
private MoneySorter sorter = new MoneySorter();
private String input = "0";
private double money = Double.parseDouble(input);
private static JTextField typeHere = new JTextField();
///labels num1-3 are the labels being changed
private static JLabel num1 = new JLabel(new MoneySorterRunner().sorter.divQuarter(new MoneySorterRunner().money));
private static JLabel num2 = new JLabel(new MoneySorterRunner().sorter.divQuarter(new MoneySorterRunner().money));
private static JLabel num3 = new JLabel(new MoneySorterRunner().sorter.divHalf(new MoneySorterRunner().money));
public static void main(String args[]) {
JFrame frame = new JFrame("Money Calculator - v0.1a");
JPanel panel = new JPanel();
JButton doThing = new JButton("Do a Thing");
doThing.setActionCommand("Do a Thing");
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 250);
frame.setLocation(200, 200);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
panel.setLayout(null);
frame.setVisible(true);
JLabel item1 = new JLabel("test");
JLabel item2 = new JLabel("test");
JLabel item3 = new JLabel("test");
item1.setFont(new Font("Arial", Font.PLAIN, 30));
item2.setFont(new Font("Arial", Font.PLAIN, 30));
item3.setFont(new Font("Arial", Font.PLAIN, 30));
num1.setFont(new Font("Arial", Font.PLAIN, 25));
num2.setFont(new Font("Arial", Font.PLAIN, 25));
num3.setFont(new Font("Arial", Font.PLAIN, 25));
Dimension size1 = item1.getPreferredSize();
Dimension size2 = item2.getPreferredSize();
Dimension size3 = item3.getPreferredSize();
panel.add(item1);
panel.add(item2);
panel.add(item3);
panel.add(num1);
panel.add(num2);
panel.add(num3);
panel.add(doThing);
panel.add(typeHere);
item1.setBounds(10, 10, size1.width + 3, size1.height);
item2.setBounds(190, 10, size2.width + 3, size2.height);
item3.setBounds(325, 10, size3.width + 3, size3.height);
num1.setBounds(50, 50, 50, 25);
num2.setBounds(200, 50, 50, 25);
num3.setBounds(350, 50, 50, 25);
doThing.setBounds(250, 150, 100, 25);
typeHere.setBounds(100, 150, 150, 25);
}
public void actionPerformed(ActionEvent event){
String check = event.getActionCommand();
if(check.equals("Do a Thing")){
input = typeHere.getText();
}
if(input != "0"){
num1.setText(sorter.divQuarter(money));
num2.setText(sorter.divQuarter(money));
num3.setText(sorter.divHalf(money));
}
}
}
For those who wanted the MoneySorter.java:
public MoneySorter(){
}
public String divQuarter(double moneyIn){
String answer = Double.toString(moneyIn);
return answer;
}
public String divHalf(double moneyIn){
String answer = Double.toString(moneyIn);
return answer;
}
}
I understand that your program is supposed to do the following.
User enters an amount of money in a JTextField and when she clicks on a JButton the JLabels show the entered amount in dollars, half-dollars and quarters (as per U.S. currency). My answer, below, is based on this understanding.
I don't know if making all the variables static is good or bad but I never use static class member variables in my Swing programs.
Here is my analysis of your code.
private double money = Double.parseDouble(input);
This line of code will be executed precisely once, when you launch class MoneySorterRunner. You want to do this every time the JButton is clicked, hence parsing the text entered into the JTextField should be performed in the actionPerformed method.
JPanel panel = new JPanel();
panel.setLayout(null);
It is almost never needed to set the layout manager to null. You can almost always find an appropriate layout manager or you can place one JPanel within another and use different layout managers for each JPanel in order to get the desired placement of components within the Swing application window.
JButton doThing = new JButton("Do a Thing");
doThing.setActionCommand("Do a Thing");
By default, the text of a JButton is also its action command so no need to explicitly set it.
frame.setLocation(200, 200);
frame.setLocationRelativeTo(null);
These are two different ways to set the location of the JFrame and they do not complement each other. Use one or the other, but not both.
frame.setVisible(true);
Only after you have created all the [GUI] components and added them to the JFrame should you make the JFrame visible. So this should be the last line of the code that creates your GUI.
doThing.setBounds(250, 150, 100, 25);
If you use a layout manager, you never need to call method setBounds.
if(input != "0"){
This is not the way to compare strings. Use method equals as you have done here
if(check.equals("Do a Thing")){
Here is my rewrite of your application. Note that since I could not find the code for class MoneySorter, in your question, I just created my own version of that class. The point is to show how to change the text of the JLabel after clicking on the JButton and not how to create the actual text to display.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class MoneySorterRunner implements ActionListener {
private MoneySorter sorter = new MoneySorter();
private JTextField typeHere = new JTextField();
private JLabel num1;
private JLabel num2;
private JLabel num3;
private void createAndShowGui() {
JFrame frame = new JFrame("Money Calculator - v0.1a");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(createLabels(), BorderLayout.PAGE_START);
frame.add(createForm(), BorderLayout.CENTER);
frame.setSize(550, 250);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel createForm() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 0));
panel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
typeHere = new JTextField(10);
panel.add(typeHere);
JButton doThing = new JButton("Do a Thing");
doThing.addActionListener(this);
panel.add(doThing);
return panel;
}
private static JLabel createLabel(String text) {
JLabel label = new JLabel(text);
label.setFont(new Font("Arial", Font.PLAIN, 25));
return label;
}
private JPanel createLabels() {
JPanel panel = new JPanel(new GridLayout());
num1 = createLabel("num1");
panel.add(num1);
num2 = createLabel("num2");
panel.add(num2);
num3 = createLabel("num3");
panel.add(num3);
return panel;
}
public static void main(String args[]) {
new MoneySorterRunner().createAndShowGui();
}
public void actionPerformed(ActionEvent event){
String check = event.getActionCommand();
if(check.equals("Do a Thing")){
String text = typeHere.getText();
if (!text.isEmpty()) {
double money = Double.parseDouble(text);
num1.setText(sorter.divQuarter(money));
num2.setText(sorter.divQuarter(money));
num3.setText(sorter.divHalf(money));
}
}
}
}
class MoneySorter {
public String divQuarter(double money) {
return "divQuarter(" + money + ")";
}
public String divHalf(double money) {
return "divHalf(" + money + ")";
}
}
This is how your GUI looked when I ran your original code (as posted in your question).
This is how the GUI looks when running the code in this answer.
After launching
After entering a value and clicking the JButton
It looks like you forgot to set the ActionListener. You should also change your method to another name, because your method has the same name as the actionPerformed of the ActionListener.
doThing.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new MoneySorterRunner().actionPerformedMethod(e);
}
});
You forgot to add the ActionListener.
In order to fix this, you need to do two things:
Add this statement to your code, preferably near where you create the button (so that it is easier to keep track). -
doThing.addActionListener(this);
When you write "public class", you also need this keyword: implements ActionListener - meaning your class (basically the first line) should look like:
public class MoneySorterRunner implements ActionListener
And that should make it work.
Related
I have a JTextArea where I want to allow the user to input any number of strings up to 100 but it could be less. When I set the JTextArea as I have in my code below where it is commented out (i.e. //tfResult= new JTextArea(10, 0);) and the user inputs ten lines of strings then my code runs exactly as expected and prints out what I need it to.
But if I try to input more of less lines I get
java.lang.ArrayIndexOutOfBoundsException
followed by the number of lines of user input, whether I have it declared with no bounds or as I have it commented out.
I am new to graphics in java and I can't figure out why this is happening and I have searched everywhere for answers. Do I have the bounds set wrong or have I declared the JTextArea wrong?
I also am trying to include a JScrollPane but I am having issues with that also as its not showing up.
I would really appreciate any help as I am struggling to solve this issue.
class Window {
JFrame windowFrame;
Panel bottomPanel;
JScrollPane scroll;
JTextArea tfResult;
Button btnPlayAgain;
Font font;
Window(int width, int height, String title)
{
windowFrame = new JFrame();
windowFrame.setTitle(title);
windowFrame.setBounds(0,0,width,height);
windowFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
windowFrame.setResizable(true);
windowFrame.setCursor(new Cursor(Cursor.HAND_CURSOR)); // setting cursor to hand
windowFrame.setLayout(null);
createBottomPanel();
windowFrame.add(bottomPanel);
//windowFrame.add(field.getCanvas());
windowFrame.setVisible(true);
}
private void createBottomPanel()
{
JButton b = new JButton("Compute");
bottomPanel = new Panel();
bottomPanel.setBackground(Color.PINK);
bottomPanel.setBounds(0,400,800,140);
bottomPanel.setLayout(null);
//*********
//tfResult= new JTextArea(10, 0);
tfResult= new JTextArea();
tfResult.setBounds(10,10,600,100);
tfResult.setFont(new Font("SansSerif", Font.BOLD, 16));
tfResult.setFocusable(true);
scroll = new JScrollPane(tfResult);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
btnPlayAgain = new Button("Compute");
btnPlayAgain.setBounds(620,10,150,100);
btnPlayAgain.setBackground(Color.RED);
btnPlayAgain.setFont(new Font("SansSerif", Font.BOLD, 24));
btnPlayAgain.setFocusable(true);
bottomPanel.add(tfResult);
bottomPanel.add(btnPlayAgain);
bottomPanel.add(b);
bottomPanel.add(scroll);
tfResult.setVisible(true);
scroll.setVisible(true);
btnPlayAgain.setVisible(true);
bottomPanel.setVisible(true);
btnPlayAgain.addActionListener(new ActionListener()
{
//#Override
public void actionPerformed(ActionEvent e)
{
//should include the code to genrate the output inside here
String input = tfResult.getText();
Mat xy;
xy = new Mat();
//String output = xy.getOutput(input).toString();
String output = xy.getOutput(input);
//String output = Output(input);
tfTarget.setText(output);
}
});
}
}
I went ahead and created the following GUI that allows you to enter data with a JTextArea.
The first thing I did was start my Swing application with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
Next, I created a JFrame. Then I created a JPanel with a BorderLayout. The JTextArea is inside of a JScrollPane, which is then placed inside of the center of a JPanel.
The JButton is placed after the last line of the JPanel.
Here's the complete runnable code, otherwise known as a minimal runnable example.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class JTextAreaInputGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new JTextAreaInputGUI());
}
private JTextArea textArea;
#Override
public void run() {
JFrame frame = new JFrame("JTextArea Input GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
textArea = new JTextArea(10, 40);
JScrollPane scrollPane = new JScrollPane(textArea);
panel.add(scrollPane, BorderLayout.CENTER);
JButton button = new JButton("Submit");
button.addActionListener(new ButtonListener());
panel.add(button, BorderLayout.AFTER_LAST_LINE);
return panel;
}
public class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
System.out.println(textArea.getText().trim());
}
}
}
I am trying to show a text saying "The background is (color)" whenever I press a button that has the name of the color written on it but the text doesn't show up.
How it is supposed to be:
but mine is like this:
Here is my code:
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ThreeBtn extends JFrame {
private JButton btnRed;
private JButton btnGreen;
private JButton btnBlue;
public class ButtonListener implements ActionListener {
public void actionPerformed (ActionEvent e) {
if (e.getSource() == btnRed) {
(getContentPane()).setBackground(Color.red);
JLabel label = new JLabel("빨간색 배경입니다."); //it means "The background is red" in Korean label.setFont(new Font("Serif", Font.BOLD, 25));
label.setForeground(Color.yellow);
(getContentPane()).add(label);
}
else if(e.getSource()==btnGreen) {
(getContentPane()).setBackground(Color.green);
JLabel label = new JLabel("초록색 배경입니다."); //it means "The background is green" in Korean
label.setFont(new Font("Serif", Font.BOLD, 25));
label.setForeground(Color.yellow);
(getContentPane()).add(label);
}
else if(e.getSource()==btnBlue) {
(getContentPane()).setBackground(Color.blue);
JLabel label = new JLabel("파란색 배경입니다."); //it means "The background is blue" in Korean
label.setFont(new Font("Serif", Font.BOLD, 25));
label.setForeground(Color.yellow);
(getContentPane()).add(label);
}
}
}
public ThreeBtn() {
setSize(300, 200);
setTitle("Three Button Example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container cPane = getContentPane();
cPane.setLayout(new FlowLayout());
btnRed = new JButton("RED");
btnGreen = new JButton("GREEN");
btnBlue = new JButton("Blue");
ButtonListener listener = new ButtonListener();
btnRed.addActionListener(listener);
btnGreen.addActionListener(listener);
btnBlue.addActionListener(listener);
cPane.add(btnRed);
cPane.add(btnGreen);
cPane.add(btnBlue);
}
public static void main(String[] args) {
(new ThreeBtn()).setVisible(true);
}
}
I am wondering if I used JLabel in a wrong way in the ActionListener but I can't figure it out.
I would really appreciate your help.
When adding or deleting components to your GUI on runtime, you have to tell Swing that you did so. To do this, you should use revalidate() and repaint() on the container where the modification happened.
However, in your case, you don't actually need to always add a new JLabel on runtime, as you can simply do that when setting up the GUI, and only modifying the label that is already there. By doing it this way, you avoid having to revalidate() and repaint() (and it is also easier and cleaner this way).
I updated your code and did the following modificiations:
Moved the declaration and initialization of the JLabel out of the actionPerformed(), so you don't have to create a new JLabel each time a button is pressed. Now, only the text is changed. (A side effect of this change is, that the revalidate() and repaint() are actually not needed anymore, as no more component is added during runtime)
Started the GUI on the Event Dispatch Thread via SwingUtilities.invokeLater().
Usually it is also good practice in Swing to not create a subclass of JFrame if this is not specifically needed (like in your case). The better approach is to subclass JPanel, add the necessary components there, override getPreferredSize() and then add this to the JFrame. I have not included this change here, since it might have caused too much confusion.
Updated code:
public class ThreeBtn extends JFrame {
private JButton btnRed;
private JButton btnGreen;
private JButton btnBlue;
private JLabel label;
public class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
Container contentPane = getContentPane();
if (e.getSource() == btnRed) {
contentPane.setBackground(Color.red);
label.setText("red in korean");
} else if (e.getSource() == btnGreen) {
contentPane.setBackground(Color.green);
label.setText("green in korean");
} else if (e.getSource() == btnBlue) {
contentPane.setBackground(Color.blue);
label.setText("blue in korean");
}
}
}
public ThreeBtn() {
setSize(300, 200);
setTitle("Three Button Example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container cPane = getContentPane();
cPane.setLayout(new FlowLayout());
btnRed = new JButton("RED");
btnGreen = new JButton("GREEN");
btnBlue = new JButton("BLUE");
label = new JLabel("");
label.setFont(new Font("Serif", Font.BOLD, 25));
label.setForeground(Color.yellow);
ButtonListener listener = new ButtonListener();
btnRed.addActionListener(listener);
btnGreen.addActionListener(listener);
btnBlue.addActionListener(listener);
cPane.add(btnRed);
cPane.add(btnGreen);
cPane.add(btnBlue);
cPane.add(label);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> (new ThreeBtn()).setVisible(true));
}
}
Output:
This now works as per your requirements with the used FlowLayout. However, you may use another layout manager (or combine different ones) if you plan on doing more with it.
The Dimensions of the frame and panel where small so they did not show the text when you pressed the buttons.
Dimension size = label.getPreferredSize();
label.setBounds(150, 100, size.width, size.height);
I dont know if there are any rules for your program, but I would suggest, just limiting your if statements in ActionListener to the point where you set the foreground. Then make your JLabel object a class variable, and add the JLabel in the constructor. Here is the full edited code:
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ThreeBtn extends JFrame {
private static final long serialVersionUID = 1L;
private JButton btnRed;
private JButton btnGreen;
private JButton btnBlue;
private JLabel text = new JLabel();
public class ButtonListener implements ActionListener {
public void actionPerformed (ActionEvent e) {
if (e.getSource() == btnRed) {
(getContentPane()).setBackground(Color.red);
text.setText("red"); //it means "The background is red" in Korean
text.setFont(new Font("Serif", Font.BOLD, 25));
text.setForeground(Color.yellow);
}
else if(e.getSource()==btnGreen) {
(getContentPane()).setBackground(Color.green);
text.setText("green"); //it means "The background is green" in Korean
text.setFont(new Font("Serif", Font.BOLD, 25));
text.setForeground(Color.yellow);
}
else if(e.getSource()==btnBlue) {
(getContentPane()).setBackground(Color.blue);
text.setText("blue"); //it means "The background is blue" in Korean
text.setFont(new Font("Serif", Font.BOLD, 25));
text.setForeground(Color.yellow);
(getContentPane()).add(text);
}
}
}
public ThreeBtn() {
setSize(300, 200);
setTitle("Three Button Example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container cPane = getContentPane();
cPane.setLayout(new FlowLayout());
btnRed = new JButton("RED");
btnGreen = new JButton("GREEN");
btnBlue = new JButton("Blue");
ButtonListener listener = new ButtonListener();
btnRed.addActionListener(listener);
btnGreen.addActionListener(listener);
btnBlue.addActionListener(listener);
cPane.add(btnRed);
cPane.add(btnGreen);
cPane.add(btnBlue);
cPane.add(text);
}
public static void main(String[] args) {
(new ThreeBtn()).setVisible(true);
}
}
For my assignment I have to create a frame-based application that allows the user to specify RGB values in three text fields, and, when a button is pressed, displays my name and registration number in the chosen colour. I believe all my code is correct so far however it appears that there is an issue in the part that changes the colour.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ex1 extends JFrame {
JLabel label;
JTextField r, g, b;
public ex1() {
//panels to hold information
JPanel bottomPanel = new JPanel();
JPanel upperPanel = new JPanel();
//fields that will hold the colour values
r = new JTextField("Red", 10);
g = new JTextField("Green", 10);
b = new JTextField("Blue", 10);
//add to frame
bottomPanel.add(r);
bottomPanel.add(g);
bottomPanel.add(b);
add(bottomPanel, BorderLayout.SOUTH);
add(upperPanel, BorderLayout.CENTER);
label = new JLabel("CE203 Assignment 1, submitted by:");
label.setForeground(new Color(255, 0, 0));
JButton button = new JButton("Enter");
upperPanel.add(label);
bottomPanel.add(button);
button.addActionListener(new ButtonHandler(this));
}
public JLabel getLabel() {
return label;
}
class ButtonHandler implements ActionListener {
private ex1 assignment1;
public ButtonHandler(ex1 assignment1) {
this.assignment1 = assignment1;
}
#Override
public void actionPerformed(ActionEvent e) {
int r1 = Integer.parseInt(assignment1.r.getText());
int g1 = Integer.parseInt(assignment1.g.getText());
int b1 = Integer.parseInt(assignment1.b.getText());
assignment1.getLabel().setForground(new Color(r1, g1, b1));
}
}
public static void main(String[] args) {
JFrame frame = new ex1();
frame.setSize(400, 400);
frame.setDefaultCloseOperation(ex1.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
If anyone could show me what is going wrong and how I can fix it, it would be greatly appreciated.
Don't ignore the IDE when it is reporting compilation errors!
assignment1.getLabel().setForground(new Color(r1, g1, b1));
Should be:
assignment1.getLabel().setForeground(new Color(r1, g1, b1));
Other tips
Instead of:
frame.setSize(400, 400); // random guess at required size
have:
frame.pack(); // calculates the required size
In real world programming, the user would lynch a programmer for offering 3 text fields when one JColorChooser is vastly superior.
I have a class called 'Panel' that extends JPanel and it is inside another class called 'Main'. The constructor instantiates JFrame, and all the GUI components, and sets it all up, such as size.
The class 'Panel' which extends JPanel has a method public void paintComponent(Graphics g){} and inside it I added a few JButtons and used g.drawString's.
Then in the 'Main' class, I added the 'Panel' to the JFrame.
My question is, I am trying to implement an actionListener to a button added inside the 'Panel' class. The actionListener function would add more buttons and use g.drawString's as well. Now where would I place the ActionListener in order to do so? How can I use g.drawString for a particular panel and the g.drawString line is inside another class, which is the ActionListener class? I would need to use Graphics g of paintComponent inside the actionPerformed.
Thank you!
EDIT -
CODE EXAMPLE:
public class Main{
private JFrame jf;
private JTextField jtf1;
private JTextField jtf2;
private Panel p;
private JComboBox jcb1;
private JComboBox jcb2;
private JButton button;
private Object options[];
//ActionListener Variables
private int string1 = 150;
private int string2 = 150;
private int yJtf1 = 150;
private int yJtf2 = 160;
private int cb1 = 140;
private int cb2 = 165;
private int count = 0;
public Main(){
jf= new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(700, 700);
p = new Panel();
jtf1 = new JTextField("", 20);
jtf2= new JTextField("", 20);
Object options[] = {""};
jcb1 = new JComboBox(tools);
jcb2 = new JComboBox(tools);
button = new JButton("+");
jf.add(p);
jf.setVisible(true);`
}
public class Panel extends JPanel{
public Panel(){
this.setLayout(null);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
/*button.addActionListener(new ActionListener(){ //Would this work or should the ActionListener be a class as shown below?
public void actionPerformed(ActionEvent e){
if(count < 3){ //Won't be allowed to add anymore after 3 times
string1 += 50;
string2 += 50;
jtf1 += 50;
jtf2 += 50;
cb1 += 50;
cb2 += 45;
//Would like to add the following components to the 'Panel' (which is a JPanel) whenever the JButton 'button' already added to 'Panel' is clicked.
p.add(jtf1); //Would doing p.add really add to the panel when the ActionListener is called?
jtf1.setBounds(60, yJtf1, 50, 40);
p.add(jtf2);
jtf2.setBounds(60, yJtf2, 50, 40);
add(jcb1);
jcb1.setBounds(250, cb1, 50, 40);
add(left2);
jcb2.setBounds(250, cb2, 50, 40);
Font font = new Font("TimesRoman", Font.BOLD, 18);
g.setFont(font); //Getting error on 'g' regardless
g.drawString("Hi", 15, string1); //This is the main problem, how would I be able to add this strings to the 'Panel' (which is a JPanel)
g.drawString("There", 330, string1);
}
count++;
}
});*/
add(jtf1);
jtf1.setBounds(100, 30, 120, 30);
add(jtf2);
ljtf2.setBounds(100, 60, 120, 30);
add(button);
plusButton.setBounds(200,150, 50, 50);
//button.addActionListener(new ButtonClicked()); if doing ActionListener via class like below
add(jcb1);
jcb1.setBounds(300, 350, 100, 50);
add(ljcb2);
jcb2.setBounds(300, 350, 100, 25);
Font font = new Font("Arial", Font.BOLD, 12);
g.setFont(font);
g.drawString("Item:", 40, 45);
g.drawString("Cost:", 40, 75);
}
}
public static void main(String [] args){
new Main();
}
class ButtonClicked implements ActionListener{ //Action Listener: The follow is what I am trying to implement
public void actionPerformed(ActionEvent ae){
if(count < 3){ //Won't be allowed to add anymore after 3 times
string1 += 50;
string2 += 50;
jtf1 += 50;
jtf2 += 50;
cb1 += 50;
cb2 += 45;
//Would like to add the following components to the 'Panel' (which is a JPanel) whenever the JButton 'button' already added to 'Panel' is clicked.
p.add(jtf1); //Would doing p.add really add to the panel when the ActionListener is called?
jtf1.setBounds(60, yJtf1, 50, 40);
p.add(jtf2);
jtf2.setBounds(60, yJtf2, 50, 40);
mp.add(jcb1);
jcb1.setBounds(250, cb1, 50, 40);
mp.add(left2);
jcb2.setBounds(250, cb2, 50, 40);
Font font = new Font("TimesRoman", Font.BOLD, 18);
g.setFont(font);
g.drawString("Hi", 15, string1); //This is the main problem, how would I be able to add this strings to the 'Panel' (which is a JPanel)
g.drawString("There", 330, string1);
}
count++;
}
}
}
I would need to use Graphics g of paintComponent inside the actionPerformed."`
No, you wouldn't since Swing graphics is passive not active. The Graphics object would reside in the JPanel's paintComponent method and would be passed to it from the JVM when it and only it calls the paintComponent method. The actionPerformed method would then change the value of a String variable or perhaps an ArrayList<String>, call repaint(), and then the JPanel's paintComponent method would use the changed String to draw the appropriate text.
If you need more specific help, consider telling us a few more details and posting a minimal example program.
Edit
On review of your code I have several suggestions:
Please try to fix your code a bit so that it is either compilable or as close to compilable as possible.
Never add components or do anything but painting inside of your paintComopnent(...) method. You don't have full control over when or even if that method will be called, and placing something in inside of this method will result in unwanted side effects, like combo boxes that simply won't work.
If you ever wanted text shown in your program, you can always add a JLabel.
Your program uses null layout and setBounds(...) something that results in a rigid GUI that may look good on one system but will usually look poor on any other system or screen resolution. Also programs created this way are very hard to debug, maintain and upgrade. Instead use the layout managers as this is what they excel at: at creating complex flexible GUI's that can be enhanced and changed easily.
Edit
I'm guessing what you really want to do, and that possibly is to add more components to allow the user to enter more data into the GUI. You also want to add text perhaps to guide the user in what the purpose of the components may be. If this is so, then the best solution is not to add Strings to the GUI in paintComponent but rather to add Strings/Components in an organized fashion with the Strings being displayed in JLabels, and the components and the labels all held in a JPanel or JPanels, and added to the GUI using layout managers.
For example, if you want the user to add data in two JTextfields and have two JComboBoxes, and then allow the user to add 3 more of these guys if need be, a GUI could look something like this:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class Main2 extends JPanel {
private List<DataPanel> dataPanelList = new ArrayList<>();
private JPanel dataPanelHolder = new JPanel();
public Main2() {
DataPanel dataPanel = new DataPanel();
dataPanelList.add(dataPanel);
setLayout(new BorderLayout());
dataPanelHolder.setLayout(new BoxLayout(dataPanelHolder, BoxLayout.PAGE_AXIS));
dataPanelHolder.add(dataPanel);
JPanel innerBorderLayoutPanel = new JPanel(new BorderLayout());
innerBorderLayoutPanel.add(dataPanelHolder, BorderLayout.PAGE_START);
JScrollPane scrollPane = new JScrollPane(innerBorderLayoutPanel);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
int w = dataPanel.getPreferredSize().width;
int h = dataPanel.getPreferredSize().height * 4;
Dimension viewPortSize = new Dimension(w, h);
scrollPane.getViewport().setPreferredSize(viewPortSize);
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));
buttonPanel.add(new JButton(new AddDatatAction("Add")));
buttonPanel.add(new JButton(new ExitAction("Exit", KeyEvent.VK_X)));
add(scrollPane, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.PAGE_END);
}
private class AddDatatAction extends AbstractAction {
private int maxCount = 4;
public AddDatatAction(String name) {
super(name);
int mnemonic = (int)name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
if (dataPanelList.size() < maxCount) {
DataPanel dataPanel = new DataPanel();
dataPanelList.add(dataPanel);
dataPanelHolder.add(dataPanel);
dataPanelHolder.revalidate();
dataPanelHolder.repaint();
}
}
}
private class ExitAction extends AbstractAction {
public ExitAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
Window win = SwingUtilities.getWindowAncestor(Main2.this);
win.dispose();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Main2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Main2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class DataPanel extends JPanel {
private static final String[] TOOLS = {"Tool 1", "Tool 2", "Tool 3", "Tool 4"};
private static final String[] FIELD_LABELS = {"Item", "Cost"};
private static final String[] COMBO_LABELS = {"Foo", "Bar"};
private JTextField[] fields = new JTextField[FIELD_LABELS.length];
private List<JComboBox<String>> comboList = new ArrayList<>();
public DataPanel() {
setBorder(BorderFactory.createTitledBorder("Data"));
setLayout(new GridBagLayout());
for (int i = 0; i < FIELD_LABELS.length; i++) {
add(new JLabel(FIELD_LABELS[i]), createGbc(0, i));
fields[i] = new JTextField(10);
add(fields[i], createGbc(1, i));
JComboBox<String> combo = new JComboBox<>(TOOLS);
comboList.add(combo);
add(combo, createGbc(2, i));
add(new JLabel(COMBO_LABELS[i]), createGbc(3, i));
}
}
public static GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
int ins = 4;
gbc.insets = new Insets(ins, ins, ins, ins);
return gbc;
}
}
And could look like:
one datapanel added
four added:
I want to create a jtext field with a definite size, but I would like it to expand like a scroll pane when the input grows. Here is what I have so far:
JButton b,b1;
JLabel j1,j2,j3;
JTextField t1,t2;
public Window(){
super("frame");
//new Thread(this).start();
b=new JButton("Click");
j1=new JLabel("VALUE1");
t1=new JTextField(30);
j2=new JLabel("VALUE2");j3=new JLabel(" ");
t2=new JTextField(30);
j1.setBounds(100, 50, 150, 50);
t1.setBounds(150, 50, 200, 50);
j2.setBounds(200, 150, 250, 150);
t2.setBounds(250, 150, 200, 50);j3.setBounds(300, 150, 250, 150);
b.setBorder(new LineBorder(Color.black));
b.setBackground(Color.black);
b.setForeground(Color.white);
b1=new JButton("Exit");
super.setSize(300,300);
super.setLocation(250,150);
super.setLayout(new FlowLayout());
super.setVisible(true);
add(j1);add(t1);add(j2);add(t2); add(j3);
add(b);add(b1);
b.addActionListener(this);
b1.addActionListener(this);
If you dont want to use JScrollPane this is something you are looking for -
I have created a sample program to auto resize the JTextField size
i.e if text is added its size increases and if text is deleted its size is reduced.
I have used KeyListener's - keyTyped event to detect and update the text field size.
You can add document listener too to do the same thing.
Here is my sample code -
import java.awt.Dimension;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class AutoResizeTest
{
public AutoResizeTest(){
JFrame frame = new JFrame("Auto-Resizable TextField");
frame.setLayout(null);
MyCustomTextField expandableText = new MyCustomTextField(20);
expandableText.setBounds(10, 10, 200, 30);
expandableText.setPreferredSize(new Dimension(200,30));
expandableText.setMaximumSize(new Dimension(600,30));
frame.add(expandableText);
frame.setBounds(100,100,700,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args)
{
AutoResizeTest test = new AutoResizeTest();
}
class MyCustomTextField extends javax.swing.JTextField{
private int originallimit;
int previousLength;
int length;
public MyCustomTextField(int limit){
previousLength=0;
originallimit = limit;
this.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
JTextField textField = (JTextField) e.getSource();
length = textField.getText().length();
if(length >= originallimit){
if(length > previousLength){
textField.setSize(new Dimension(textField.getWidth()+10, textField.getHeight()));
}
else{
if(length < previousLength)
textField.setSize(new Dimension(textField.getWidth()-10, textField.getHeight()));
}
previousLength = length;
}else{
textField.setSize(textField.getPreferredSize());
}
}
});
}
}
}
In this code I have increamented/reduced the size by 10. You can put your desired value.
Hope that helps you.
Place the TextArea in a seperate JPanel with BorderLayout and in the center and the panel automatically expands, when the content increases.
textArea = new JTextArea(2, WIDTH);
textArea.setLineWrap(true);
textArea.getDocument().putProperty("filterNewlines", Boolean.TRUE);
The default size of the JTextField will be set and provide a ScrollPane to JTextField which will make field to expand if necessary.
Try the following
JTextField jtext = new JTextField(pane);
JScrollPane scroll = new JScrollPane(jtext);