I am trying to making a calculator.
Here the user can add multiple JTextFields to take his/her desired input with just one button click.
Now I want that the user will take the input in multiple JTextFields added by him and on clicking the Result button will show the sum of all. But I am always getting 0 as output.
Code:
public class Button extends JFrame {
private JPanel contentPane;
private JButton btnAdd;
private JButton btnResult;
private JTextField resultField;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Button frame = new Button();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Button() {
initComponents();
}
static JTextField field = null;
//static JTextField fields[] = new JTextField[10];
private static int y = 0;
ArrayList<String> arr = new ArrayList<String>();
int ans, sum = 0;
private void initComponents() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 527, 414);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
btnAdd = new JButton("Add");
btnAdd.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
field = new JTextField();
field.setBounds(45, y += 60, 284, 32);
field.setAlignmentX(Component.CENTER_ALIGNMENT);
contentPane.add(field);
contentPane.revalidate();
contentPane.repaint();
}
});
btnAdd.setBounds(170, 341, 89, 23);
contentPane.add(btnAdd);
btnResult = new JButton("Result");
btnResult.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < arr.size(); i++) {
arr.add(field.getText());
sum += Integer.parseInt(arr.get(i));
}
resultField.setText(String.valueOf(sum));
}
});
btnResult.setBounds(383, 306, 89, 23);
contentPane.add(btnResult);
resultField = new JTextField();
resultField.setBounds(361, 275, 129, 20);
contentPane.add(resultField);
resultField.setColumns(10);
}
}
Please help how can I find the correct output?
Suggestions:
Again, when you create a data-entry text field, add it to the GUI and add it to an ArrayList of the data entry field type.
Then in the result button's ActionListener, iterate through this list using a for loop.
Inside of the for loop, get the entry field, get its text (via .getText() if using a JTextField), parse it to number via Integer.parseInt(...), and add it to a sum variable that is initialized to 0 prior to the for loop. Then display the result after the loop.
Also,
Best to use JSpinners that use a SpinnerNumberModel such as JSpinner spinner = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1)); instead of JTextField for number entry. This will limit the user to entering numbers only, and won't allow non-numeric text entry, a danger inherent in your current design.
Having to add your entry fields by button may be an over-complication
But if it is necessary, then best to add the spinners (or text fields if you must) to a JPanel that uses a proper layout manager, such a new GridLayout(0, 1) (variable number of rows, 1 column) and then add that to a JScrollPane so that you can see as many fields as has been entered.
If using a JSpinner, then you don't even need a "calculate result" button, since if you add a ChangeListener to each JSpinner, you can calculate the result on the fly whenever a spinner has had its data changed.
e.g.,
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class Button2 extends JPanel {
private List<JSpinner> spinnerList = new ArrayList<>();
private JButton resultButton = new JButton("Result");
private JButton addEntryFieldBtn = new JButton("Add Entry Field");
private JTextField resultField = new JTextField(6);
private JPanel fieldPanel = new JPanel(new GridLayout(0, 1, 4, 4));
public Button2() {
resultField.setFocusable(false);
resultButton.addActionListener(e -> calcResult());
resultButton.setMnemonic(KeyEvent.VK_R);
addEntryFieldBtn.addActionListener(e -> addEntryField());
JPanel topPanel = new JPanel();
topPanel.add(addEntryFieldBtn);
topPanel.add(resultButton);
topPanel.add(new JLabel("Result:"));
topPanel.add(resultField);
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.add(fieldPanel, BorderLayout.PAGE_START);
JScrollPane scrollPane = new JScrollPane(centerPanel);
scrollPane.setPreferredSize(new Dimension(300, 300));
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(scrollPane);
}
private void calcResult() {
int sum = 0;
for (JSpinner spinner : spinnerList) {
sum += (int) spinner.getValue();
}
resultField.setText(String.valueOf(sum));
}
private void addEntryField() {
JSpinner spinner = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1));
spinner.addChangeListener(evt -> {
calcResult();
});
fieldPanel.add(spinner);
spinnerList.add(spinner);
revalidate();
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Button2 mainPanel = new Button2();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
Related
I have to make a scrollable list where I can add a panel with 3 labels many times.
I kind of made it work but the first panels are stretched and occupy all the area of the JScrollPane and I can't figure out how to fix this, I tried changing layouts many times but still didn't manage to fix it.
I want the added panel to occupy a fixed size but I can't figure this out. Example in this picture:
https://i.stack.imgur.com/LNznP.png
The one on the left is the one that I get and the one on the right (edited) is how I want it to work.
This is my first day of Swing so the code is very likely a mess, sorry in advance.
Here is the code:
public class MainWindow extends JFrame implements ActionListener{
private JPanel viewportPanel;
private JButton addButton,remButton;
private JScrollPane scrollPane;
private int counter = 0;
private JLabel dateLabel,dateLabel_1,dateLabel_2;
public MainWindow(boolean run) {
//BUTTONS
addButton = new JButton("Add");
addButton.setLocation(521, 11);
addButton.setSize(101, 100);
addButton.addActionListener(this);
remButton = new JButton("Remove");
remButton.setLocation(521, 122);
remButton.setSize(101, 100);
remButton.addActionListener(this);
//SCROLLPANE
scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setBounds(10, 11, 501, 211);
add(scrollPane);
//PANELS
viewportPanel = new JPanel(new GridLayout(0,1));
scrollPane.setViewportView(viewportPanel);
//FRAME
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 650, 273);
setResizable(false);
//setIconImage(new ImageIcon("epic.png").getImage());
setLayout(null);
if(run) setVisible(true);
add(addButton);
add(remButton);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == addButton) {
//LABELS
dateLabel = new JLabel("DATE");
dateLabel.setFont(new Font("Tahoma", Font.BOLD, 28));
dateLabel.setSize(500,500);
dateLabel_1 = new JLabel("LABEL1");
dateLabel_1.setFont(new Font("Tahoma", Font.BOLD, 22));
dateLabel_1.setBounds(10, 45, 481, 30);
dateLabel_2 = new JLabel("LABEL2");
dateLabel_2.setFont(new Font("Tahoma", Font.ITALIC, 22));
dateLabel_2.setBounds(10, 45, 481, 30);
//PANEL WITH ALL THE STUFF
JPanel componentPanel = new JPanel();
componentPanel.setLayout(new GridLayout(3, 1));
componentPanel.setMaximumSize(new Dimension(50,50));
componentPanel.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK));
componentPanel.setBackground(Color.gray);
componentPanel.add(dateLabel);
componentPanel.add(dateLabel_1);
componentPanel.add(dateLabel_2);
viewportPanel.add(componentPanel); //add panel with labels to viewportpanel
counter++;
}
if(e.getSource() == remButton) {
Component[] componentList = viewportPanel.getComponents();
int lastElement = (componentList.length);
viewportPanel.remove(--lastElement);
--counter;
}
viewportPanel.revalidate();
viewportPanel.repaint();
}
}
Some help would be amazing!
First off, never do this:
setLayout(null);
Next, if you want things compressed at the top of a container, then use a layout that does this. such as a BorderLayout with the compressed items placed into a JPanel (perhaps one that uses a GridLayout) that is placed BorderLayout.PAGE_START
Actually, it looks as if your best solution is to us a JList, one that uses a custom renderer that places your time JLabel and two text JLabels into a JPanel and displays this in the list. So let's explore that.
First create a class to hold the data that is displayed by the JList, which looks to be a date and two lines of text:
public class ListItem {
private LocalDate date;
private String text1;
private String text2;
public ListItem(LocalDate date, String text1, String text2) {
super();
this.date = date;
this.text1 = text1;
this.text2 = text2;
}
public LocalDate getDate() {
return date;
}
public String getText1() {
return text1;
}
public String getText2() {
return text2;
}
}
Then let's create a renderer that a JList can use to display the above information in a JPanel. This is more complicated and requires that the class create a JPanel that places the labels where we want them, perhaps using a GridLayout with 1 column and 3 rows, plus some gaps between the rows: setLayout(new GridLayout(3, 1, 2 * gap, 2 * gap));. The class must implement the ListCellRenderer<T> interface which has one method: public Component getListCellRendererComponent(...). Java will pass in the paramters into this method, including a ListItem value, and we will use that value to fill in the JLabels that we add into this JPanel. Edited to highlight selected items.
import java.awt.*;
import java.time.format.DateTimeFormatter;
import javax.swing.*;
import javax.swing.border.Border;
#SuppressWarnings("serial")
public class ListItemRenderer extends JPanel implements ListCellRenderer<ListItem> {
private static final Color LIGHT_BLUE = new Color(204, 255, 255);
private static final Color REDDISH_GREY = new Color(205, 126, 121);
private DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
private static final int GAP = 2;
private Border emptyBorder = BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP);
private Border blackBorder = BorderFactory.createLineBorder(Color.BLACK);
private Border redBorder = BorderFactory.createLineBorder(REDDISH_GREY, 2);
private JLabel dateLabel = new JLabel();
private JLabel text1Label = new JLabel();
private JLabel text2Label = new JLabel();
public ListItemRenderer() {
dateLabel.setFont(dateLabel.getFont().deriveFont(Font.BOLD, 14f));
text1Label.setFont(text1Label.getFont().deriveFont(Font.BOLD));
text2Label.setFont(text1Label.getFont().deriveFont(Font.ITALIC));
int gap = 2;
setLayout(new GridLayout(0, 1, 2 * gap, 2 * gap));
setBorder(BorderFactory.createCompoundBorder(emptyBorder, blackBorder));
add(dateLabel);
add(text1Label);
add(text2Label);
}
#Override
public Component getListCellRendererComponent(JList<? extends ListItem> list, ListItem value, int index,
boolean isSelected, boolean cellHasFocus) {
if (value != null) {
String dateText = dateFormatter.format(value.getDate());
dateLabel.setText(dateText);
text1Label.setText(value.getText1());
text2Label.setText(value.getText2());
} else {
dateLabel.setText("");
text1Label.setText("");
text2Label.setText("");
}
if (isSelected ) {
setBackground(LIGHT_BLUE);
setBorder(BorderFactory.createCompoundBorder(emptyBorder, redBorder));
} else {
setBackground(null);
setBorder(BorderFactory.createCompoundBorder(emptyBorder, blackBorder));
}
return this;
}
}
And now the main program that puts this all together, edited to show removing items:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class MainPanel extends JPanel {
DefaultListModel<ListItem> listModel = new DefaultListModel<>();
private JList<ListItem> jList = new JList<>(listModel);
private JScrollPane scrollPane = new JScrollPane(jList);
private JButton addButton = new JButton("Add");
private JButton removeButton = new JButton("Remove");
public MainPanel() {
jList.setPrototypeCellValue(new ListItem(LocalDate.now(),
"This is text 1 for testing. This is text 1 for testing. This is text 1 for testing",
"This is text 2 for testing. This is text 2 for testing. This is text 2 for testing"));
jList.setVisibleRowCount(4);
jList.setCellRenderer(new ListItemRenderer());
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 3, 3));
buttonPanel.add(addButton);
buttonPanel.add(removeButton);
addButton.setMnemonic(KeyEvent.VK_A);
removeButton.setMnemonic(KeyEvent.VK_R);
addButton.addActionListener(e -> addEvent());
removeButton.addActionListener(e -> removeEvent());
JPanel rightPanel = new JPanel();
rightPanel.add(buttonPanel);
int gap = 5;
setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
setLayout(new BorderLayout());
add(scrollPane);
add(rightPanel, BorderLayout.LINE_END);
}
private void removeEvent() {
int[] selectedIndices = jList.getSelectedIndices();
for (int i = selectedIndices.length - 1; i >= 0; i--) {
listModel.remove(selectedIndices[i]);
}
}
private void addEvent() {
// this adds random stuff to the JList
String text1 = "Some random text: " + randomText();
String text2 = "Some random text: " + randomText();
listModel.addElement(new ListItem(LocalDate.now(), text1, text2));
// TODO: change this so that it adds *real* data to the JList
}
private String randomText() {
Random random = new Random();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 2 + random.nextInt(3); i++) {
for (int j = 0; j < 3 + random.nextInt(5); j++) {
char c = (char) ('a' + random.nextInt('z' - 'a'));
builder.append(c);
}
builder.append(" ");
}
return builder.toString();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
Output would look like:
For some reason my scrollbar is appearing but it is not working. What is suppose to happen is using the scrollbar to scroll through the text of the textarea. Can somebody please explain why this isnt working?
import java.io.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class App extends JFrame{
private JPanel paneel;
public App(){
paneel = new AppPaneel();
setContentPane(paneel);
}
public static void main(String args[]){
JFrame frame = new App();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setTitle("Auto Clicker");
frame.setVisible(true);
}
}
class AppPaneel extends JPanel{
private JTextField delayField, xLocation, yLocation;
private JTextArea listArea;
private JButton addButton, saveButton, runButton;
private JScrollPane scroll;
public AppPaneel(){
setLayout(null);
delayField = new JTextField();
delayField.setBounds(10, 10, 85, 25);
delayField.setText("delay in ms");
xLocation = new JTextField();
xLocation.setBounds(105, 10, 85, 25);
xLocation.setText("X position");
yLocation = new JTextField();
yLocation.setBounds(200, 10, 85, 25);
yLocation.setText("Y position");
addButton = new JButton("Add");
addButton.setBounds(295, 10, 75, 24);
addButton.addActionListener(new AddHandler());
listArea = new JTextArea();
listArea.setBounds(10, 45, 360, 180);
scroll = new JScrollPane(listArea);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scroll.setBounds(370, 45, 20, 180);
saveButton = new JButton("Save");
saveButton.setBounds(10, 230, 85, 24);
runButton = new JButton("Run (F1)");
runButton.setBounds(105, 230, 85, 24);
runButton.addActionListener(new RunHandler());
add(delayField);
add(xLocation);
add(yLocation);
add(addButton);
add(listArea);
add(saveButton);
add(runButton);
add(scroll);
}
class AddHandler implements ActionListener{
public void actionPerformed(ActionEvent a){
listArea.setText(listArea.getText() + delayField.getText() + ", " + xLocation.getText() + ", " + yLocation.getText() + ", " + "click;" + "\n");
}
}
class RunHandler implements ActionListener{
private Robot bot;
private String text;
int foo = Integer.parseInt("1234");
public void actionPerformed(ActionEvent b) {
try{
text = listArea.getText();
bot = new Robot();
for(String line : text.split("\\n")){
int delay = Integer.parseInt((line.substring(0, 4)));
int xpos = Integer.parseInt((line.substring(6, 10)));
int ypos = Integer.parseInt((line.substring(12, 16)));
bot.mouseMove(xpos, ypos);
Thread.sleep(delay);
bot.mousePress(InputEvent.BUTTON1_MASK);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
}
}
catch (AWTException | InterruptedException e){
e.printStackTrace();
}
}
}
}
Don't use null layouts and setBounds as it is messing up your program. We tell folks time and time again not to do this for a reason -- by setting the JTextArea's bound you constrain its size so it won't grow when it needs to. The solution, as always -- learn and use the layout managers. Set the JTextArea's column and row properties but not its bounds, its size, or its preferred size.
Next don't do this: Thread.sleep(delay); in your Swing application as it will put the entire application to sleep. Use a Swing Timer instead for any delays. The tutorials can help you use this.
For a non-functional layout example:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class App2 extends JPanel {
private static final int GAP = 5;
private JTextField textField1 = new JTextField(GAP);
private JTextField textField2 = new JTextField(GAP);
private JTextField textField3 = new JTextField(GAP);
private JTextArea textArea = new JTextArea(15, 30);
public App2() {
JPanel topPanel = new JPanel(new GridLayout(1, 0, GAP, GAP));
topPanel.add(textField1);
topPanel.add(textField2);
topPanel.add(textField3);
topPanel.add(new JButton("Add"));
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JPanel bottomPanel = new JPanel(new GridLayout(1, 0, GAP, GAP));
bottomPanel.add(new JButton("Save"));
bottomPanel.add(new JButton("Run (F1)"));
bottomPanel.add(new JLabel(""));
bottomPanel.add(new JLabel(""));
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout(GAP, GAP));
add(topPanel, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Auto Clicker");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new App2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Your whole approach is wrong. You should not be using a null layout. For example:
scroll.setBounds(370, 45, 20, 180);
you are setting the width to 20. Well how to you expect the text area to display in 20 pixels? This is the problem with using setBounds(...), the random numbers you use have no meaning. Let a layout manager do its job. Also:
add(listArea);
The problem is that a component can only have a single parent. You originally created the JScrollPane with the text area which is correct.
But then you add the text area directly to the frame which removes it from the scroll pane so the scroll panel will no longer function.
Get rid of that statement and just add the scroll pane to the frame.
However, I don't recommend you use this as your final solution. I just wanted to mention the current problems so you hopefully understand the benefits of using layout managers and so that you don't try to share components again.
The proper solution is to use layout managers as has been suggested by the "Community Wiki". Then the layout manager will determine the size and location of each component so you don't need to worry about calculating your pixel values correctly.
For some reason the AddListener class below doesn't work, and I keep getting a number format exception. Could anyone please tell me the reason for this. It seems to me as if it should work.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class BabyCalculator extends JFrame {
JFrame theFrame = this;
JTextField addField; // Declaring this here so that you can access the variable from other places. MAKE SURE TO NOT DECLARE THIS AGAIN IN THE CONSTRUCTOR
JTextField totalField;
public BabyCalculator() {
//You set this up so that you can refer to the frame using the inner class below.
setDefaultCloseOperation(EXIT_ON_CLOSE);
setName("Baby Calculator");
setLayout(new GridLayout(3, 0));
//add
JLabel addLabel = new JLabel("Amount to add:");
addField = new JTextField(10);
JButton addButton = new JButton("add");
addButton.addActionListener(new AddListener());
//multiply
JLabel multiplyLabel = new JLabel("Amount to multiply:");
JTextField multiplyField = new JTextField(10);
JButton multiplyButton = new JButton("multiply");
//total
JLabel totalLabel = new JLabel("Total");
totalField = new JTextField(10);
totalField.setEditable(false);
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(new StopListener());
//Create Panels
JPanel topRow = new JPanel(new BorderLayout());
JPanel middleRow = new JPanel(new BorderLayout());
JPanel bottomRow = new JPanel(new FlowLayout());
//Add the top Row
topRow.add(addLabel, BorderLayout.WEST);
topRow.add(addField, BorderLayout.CENTER);
topRow.add(addButton, BorderLayout.EAST);
add(topRow);
middleRow.add(multiplyLabel, BorderLayout.WEST);
middleRow.add(multiplyField, BorderLayout.CENTER);
middleRow.add(multiplyButton, BorderLayout.EAST);
add(middleRow);
bottomRow.add(totalLabel);
bottomRow.add(totalField);
bottomRow.add(stopButton);
add(bottomRow);
pack();
setVisible(true);
}
public class AddListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String addFieldText = addField.getText();
String totalFieldText = totalField.getText();
double addAmount = Double.parseDouble(addFieldText);
double total = Double.parseDouble(totalFieldText);
total += addAmount;
totalField.setText(total + "");
}
}
//end class AddListener
public class StopListener implements ActionListener {//this is an inner class
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(theFrame, "You Clicked the stop button");
}//end class StopListener
}
public static void main(String[] args) {
JFrame newFrame = new BabyCalculator();
}
}
Note: The problem in the code is definitely related to the AddListener. Whenever I click the add button in the GUI I get an exception.
The problem is with the totalFieldText, it's default value is blank, meaning that when you try and convert to a double value, it causes a NumberFormatException
Try giving it a default value of 0, for example
totalField = new JTextField("0", 10);
You might also like to take a look at How to Use Spinners and How to Use Formatted Text Fields which will make your life easier
when i select something in combobox :
it show joptionPane Dialog box wiht two inputs.
here i want to first focusing amount field and then, when i entered in amount field its goes to no of App field then enter go to OK .
Here is my code for JOption Dialog:
JTextField xField = new JTextField(5);
JTextField yField = new JTextField(5);
JPanel myPanel = new JPanel();
myPanel.add(new JLabel("Amount:"));
myPanel.add(xField);
myPanel.add(Box.createHorizontalStrut(15)); // a spacer
myPanel.add(new JLabel("No of App:"));
myPanel.add(yField);
int value = 0;
xField.requestFocus();
int result = JOptionPane.showConfirmDialog(null, myPanel, "Please Enter Amount and No.of app", JOptionPane.OK_CANCEL_OPTION);
You simply try to focus a component which is not layout in a window.
Replace
xField.requestFocus();
by
SwingUtilities.invokeLater(new Runnable() {
public void run() {
xField.requestFocusInWindow();
}
});
You can create your own JDialog on the event that an item has changed to a new item. Then, you can get values entered in the JDialog and appropriately set the information in your parent. If you want to change the order of focus, use a custom focus policy. If you want to change the traversal focus key to the Enter key, you should re-map the key so that it reacts the same as the Tab key. There are several resources online and on this site with information on how to do that.
You should note that the default focus traversal policy is dependent on the order in which you add you elements to your content panel.
I have created a simple example for you on using a JDialog:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class RankSelection extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JTextField textField;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
RankSelection frame = new RankSelection();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public RankSelection() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JComboBox<String> comboBox = new JComboBox<String>();
comboBox.setModel(new DefaultComboBoxModel<String>(new String[] {"Slave", "Peasant", "Minion", "Knight", "Bishop", "Prince", "Coder King"}));
comboBox.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.SELECTED){
Amount amount = new Amount();
textField.setText(Integer.toString((Integer) amount.getStinkiness().getValue()));
}
}
});
contentPane.add(comboBox, BorderLayout.CENTER);
JLabel lblYourRank = new JLabel("Your Rank");
contentPane.add(lblYourRank, BorderLayout.NORTH);
JPanel panel = new JPanel();
contentPane.add(panel, BorderLayout.SOUTH);
JLabel lblYourStinkiness = new JLabel("Your Stinkiness:");
panel.add(lblYourStinkiness);
textField = new JTextField();
textField.setEditable(false);
textField.setEnabled(false);
textField.setText("0");
panel.add(textField);
textField.setColumns(10);
pack();
}
}
The custom JDialog:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class Amount extends JDialog {
private static final long serialVersionUID = 1L;
private final JPanel contentPanel = new JPanel();
private JSpinner amount;
private JSpinner stinkiness;
public Amount() {
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setModalityType(ModalityType.APPLICATION_MODAL);
getContentPane().setLayout(new BorderLayout());
contentPanel.setLayout(new FlowLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
JLabel lblAmount = new JLabel("Amount:");
amount = new JSpinner();
JLabel lblStinkiness = new JLabel("Stinkiness:");
stinkiness = new JSpinner();
contentPanel.add(lblAmount);
contentPanel.add(amount);
contentPanel.add(lblStinkiness);
contentPanel.add(stinkiness);
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
JButton okButton = new JButton("OK");
okButton.setActionCommand("OK");
buttonPane.add(okButton);
getRootPane().setDefaultButton(okButton);
okButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
pack();
setVisible(true);
}
public JSpinner getAmount() {
return amount;
}
public JSpinner getStinkiness() {
return stinkiness;
}
}
I am working on a project for my college course. I was just wondering if anyone knew how to add a scrollBar to a JTextArea. At present I have the GUI laid out correctly, the only thing missing is the scroll bar.
This is what the GUI looks like. As you can see on the second TextArea I would like to add the Scrollbar.
This is my code where I create the pane. But nothing seems to happen... t2 is the JTextArea I want to add it to.
scroll = new JScrollPane(t2);
scroll.setBounds(10,60,780,500);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
Any help would be great, thanks!
The Scroll Bar comes when your text goes beyond the bounds of your view area. Don't use Absolute Positioning, for such a small talk at hand, always prefer Layout Managers, do read the first para of the first link, to know the advantage of using a Layout Manager.
What you simply need to do is use this thingy :
JTextArea msgArea = new JTextArea(10, 10);
msgArea.setWrapStyleWord(true);
msgArea.setLineWrap(true);
JScrollPane msgScroller = new JScrollPane();
msgScroller.setBorder(
BorderFactory.createTitledBorder("Messages"));
msgScroller.setViewportView(msgArea);
panelObject.add(msgScroller);
Here is a small program for your understanding :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class JTextAreaScroller
{
private JTextArea msgArea;
private JScrollPane msgScroller;
private JTextArea logArea;
private JScrollPane logScroller;
private JButton sendButton;
private JButton terminateButton;
private Timer timer;
private int counter = 0;
private String[] messages = {
"Hello there\n",
"How you doing ?\n",
"This is a very long text that might won't fit in a single line :-)\n",
"Okay just to occupy more space, it's another line.\n",
"Don't read too much of the messages, instead work on the solution.\n",
"Byee byee :-)\n",
"Cheers\n"
};
private ActionListener timerAction = new ActionListener()
{
#Override
public void actionPerformed(ActionEvent ae)
{
if (counter < messages.length)
msgArea.append(messages[counter++]);
else
counter = 0;
}
};
private void displayGUI()
{
JFrame frame = new JFrame("Chat Messenger Dummy");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout(5, 5));
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(0, 1, 5, 5));
logArea = new JTextArea(10, 10);
logArea.setWrapStyleWord(true);
logArea.setLineWrap(true);
logScroller = new JScrollPane();
logScroller.setBorder(
BorderFactory.createTitledBorder("Chat Log"));
logScroller.setViewportView(logArea);
msgArea = new JTextArea(10, 10);
msgArea.setWrapStyleWord(true);
msgArea.setLineWrap(true);
msgScroller = new JScrollPane();
msgScroller.setBorder(
BorderFactory.createTitledBorder("Messages"));
msgScroller.setViewportView(msgArea);
centerPanel.add(logScroller);
centerPanel.add(msgScroller);
JPanel bottomPanel = new JPanel();
terminateButton = new JButton("Terminate Session");
terminateButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent ae)
{
if (timer.isRunning())
timer.stop();
else
timer.start();
}
});
sendButton = new JButton("Send");
bottomPanel.add(terminateButton);
bottomPanel.add(sendButton);
contentPane.add(centerPanel, BorderLayout.CENTER);
contentPane.add(bottomPanel, BorderLayout.PAGE_END);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
timer = new Timer(1000, timerAction);
timer.start();
}
public static void main(String... args)
{
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
new JTextAreaScroller().displayGUI();
}
});
}
}
Here is the outcome of the same :
The scroll bar by default will only be shown when the content overfills the available viewable area
You can change this via the JScrollPane#setVerticalScrollBarPolicy method, passing it ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS