【问题标题】:How to Draw JPanel's Components without the background?如何在没有背景的情况下绘制 JPanel 的组件?
【发布时间】:2015-12-07 06:41:11
【问题描述】:

所以我有一个扩展 JPanel 的“GameCourt”类。此类覆盖paintComponent 代码,以便它绘制一些组件(迷宫、角色和一些硬币)。这个 JPanel 是扩展 JLayeredPane 的类的一部分,它有两层,一层用于绘制背景(使用扩展 JPanel 的 BackgroundPanel 类),另一层用于绘制我想要的所有元素(重置按钮、标签..)

所以我想要的是 JLayeredPane 中背景上方的 GameCourt,而不是绘制它的背景,这样我就可以查看漂亮的图像。

我在 GameCourt 中尝试了 setOpaque(false),but then it only displays the background.

I tried setBackground (new Color(0,0,0,0)) but that didn't work. 那是因为在 GameCourt JPanel 后面还有另一个 blackBackground 我不知道它是从哪里来的。我尝试了 super.setBackground,但没有任何效果。

我尝试更改 JLayeredPane 中的背景索引以使其高于 GameCourt(JPanel),但这并没有什么不同。 (这很奇怪,因为它至少应该在 GameCourt JPanel 上方绘制背景。

另外,我尝试在 JavaDocs 中的示例代码中执行:add(background, new Integer(0)),但它显​​示“Illegal Argument Exception”。

我真的不知道出了什么问题...我想我误解了 JLayeredPane 代码,因为当我使用 setOpaque(false) 但不向 JLayeredPane 添加背景时,它会正确显示所有内容。另外,将 add(background,0) 更改为 add(background,2) 有何不同??

这是“GameCourt”代码(简化版): m.draw(g)、coins.drawCoins(g) 等。只画一堆png图片。

 public class GameCourt extends JPanel {

 public GameCourt(JLabel status) {

 //     setOpaque(false);    
    setBackground(new Color(0,0,0,0));
 // Game constants
public static final int COURT_WIDTH = 1275;
public static final int COURT_HEIGHT = 765;
}

/**
 * (Re-)set the game to its initial state.
 */
public void reset() {
    playing = true;
    status.setText("Running...");

    // Make sure that this component has the keyboard focus
    requestFocusInWindow();
}

/**
 * This method is called every time the timer defined in the constructor
 * triggers.
 */
private void tick() {
    if (playing) {
        repaint();
    }
}
@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    m.drawMaze(g);
    player.draw(g);
    coins.drawCoins(g);
}

@Override
public Dimension getPreferredSize() {
    return new Dimension(COURT_WIDTH, COURT_HEIGHT);
}
}

这里是 JLayeredPanel 代码(也稍微简化了):

public class LayeredGameCourt extends JLayeredPane {

package Game;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class LayeredGameCourt extends JLayeredPane {


    private GameCourt court;
    public LayeredGameCourt()    {

        setPreferredSize(new Dimension(GameCourt.COURT_WIDTH, GameCourt.COURT_HEIGHT+90));
        setLayout(new BorderLayout());

        final JBackgroundPanel background = new JBackgroundPanel();
        add(background,0);
        background.setBounds(0,0,GameCourt.COURT_WIDTH,GameCourt.COURT_HEIGHT+90);

        // Status panel
        final JLabel status = new JLabel("Running...");

        // Main playing area
        final GameCourt court = new GameCourt(status);
        this.court=court;
        add(court, 1);
        court.setBounds(0,90,GameCourt.COURT_WIDTH,GameCourt.COURT_HEIGHT);

        // Reset button
        final JPanel control_panel = new JPanel();
        add(control_panel, 1);


        final JButton reset = new JButton("Reset");
        reset.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                court.reset();
            }
        });
        control_panel.add(status);
        control_panel.add(reset);
        // Start game
        court.reset();
    }

    public void requestFocusForGC(){
        court.requestFocusInWindow();
    }

    }

最后,(无用的)backgroundPanel 代码,如果有帮助的话:

@SuppressWarnings("serial")
public class JBackgroundPanel extends JPanel {

    private BufferedImage background;
    public JBackgroundPanel() {
        try {
            if (background == null) {
                background = ImageIO.read(new File("background.png"));
            }
        } catch (IOException e) {
            System.out.println("Internal Error:" + e.getMessage());
        } 
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(background, 0, 0,null);  
        System.out.println("attempting to paint");
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(GameCourt.COURT_WIDTH, GameCourt.COURT_HEIGHT+90);
    }
}

【问题讨论】:

    标签: java swing jpanel transparent jlayeredpane


    【解决方案1】:

    没关系,让它工作!

    对于可能遇到相同问题的其他人。以下是我的思考过程。

    为什么我不能 add(Background, new Integer(0))?

    也许是因为背景不是一个组件?没有。 查看 java 文档,意识到他们没有设置布局类型。 也许我的 .add 调用了我添加的 BorderLayout 的 .add,这就是它失败的原因。

    所以我删除了它,它起作用了!!!

    我需要做的就是疯狂地注释掉我出于某种该死的原因决定需要在那里的一行。

    但它有效!!!!

    澄清:这是我删除的行:

    setLayout(new BorderLayout());
    

    感谢(如果)任何试图提供帮助的人!

    【讨论】:

    • How to use layered panes 中所述 - “将组件添加到分层窗格时,您使用整数指定层。使用 setLayer 更改组件的层时,您使用 int。您可能会认为,如果您在 add 方法中使用 int 而不是 Integer,编译器会报错,或者您的程序会抛出非法参数异常。但编译器什么也没说,这会导致常见的分层窗格问题。”
    • 默认情况下JLayeredPane没有默认布局管理器,你可以使用它们,但是你会受到该布局管理器工作方式的限制,例如BorderLayout只会管理在 5 个可用插槽中的任何一个上的单个组件,如果您将更多组件添加到同一位置,则只会管理最后一个组件
    • 是的,我想这也是我无法集中注意力的原因,谢谢!
    猜你喜欢
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-01
    • 2022-01-08
    相关资源
    最近更新 更多