在JPanel中绘制文本

6
我正在寻找如何在JPanel中绘制文本的最基本描述。我知道有数十亿个教程,但没有一个适合我,而我有一些特定的问题,这可能有助于其他困惑的人。作为设置(测试应用程序),我有一个类,其中包含JLabel、JTextField、JButton和JPanel。该应用程序从外部文件中读取整数,并在按下JButton时显示它们的平均值。我已经将所有底层编程都解决了(也就是说,按钮响应并将平均值打印到命令行),但我似乎无法解决如何将平均值打印到面板中。我猜我最大的问题是如何将paint()或paintComponet()方法与其余代码结合起来。它应该是自己的类吗?JPanel应该是自己的类吗?似乎大多数教程都在告诉我是这样的,只是不确定第一步是什么。代码看起来像:
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");
            BufferedReader br = new BufferedReader(new InputStreamReader(fstream));

            //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);
}
}

非常感谢您的帮助和指导。我知道我最近在其他问题中使用了这段代码,我只是想了解全部!理想情况下,当单击按钮时,面板将显示读入整数的平均值,并在焦点在文本字段上并按下回车键时显示输入的任何内容,但我正在迈出踏实的步伐,就像我所说的那样,我希望这个主题成为一个通用教程,供其他有类似问题的人参考,他们在sun docs或其他网站上找不到答案。非常感谢您的提前帮助。丹 :)

4个回答

7
在您的Main类中创建一个扩展JPanel的内部类:
class MyPanel extends JPanel {

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

}

在调用computeAverage()方法后,您需要在该面板上调用repaint()方法:

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

2
将paintComponent()方法更改为paint()的建议是错误的。在框架级别覆盖paint()是你不调用super.paint()时可以做的最糟糕的事情之一。首先,由于这是由超类处理的,因此不会绘制添加到框架中的任何组件。您还将失去绘画优化。 - camickr

7

向JPanel添加一个JLabel。

对JLabel调用setText(String)方法,您的文本将在JPanel中绘制。


我喜欢它的简洁性。虽然不完全是我想要的,但感谢您查看我的问题。 - danwoods

5

1) JFrame没有paintComponent()方法,所以您发布的代码不会起作用。您需要创建一个自定义JPanel并覆盖其paintComponent()方法来进行自定义绘制。

2) 即使您执行上述操作,绘图仍然不会显示,因为面板默认大小为零。因此,您需要设置面板的首选大小以确保它可见。

3) 您为什么要这样做。您只需要使用JLabel并设置JLabel的文本即可。

我很难相信您看过其他教程。在自定义绘画的Swing教程中有一个20行的程序,展示了基础知识。


哇,有点粗鲁啊?也许你应该把屏幕名改成camdickr。谢谢提供链接。 - danwoods
2
除了我给出正确的答案之外,你接受的那个答案是在我的回答发布后进行编辑的。我也在另一个帖子之前建议使用JLabel。我解释了代码为什么不起作用,并提出了修复建议。“授人以鱼,不如授人以渔。”我给了你学习如何开发自己技能的工具和建议,这样长远来看会更好。这就是为什么我不发布代码的原因。期望别人为你编写代码是错误的态度。 - camickr

-1

我认为你不应该对JFrame进行子类化。把JFrame的实例作为Main类的实例变量,并将JPanel等添加到它上面。


这甚至没有尝试回答问题,最好作为对问题的评论。 - pstanton
同意。我想快速添加一些东西来帮助,但回想起来,我同意我的帖子并没有提供太多帮助。 - sateesh
只需在下面留下一条评论,虽然不算作答案,但仍然有帮助。 - pstanton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接