【问题标题】:JPanel or JLabel seem to be creating two labels instead of one for each object?JPanel 或 JLabel 似乎是为每个对象创建两个标签而不是一个标签?
【发布时间】:2011-10-12 07:46:20
【问题描述】:

如果这是一个非常简单的解决方案或愚蠢的错误,请原谅 - 这是我第一次尝试在 Java 中实现图形! :)

我正在尝试制作一个图块板,每个图块都是一个图块对象,图块的所有位置都存储在称为“内容”(内容[][][])的图块三重数组中。

为了使每个图块“可点击”,我基本上是为每个图块图标创建一个标签,并根据图块对象的 x,y 坐标在板上定位该图块。我对内容数组中的每个非空 Tile 对象执行此操作。

当我使用 graphics.drawImage 函数时这很好用,但是当我使用 setBorders() 函数定位每个标签时:

  1. 创建磁贴布局,但并不完美 - 似乎有些缺失或低于其他。

  1. 它会在其他处于正确位置的图块上方创建一个重复的未定位图层。

我正在调用的函数的代码是:

    public void paintComponent(Graphics graphics) {
    // let superclass paint to fill in background
    super.paintComponent(graphics);
    Tile[][][] content = b.getContent();

    if (content==null || tileImages==null) {
        return;
    }

    /* Set dummy previous label */ 
    prevT.setBounds(-1,-1,1,1);

    // draw tiles back to front

    for (int i = 0; i<content.length; i++) {
        for (int y = 0; y<content[i].length; y++) {
            for (int x = 0; x<content[i][y].length; x++) {
                final Tile t = content[i][y][x];
                if (t!=null) {
                    if (y>0 && content[i][y-1][x]!=null && t.equals(content[i][y-1][x])) {
                        continue;
                    }
                    if (x>0 && content[i][y][x-1]!=null && t.equals(content[i][y][x-1])) {
                        continue;
                    }
                    Image image = tileImages[t.getValue()][t.getSubindex()];

                    if (b.free(t)) {
                        image = tileImagesHL[t.getValue()][t.getSubindex()];

                    }

                    /* Mouse event magic */

                    graphics.drawImage(image, x*TILEW+TILEW/2+i*TILESKEW, (y+1)*TILEH/2-i*TILESKEW, null);

                    /* Create icon to be displayed */
                    ImageIcon icon = new ImageIcon(image);
                    /* Label that acts as the clickable tile */
                    final JLabel label = new JLabel();

                    /* Associate image with label */
                    label.setIcon(icon);

                    /* Allow mouse events to interact with label */
                    label.addMouseListener(this);

                    /* Position labels according to tile coordinates */
                    label.setBounds(x*TILEW+TILEW/2+i*TILESKEW, (y+1)*TILEH/2-i*TILESKEW, image.getWidth(null), image.getHeight(null));

                    /* Associate label with specified tile */
                    t.setLabel(label);

                    /* Add label to list*/
                    labels.add(label);

                    this.setVisible(true);
                    this.add(label);

                }
            }
        }
    }
}

任何解释为什么会发生这种情况将不胜感激!我已经尝试重写这个函数很多次了,但我没有想法!

谢谢! :)

【问题讨论】:

  • 只是为了强调@mKorbel 回答中最重要的要点:不要更改paintComponent 中组件的任何状态,它是用于绘画的,仅此而已。

标签: java swing icons jpanel jlabel


【解决方案1】:

1)不要在paintComponent(Graphics graphics)里面创建Object,在之前准备好这些Object

我的观点,带有鼠标事件魔术的简单容器,没有MouseListener

2) 创建JPanel 并将JButton#setBackground(someColor) 放在那里,然后添加JButton#setRolloverIcon(someIcon),不再需要任何MouseListener

3) 如果您创建 Tiles,则查找 GridLayout

4) 准备Icons 并将这些Icon 添加到JButton,仅此而已,Objects 的任何Array,没有代码超过我描述的

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

public class TilesWithButton {

    private Icon warningIcon = UIManager.getIcon("OptionPane.warningIcon");
    private Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon");
    private Icon errorIconRoll = UIManager.getIcon("OptionPane.errorIcon");
    private JPanel myPanel = new JPanel();

    public TilesWithButton() {
        myPanel.setLayout(new GridLayout(1, 2, 1, 1));

        JButton btn = new JButton();
        btn.setBackground(Color.white);
        btn.setIcon(infoIcon);
        btn.setRolloverIcon(errorIconRoll);
        btn.setFocusPainted(false);
        myPanel.add(btn);

        JButton btn1 = new JButton();
        btn1.setBackground(Color.white);
        btn1.setIcon(warningIcon);
        btn1.setRolloverIcon(errorIconRoll);
        btn1.setFocusPainted(false);
        myPanel.add(btn1);

        JFrame frame = new JFrame("Tiles");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(myPanel);
        frame.pack();
        frame.setLocation(150, 100);
        frame.setVisible(true);
    }

    public static void main(final String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                TilesWithButton tilesWithButton = new TilesWithButton();
            }
        });
    }
}

【讨论】:

  • @KristinaElise:也可以考虑MVC pattern
  • 非常感谢您的帮助!感谢您的回答,我能够解决它:)
猜你喜欢
  • 1970-01-01
  • 2021-09-28
  • 1970-01-01
  • 2017-06-13
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-02
相关资源
最近更新 更多