Small error I can't manage to do. So right now my program GUI looks like this:
Now there is a TextField under the 'Mark' column were the user can input their data. I also want the same for the weight section were I want to insert a TextField right under 'Weight' column.
However when I try and put in a TextField, both the the Textfields turn like this when the window is small:
and this when the window is enlarged:
How can I make it so that there is a textfield under Mark AND Weight?
Code:
public class Gradeanalysis implements ActionListener {
public void actionPerformed (ActionEvent e){
GridBagConstraints gbc = new GridBagConstraints();
//Adding the JPanels. Panel for instructions
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
//JLabel for the Instructions.
JLabel label = new JLabel("<html> Instructions: Type in the grades you’ve received, along with the weights they’ll have in the determination of your overall average. <br> After you press ‘Calculate’, the results will show your average so far. <br> Every grade you enter must be a non-negative number, and every percentage/weight you enter must be a positive number :)</html>");
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = 2;
gbc.gridy = 0;
panel.add(label, gbc);
//JLabel1 for Assingment/Grade/Weight(Percent)
JLabel label1 = new JLabel("<html><pre>Assingment\t\t\t\t\t Mark\t\t\t\t\tWeight</pre></html>");
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.NORTH;
panel.add(label1, gbc);
//JLabel Numbers for the number list of assingments at the side.
JLabel numbers = new JLabel("1");
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.NORTH;
gbc.weighty = 1;
panel.add(numbers, gbc);
//JTextfield for Mark
JTextField mark = new JTextField(2);
gbc.fill = GridBagConstraints.NONE;
gbc.gridy = 2;
panel.add(mark, gbc);
//JTextfield for Weight
JTextField weight = new JTextField(2);
gbc.gridx = 2;
panel.add(weight, gbc);
//New frame set
JFrame frame = new JFrame("Grade Calculator-- ");
frame.setVisible(true);
frame.setSize(750,700);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.add(panel);
}
}
Thanks for reading.
Here's the GUI I created.
I don't know where your main method is, but you must always start a Swing application with a call to the SwingUtilities invokeLater method. The invokeLater method puts the creation and execution of the Swing components on the Event Dispatch thread (EDT).
When I use the GridBagLayout, I use the addComponent method I created to create a unique GridBagConstraints for each Swing component. I don't like to remember defaults.
The order of the JFrame methods is extremely important. Memorize the order of the JFrame methods in this example.
I put the instructions in a JTextArea. This way, the instruction text splits based on the size of the JTextArea. There's no need to hard code the line breaks with HTML.
Here's the code.
package com.ggl.testing;
import java.awt.Component;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class GradeAnalysis implements Runnable {
private static final Insets normalInsets = new Insets(10, 10, 0, 10);
private static final Insets finalInsets = new Insets(10, 10, 10, 10);
public static void main(String[] args) {
SwingUtilities.invokeLater(new GradeAnalysis());
}
@Override
public void run() {
JFrame frame = new JFrame("Grade Calculator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel());
frame.pack();
frame.setVisible(true);
}
private JPanel createMainPanel() {
GridBagConstraints gbc = new GridBagConstraints();
// Adding the JPanels. Panel for instructions
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
int gridy = 0;
// JLabel for the Instructions.
JTextArea instructionTextArea = new JTextArea(5, 30);
instructionTextArea.setEditable(false);
instructionTextArea.setLineWrap(true);
instructionTextArea.setWrapStyleWord(true);
instructionTextArea.setText(getInstructions());
JScrollPane instructionScrollPane = new JScrollPane(instructionTextArea);
addComponent(panel, instructionScrollPane, 0, gridy++, 3, 1,
finalInsets, GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL);
// JLabels for Assignment/Grade/Weight(Percent)
JLabel label1 = new JLabel("Assignment");
label1.setHorizontalAlignment(JLabel.CENTER);
addComponent(panel, label1, 0, gridy, 1, 1, finalInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
JLabel label2 = new JLabel("Mark");
label2.setHorizontalAlignment(JLabel.CENTER);
addComponent(panel, label2, 1, gridy, 1, 1, finalInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
JLabel label3 = new JLabel("Weight");
label3.setHorizontalAlignment(JLabel.CENTER);
addComponent(panel, label3, 2, gridy++, 1, 1, finalInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
// JLabel Numbers for the number list of assignments at the side.
JLabel number = new JLabel("1");
number.setHorizontalAlignment(JLabel.CENTER);
addComponent(panel, number, 0, gridy, 1, 1, normalInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
// JTextfield for Mark
JTextField mark = new JTextField(20);
mark.setHorizontalAlignment(JLabel.CENTER);
addComponent(panel, mark, 1, gridy, 1, 1, normalInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
// JTextfield for Weight
JTextField weight = new JTextField(20);
weight.setHorizontalAlignment(JLabel.CENTER);
addComponent(panel, weight, 2, gridy++, 1, 1, normalInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
return panel;
}
private String getInstructions() {
return "Instructions: Type in the grades you’ve received, along with the weights "
+ "they’ll have in the determination of your overall average. After you "
+ "press ‘Calculate’, the results will show your average so far. Every "
+ "grade you enter must be a non-negative number, and every "
+ "percentage/weight you enter must be a positive number :)";
}
private void addComponent(Container container, Component component,
int gridx, int gridy, int gridwidth, int gridheight, Insets insets,
int anchor, int fill) {
GridBagConstraints gbc = new GridBagConstraints(gridx, gridy,
gridwidth, gridheight, 1.0D, 1.0D, anchor, fill, insets, 0, 0);
container.add(component, gbc);
}
}
I suggest that you
- Don't use
setBounds(...)
on any component or GUI
- Same for
setSize(...)
- Instead nest JPanels each using its own layouts to achieve a pleasing and easy to manage layout and GUI.
- Consider putting your intro text into a JTextArea. If you want it to look like a JLabel, you can take out the background color and borders.
- Best of all would be to display the tabular data in a JTable, and for that you'd want to create your own table model, one based on the AbstractTableModel and that uses an Assignment object for each row.
An example without the JTable:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class GradeAnalysis2 extends JPanel {
private static final int PREF_H = 400;
private static final String DISPLAY_TEXT = "Instructions: "
+ "Type in the grades you’ve received, along with the "
+ "weights they’ll have in the determination of your "
+ "overall average.\n"
+ "After you press ‘Calculate’, the results will show "
+ "your average so far.\n"
+ "Every grade you enter must be a non-negative number, "
+ "and every percentage/weight you enter must be a "
+ "positive number :)";
private JTextArea displayArea = new JTextArea(5, 50);
private GradeTablePanel gradeTablePanel = new GradeTablePanel();
public GradeAnalysis2() {
displayArea.setText(DISPLAY_TEXT);
displayArea.setWrapStyleWord(true);
displayArea.setLineWrap(true);
displayArea.setEditable(false);
displayArea.setFocusable(false);
displayArea.setBorder(null);
displayArea.setBackground(null);
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.add(gradeTablePanel, BorderLayout.PAGE_START);
centerPanel.add(Box.createGlue(), BorderLayout.CENTER);
JScrollPane scrollPane = new JScrollPane(centerPanel);
JPanel btnPanel = new JPanel();
btnPanel.add(new JButton(new AddAssignmentAction("Add")));
setLayout(new BorderLayout());
add(displayArea, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
@Override
public Dimension getPreferredSize() {
Dimension sz = super.getPreferredSize();
if (isPreferredSizeSet()) {
return sz;
}
int height = Math.max(sz.height, PREF_H);
return new Dimension(sz.width, height);
}
private class AddAssignmentAction extends AbstractAction {
public AddAssignmentAction(String name) {
super(name);
int mnenomic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnenomic);
}
public void actionPerformed(ActionEvent e) {
gradeTablePanel.addAssignment();
gradeTablePanel.revalidate();
gradeTablePanel.repaint();
};
}
private class GradeTablePanel extends JPanel {
private int count = 0;
// parallel collections -- a bad kludge.
// a table model would make this much cleaner
private List<JTextField> marks;
private List<JTextField> weights;
public GradeTablePanel() {
setLayout(new GridBagLayout());
JLabel assgmntLbl = new JLabel(Assignment.ASSIGNMENT, SwingConstants.CENTER);
assgmntLbl.setFont(assgmntLbl.getFont().deriveFont(Font.BOLD));
JLabel markLbl = new JLabel(Assignment.MARK, SwingConstants.CENTER);
markLbl.setFont(markLbl.getFont().deriveFont(Font.BOLD));
JLabel weightLbl = new JLabel(Assignment.WEIGHT, SwingConstants.CENTER);
weightLbl.setFont(weightLbl.getFont().deriveFont(Font.BOLD));
add(assgmntLbl, createGbc(0, 0));
add(markLbl, createGbc(1, 0));
add(weightLbl, createGbc(2, 0));
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.VERTICAL;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.anchor = GridBagConstraints.CENTER;
return gbc;
}
public void addAssignment() {
count++;
JLabel countLabel = new JLabel(String.valueOf(count));
JTextField markField = new JTextField(2);
JTextField weightField = new JTextField(2);
add(countLabel, createGbc(0, count));
add(markField, createGbc(1, count));
add(weightField, createGbc(2, count));
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("GradeAnalysis2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new GradeAnalysis2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class Assignment {
public static final String ASSIGNMENT = "Assignment";
public static final String MARK = "Mark";
public static final String WEIGHT = "Weight";
private String assignment;
private int mark;
private double weight;
public Assignment(String assignment, int mark, double weight) {
this.assignment = assignment;
this.mark = mark;
this.weight = weight;
}
public String getAssignment() {
return assignment;
}
public void setAssignment(String assignment) {
this.assignment = assignment;
}
public int getMark() {
return mark;
}
public void setMark(int mark) {
this.mark = mark;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
}
You can set the minimum, expected and maximum sizes for each JTextField like so:
JTextField t = new JTextField();
t.setMaximumSize(MAX);
t.setMinimumSize(MIN);
t.setBounds(x, y, width, height);
Where MIN and MAX are a Dimension Object, and the inputs to set bounds are int