views:

552

answers:

4

Hello all, I'm looking for the most basic description of how to draw text within a JPanel. I know there are a billion tutorials out there but none of them are clicking with me and I have some specific questions which may help others who are confused. As a setup (a testing app) I have a single class which has a JLabel, a JTextField, a JButton, and a JPanel. The application reads in ints from an external file and should display their average in the panel when the JButton is pressed. I have all the underlying programing sorted out (that is, the button responds and prints the average to the command line) but I just cannot seem to sort out how to print the average to the panel. I guess my biggest question is how to incorporate the paint() or paintComponet() method in along with the rest of the code. Should it be it's own class? Should the JPanel be it's own class? It seems like that's what most of the tutorials are telling me, I'm just not sure what the first step is exactly. The code looks like:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;  

public class Main extends JFrame implements ActionListener {
  private int[] intArray = new int[10000];
  private int numOfInts = 0;
  private int avg = 0;

  protected JButton avgBtn;
  protected JTextField indexEntry;
  protected JLabel instructions;
  protected JPanel resultsPanel;

  public Main(){

    //create main frame
    this.setTitle("Section V, question 2");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setSize(350, 250);
    this.setLayout(new GridLayout(4, 1));

    //create instruction label and add to frame
    instructions = new JLabel("Follow the instructions on the exam to use this program");
    this.add(instructions);

    //create textfield for index entry and add to frame
    indexEntry = new JTextField();
    this.add(indexEntry);

    //create button for average and add to frame
    avgBtn = new JButton("Click for Average");
    this.add(avgBtn);
    avgBtn.addActionListener(this);

    //create panel to display results and add to frame
    resultsPanel = new JPanel();
    resultsPanel.setBackground(Color.BLUE);
    this.add(resultsPanel);

    //read in from file
    readFromFile();

    //compute average
    computeAverage();
  }

  private void readFromFile() {
    try {
            // Open the file
            FileInputStream fstream = new FileInputStream("numbers.dat");

            // Get the object of DataInputStream
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));

            //create placeholder for read in ints
            String strLine;

            //Read File Line By Line
            int i = 0;
            while ((strLine = br.readLine()) != null) {
              //place ints in array and increament the count of ints
              System.out.println (strLine);
              intArray[i] = Integer.parseInt(strLine);
              numOfInts++;
              i++;
            }
            //Close the input stream
            in.close();
            System.out.println ("numOfInts = " + numOfInts);
    }
    catch (Exception e) {
            //Catch exception if any
            System.err.println("Error: " + e.getMessage());
    }
  }

  //compute averaage
  private void computeAverage() {
    int sum = 0;
    for (int i = 0; i < numOfInts; i++)
    sum += intArray[i];
    avg = sum/numOfInts;
    System.out.println("avg = " + avg);
  }

//event handling
public void actionPerformed(ActionEvent e) {
    if(e.getSource() == avgBtn) {
            computeAverage();
    }
}

//"main" function
public static void main(String[] args) {
    Main m = new Main();
    m.setVisible(true);
}

//paint
public void paintComponent(Graphics g){
  g.drawString(avg, 75, 75);
}
}

Any and all help/direction is appreciated. I know I've used this code recently for other questions, I just want to know it all! Ideally the panel would display the average of the read in ints when the button was clicked, and display whatever was entered into the textfeild when the focus was on it and enter was pressed, but I'm taking baby steps, and like I said, I'd like for this thread to be a general tutorial for others with similar questions who aren't finding answers from sun docs or other sites. Thanks so much in advance. Dan :)

+3  A: 

Add a JLabel to the JPanel.

Call setText(String) on the JLabel and your text will be drawn within the JPanel.

Gunslinger47
I love the simplicity of this. Not exactly what I was looking for. but thanks for looking at my question.
danwoods
A: 

Create an inner class that extends JPanel inside your Main class:

class MyPanel extends JPanel {

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawString(Integer.toString(avg), 75, 75);
    }

}

Then you need to call repaint on that panel after calling computeAverage() in actionPerformed:

//event handling
public void actionPerformed(ActionEvent e) {
    if (e.getSource() == avgBtn) {
        computeAverage();
        panel.repaint();
    }
}
davidrobles
Thanks for the work you put into your answer. Accepted for that by itself...
danwoods
-1 the suggestion to change the paintComponent() method to paint() is wrong. Overriding paint() at the frame level is one of the worst things you can do when you don't invoke super.paint(). For one thing none of the components added to the frame will be painted since this is handled by the super class. You will also lose painting optimizations.
camickr
you are right, I fixed the solution
davidrobles
+1  A: 

1) A JFrame doesn't have a paintComponent() method so the code you posted won't do anything. You need to create a custom JPanel and override its paintComponent() method to do your custom painting.

2) Even if you do the above, the painting will still not display because a panel by default has a zero size. So you will then need to set the preferred size of the panel to make sure it is visible.

3) Why are you even doing this. All you need to do is use a JLabel and set the text of the JLabel.

I find it hard to believe you looked at other tutorials. The Swing tutorial on Custom Painting has a 20 line program that shows the basics.

camickr
Wow, a little abrasive huh? Might want to change your screen name to camdickr. Thanks for the link.
danwoods
Except I provided the correct answer. The one you accepted was edited after mine was posted. I also suggested the JLabel before the other poster. I provided explanations why the code didn't work and gave suggestions to fix it. "Give someone a fish they eat for a day. Teach someone to fish then eat for life. I gave you tools and advice to learn how to develop your own skill which will be better in the long run. That is why I don't post code. Expecting people to write code for you is the wrong attitude.
camickr
A: 

I think you should not be subclassing JFrame. Make an instance of JFrame an instance
variable of Main class and add the JPanel etc. to it.

sateesh
this doesn't even attempt to answer the question, would be better as a comment on the question.
pstanton
Agreed.Wanted to add quickly something which I thought would help. But looking back I agree my post doesn't provide much help.
sateesh
just post a comment, still helpful but doesn't pose as an answer.
pstanton