Small GUI issue I cannot fix. JTextFields

2019-02-21 03:47发布

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.

3条回答
仙女界的扛把子
2楼-- · 2019-02-21 03:50

I suggest that you

  1. Don't use setBounds(...) on any component or GUI
  2. Same for setSize(...)
  3. Instead nest JPanels each using its own layouts to achieve a pleasing and easy to manage layout and GUI.
  4. 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.
  5. 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;
   }


}
查看更多
forever°为你锁心
3楼-- · 2019-02-21 03:54

Here's the GUI I created.

Grade Calculator

  1. 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).

  2. 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.

  3. The order of the JFrame methods is extremely important. Memorize the order of the JFrame methods in this example.

  4. 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);
    }

}
查看更多
甜甜的少女心
4楼-- · 2019-02-21 04:06

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

查看更多
登录 后发表回答