【问题标题】:Why is my JLabel never being painted?为什么我的 JLabel 永远不会被绘制?
【发布时间】:2013-02-16 21:19:26
【问题描述】:

首先,我查看了此处所有其他类似的帖子,但没有一个能够提供帮助。我正在编写一个扫雷游戏,我试图在我的 JFrame 的边界布局顶部放置一个 Jlabel,并让它显示一个计数器,显示有多少地雷需要标记。每当单击网格上的任何其他 Jlabel 时,都需要重新绘制它。首先,在我的代码中,我的标题 JLabel 上从未显示任何文本。我可以让文本显示的唯一方法是将它放在我的 JLabel 构造函数中。这让我认为我的paintComponent 永远不会被调用。我还在mouseHandler 中调用了headerJabel 的repaint 方法,用于我的游戏的实际网格。这样,如果用户单击游戏中的任何组件,标题 JLabel 将重新绘制自身以反映用户的移动。

基本上,为什么我的 JLabel 不会显示任何内容,除非我明确地将它放在构造函数中?

导入 javax.swing.; 导入 java.awt.;

公共类 JLabelCounter 扩展 JLabel {

private MinesweeperModel model;
public JLabelCounter(MinesweeperModel myModel)
{
   model = myModel;    

}

public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    int minesRemaining = model.numberOfMinesRemaining();
    setText("Mines remaining" + minesRemaining);

}

}

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

public class MinesweeperPanel extends JPanel {

 private MinesweeperModel model;
 private JLabelCounter labelCounter;

public MinesweeperPanel(MinesweeperModel myModel, JLabelCounter counter)
{
    model = myModel;
    labelCounter = counter;
    setLayout(new GridLayout(10,10));
    //addMouseListener(new MouseHandler());

     for(int i = 0; i <10; i++)
    {
        for(int j = 0; j < 10; j++)
        {
            MinesweeperJLabel myJLabel = new MinesweeperJLabel(i,j,myModel);
            myJLabel.addMouseListener(new MouseHandler());
            add(myJLabel);
        }

    }

}

private class MouseHandler extends MouseAdapter
{
    public void mouseClicked(MouseEvent e)
    {

        MinesweeperJLabel labelClicked = (MinesweeperJLabel)e.getSource();
        int x = labelClicked.getXCoordinate();
        int y = labelClicked.getYCoordinate();
        int buttonClicked = e.getButton();

        if (buttonClicked == 1)
        {
            model.stepOnMine(x,y);
        }
        else if(buttonClicked == 3)
        {
            model.flagMine(x, y);
        }
      repaint(); 
      labelCounter.repaint();


    }
}

}

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

public class MinesweeperFrame  extends JFrame{

public MinesweeperFrame()
{
    MinesweeperModel myModel = new MinesweeperModel();
    setTitle("My Super Awesome Minesweeper Game!");
    Toolkit kit = Toolkit.getDefaultToolkit();
    Dimension screenSize = kit.getScreenSize();
    setSize(screenSize.width/2,screenSize.height/2);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JLabelCounter counter = new JLabelCounter(myModel);
    Container contentPane = getContentPane();
    MinesweeperPanel panel = new MinesweeperPanel(myModel,counter);
    contentPane.add(counter,BorderLayout.PAGE_START);
    contentPane.add(panel);

    setVisible(true);      


}

}

使用原样的代码,看起来好像我在运行时甚至在我的标题中都没有 JLabel。

【问题讨论】:

  • 不要从paintComponent中调用setText,它会导致组件失效和另一个重绘请求,一次又一次......你明白了
  • 那我如何让 JLabel 显示随着游戏更新的不同文本?
  • 查看答案 - 基本上,我们是观察者模式

标签: java swing jlabel repaint


【解决方案1】:

不要从paintComponent中调用setText,它会导致组件失效和另一个重绘请求,一次又一次......你明白了

而不是尝试在paint方法中更新标签。向您的模型添加某种侦听器接口,您可以使用它来更新标签。

基本上,当您的模型发生变化时,它会触发一个事件,您的标签可以对此做出反应并自行更新

【讨论】:

  • 我想过,但用户永远不会真正点击标题。所以附加到标题的监听器永远不会被触发
  • 这取决于它在听什么。 MP 没有说让它监听用户事件,而是监听模型事件。您的模型(无论您如何实现)都是代表游戏逻辑的所有数据和数据结构(与 UI 分开);它知道哪些方格已被清除,哪些方格显示相邻的地雷数量,诸如此类。当用户点击一个方块时,我希望模型会触发一个侦听器,找出其他方块的状态因此发生了哪些变化,并为每个方块触发一个侦听器。
猜你喜欢
  • 2013-07-22
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多