【问题标题】:JPanel Image Background Overlapping Other JPanelJPanel 图像背景与其他 JPanel 重叠
【发布时间】:2016-02-19 00:29:51
【问题描述】:

我有两个 JPanel,一个是图像,另一个是表单。我正在尝试将第一个面板与背景图像放在其他(绘画)后面,但它不起作用

面板背景:

public JPanel fundo() {
    JPanel bg = new JPanel(new BorderLayout());
    try {
        Image backgroundImage = ImageIO.read(new File("C:/ceu.png"));
        setContentPane(new JPanel(new BorderLayout()) {
            @Override
            public void paintComponent(Graphics g) {
                g.drawImage(backgroundImage, 0, 0, null);
            }
        });
    } catch (IOException e) {
        System.out.println(e);
    }
    return bg;
}

这是面板形式(仅遵循逻辑):

public JPanel painelCadastro() {
    JPanel telaAtual = new JPanel();
    JTextField nome, telefone, aniversario, email;
    String definicao;
    JLabel lugarnome, lugartelefone, lugaraniversario, lugaremail;
    JTextArea endereço;

    telaAtual.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    //c.anchor = GridBagConstraints.WEST;
    //c.ipadx = 2;
    //c.ipady = 3;
    //c.gridheight = GridBagConstraints.REMAINDER;  
    //c.gridwidth = GridBagConstraints.REMAINDER;  

    lugarnome = new JLabel("Nome");
    c.weightx = 1; // percentual de tamanho em relação aos demais
    c.gridwidth = 1; //tamanho do compontente em celulas HORIZONTAL
    c.gridheight = 1; //tamanho do compontente em celulas VERTICAL
    c.gridx = 0; //localização da celula na coluna
    c.gridy = 0; //localização da celula na linha
    //c.fill = GridBagConstraints.HORIZONTAL;
    c.insets = new Insets(10, 10, 0, 0);
    telaAtual.add(lugarnome, c);

    nome = new JTextField("Digite seu nome aqui");
    definicao = "nome";
    c.weightx = 1; // percentual de tamanho em relação aos demais
    c.gridwidth = 7; //tamanho do compontente em celulas HORIZONTAL
    c.gridx = 1; //localização da celula na linha
    c.gridy = 0; //localização da celula na coluna
    //c.fill = GridBagConstraints.HORIZONTAL;
    limpaCaixaTexto(nome, definicao);
    telaAtual.add(nome, c);

    lugartelefone = new JLabel("Telefone");
    c.weightx = 1; // percentual de tamanho em relação aos demais
    c.gridx = 0; //localização da celula na linha
    c.gridy = 1; //localização da celula na coluna
    c.fill = GridBagConstraints.NONE;
    telaAtual.add(lugartelefone, c);

    telefone = new JTextField("Digite seu telefone aqui");
    definicao = "telefone";
    c.weightx = 2; // percentual de tamanho em relação aos demais
    c.gridx = 1; //localização da celula na linha
    c.gridy = 1; //localização da celula na coluna
    c.fill = GridBagConstraints.HORIZONTAL;
    limpaCaixaTexto(telefone, definicao);
    telaAtual.add(telefone, c);

    lugaremail = new JLabel("Email");
    c.weightx = 1; // percentual de tamanho em relação aos demais
    c.gridx = 0; //localização da celula na linha
    c.gridy = 2; //localização da celula na coluna
    c.fill = GridBagConstraints.NONE;
    telaAtual.add(lugaremail, c);

    email = new JTextField("Digite seu e-mail aqui");
    definicao = "e-mail";
    c.weightx = 2; // percentual de tamanho em relação aos demais
    c.gridx = 1; //localização da celula na linha
    c.gridy = 2; //localização da celula na coluna
    c.fill = GridBagConstraints.HORIZONTAL;
    limpaCaixaTexto(email, definicao);
    telaAtual.add(email, c);

    //--------- INICIO CAMPO DATA -------------
    lugaraniversario = new JLabel("Data de Nascimento");
    c.weightx = 1; // percentual de tamanho em relação aos demais
    c.gridx = 0; //localização da celula na linha
    c.gridy = 3; //localização da celula na coluna
    c.fill = GridBagConstraints.NONE;
    telaAtual.add(lugaraniversario, c);

    //JFormattedTextField dataAniversario = new JFormattedTextField(DateFormat.getDateInstance(DateFormat.MEDIUM));
    //GregorianCalendar data = new GregorianCalendar();
    //dataAniversario.setText(data.get(Calendar.DAY_OF_MONTH) + "/" + (data.get(Calendar.MONTH) + 1) + "/" + (data.get(Calendar.YEAR)));
    DateFormat df = new SimpleDateFormat("dd/mm/yyyy");
    JFormattedTextField dataAniversario = new JFormattedTextField(df);
    try {
        MaskFormatter dateMask = new MaskFormatter("##/##/####");
        dateMask.install(dataAniversario);

    } catch (ParseException ex) {
        Logger.getLogger(TelaPrincipalLocadora.class
                .getName()).log(Level.SEVERE, null, ex);
    }
    definicao = "aniversario";
    c.weightx = 2; // percentual de tamanho em relação aos demais
    c.gridx = 1; //localização da celula na linha
    c.gridy = 3; //localização da celula na coluna
    c.fill = GridBagConstraints.HORIZONTAL;
    limpaCaixaTexto(dataAniversario, definicao);
    telaAtual.add(dataAniversario, c);

    //--------- FIM CAMPO DATA -------------
    return telaAtual;
}

我用这个代码给他打电话:

private static void criarGUI() throws IOException {
    //Create and set up the window.
    JFrame frame = new JFrame("Vapstor Locadoras V1.0");
    frame.setSize(590, 456);
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);
    frame.setLayout(new BorderLayout());

    TelaPrincipalLocadora demo = new TelaPrincipalLocadora();
    frame.setJMenuBar(demo.BarradeMenu());
    demo.painelCadastro().setVisible(false);

    frame.add(demo.painelCadastro()); //~HERE HE ADD

    frame.add(demo.fundo());
    System.out.println(demo.painelCadastro().isVisible()); // returns true

    demo.fundo().setOpaque(false); //HERE 
    frame.add(demo.fundo()); //AND HERE i guess is the problem

    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setVisible(true);
}

我尝试了其他方法,但我得到的是背景图像与所有内容重叠,即使是 painelCadastro() 可见.. 有什么想法能给我启发吗?

编辑

static class Background extends JComponent {

    Image backgroundImage;

    public Background() throws IOException {
        this.backgroundImage = ImageIO.read(new File("C:/ceu.png"));
    }

    @Override
    public void paintComponent(Graphics g) {
        g.drawImage(backgroundImage, 0, 0, this);
        System.out.println("pintou o 7");
    }
}

关于主类:

    JPanel tela = new JPanel(new BorderLayout());
    tela.add(new Background());
    tela.setOpaque(false);
    frame.setContentPane(tela);
    //frame.setAlwaysOnTop(true);
    demo.painelCadastro().setOpaque(false);
    frame.add(demo.painelCadastro());

好吧,我创建了一个辅助类,将她的图像添加到面板中,将内容设置为框架,但是当我尝试将表单变为可见时仍然是一个或另一个

编辑 它有效,谢谢

但是... Where is the checkbox menuitens in this 'xp interface'? Another question, is that a "label"? appears at the end of gui I guess it just can be the Dimension wrong, because the frame is .pack

【问题讨论】:

  • 如需尽快获得更好的帮助,请发帖minimal reproducible exampleShort, Self Contained, Correct Example
  • 调用 super.paintComponent 也是个好主意
  • @MadProgrammer 我用二级课程编辑它,但仍然不起作用
  • 考虑提供一个runnable example 来证明您的问题。这不是代码转储,而是您正在做的事情的一个例子,它突出了您遇到的问题。这将减少混乱并获得更好的响应
  • 你的代码有点奇怪,你似乎在使用fundoJFrame 创建背景图像(使用setContentPane),但随后你将其添加到另一个框架中在criarGUI?!但是从fundo 返回的组件实际上并不是设置contentPane时使用的组件!??!

标签: java swing user-interface jpanel overlapping


【解决方案1】:

所以,我正在尝试对您的代码进行正面和反面...

首先我们...

public JPanel fundo() {
    JPanel bg = new JPanel(new BorderLayout());
    try {
        Image backgroundImage = ImageIO.read(new File("C:/ceu.png"));
        setContentPane(new JPanel(new BorderLayout()) {
            @Override
            public void paintComponent(Graphics g) {
                g.drawImage(backgroundImage, 0, 0, null);
            }
        });
    } catch (IOException e) {
        System.out.println(e);
    }
    return bg;
}

表面上看起来不错,但是当我们仔细观察时,我注意到从该方法返回的面板不是应用为contentPane!的面板!?

但是在您的criarGUI 中,您使用fundo 方法返回的面板并将其添加到另一个框架......但您只是在框架中添加了一个空白面板。

因此,出于某种原因,您从 demo 类中获取内容并尝试将其添加到不同的框架中...为什么应该真正回答一个问题,因为这有点令人担忧...

另一个问题是,你一直打电话给painelCadastro...

demo.painelCadastro().setOpaque(false);
frame.add(demo.painelCadastro());

但是painelCadastro 每次调用它时都会创建一个新的JPanel,因此更改其opaque 状态无效,因为第二次调用它时,您将获得JPanel 的全新实例

解决方案??要么让您的方法缓存其操作的结果(AKA 延迟加载),并始终返回相同的 JPanel 实例(最初创建的),要么保持对返回的组件的引用。此外,请确保适当地命名您的方法,以便它们更多地了解它们的作用。在您的情况下,makePainelCadastrocreatePainelCadastro 可能更合适

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import javax.imageio.ImageIO;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.MaskFormatter;

public class Testing {

    public static void main(String[] args) {
        new Testing();
    }

    public Testing() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setContentPane(new Background());
                    JPanel painelCadastro = painelCadastro();
                    painelCadastro.setOpaque(false);
                    frame.add(painelCadastro);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public JPanel painelCadastro() {
        JPanel telaAtual = new JPanel();
        JTextField nome, telefone, aniversario, email;
        String definicao;
        JLabel lugarnome, lugartelefone, lugaraniversario, lugaremail;
        JTextArea endereço;

        telaAtual.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        //c.anchor = GridBagConstraints.WEST;
        //c.ipadx = 2;
        //c.ipady = 3;
        //c.gridheight = GridBagConstraints.REMAINDER;  
        //c.gridwidth = GridBagConstraints.REMAINDER;  

        lugarnome = new JLabel("Nome");
        c.weightx = 1; // percentual de tamanho em relação aos demais
        c.gridwidth = 1; //tamanho do compontente em celulas HORIZONTAL
        c.gridheight = 1; //tamanho do compontente em celulas VERTICAL
        c.gridx = 0; //localização da celula na coluna
        c.gridy = 0; //localização da celula na linha
        //c.fill = GridBagConstraints.HORIZONTAL;
        c.insets = new Insets(10, 10, 0, 0);
        telaAtual.add(lugarnome, c);

        nome = new JTextField("Digite seu nome aqui");
        definicao = "nome";
        c.weightx = 1; // percentual de tamanho em relação aos demais
        c.gridwidth = 7; //tamanho do compontente em celulas HORIZONTAL
        c.gridx = 1; //localização da celula na linha
        c.gridy = 0; //localização da celula na coluna
        //c.fill = GridBagConstraints.HORIZONTAL;
//      limpaCaixaTexto(nome, definicao);
        telaAtual.add(nome, c);

        lugartelefone = new JLabel("Telefone");
        c.weightx = 1; // percentual de tamanho em relação aos demais
        c.gridx = 0; //localização da celula na linha
        c.gridy = 1; //localização da celula na coluna
        c.fill = GridBagConstraints.NONE;
        telaAtual.add(lugartelefone, c);

        telefone = new JTextField("Digite seu telefone aqui");
        definicao = "telefone";
        c.weightx = 2; // percentual de tamanho em relação aos demais
        c.gridx = 1; //localização da celula na linha
        c.gridy = 1; //localização da celula na coluna
        c.fill = GridBagConstraints.HORIZONTAL;
//      limpaCaixaTexto(telefone, definicao);
        telaAtual.add(telefone, c);

        lugaremail = new JLabel("Email");
        c.weightx = 1; // percentual de tamanho em relação aos demais
        c.gridx = 0; //localização da celula na linha
        c.gridy = 2; //localização da celula na coluna
        c.fill = GridBagConstraints.NONE;
        telaAtual.add(lugaremail, c);

        email = new JTextField("Digite seu e-mail aqui");
        definicao = "e-mail";
        c.weightx = 2; // percentual de tamanho em relação aos demais
        c.gridx = 1; //localização da celula na linha
        c.gridy = 2; //localização da celula na coluna
        c.fill = GridBagConstraints.HORIZONTAL;
//      limpaCaixaTexto(email, definicao);
        telaAtual.add(email, c);

        //--------- INICIO CAMPO DATA -------------
        lugaraniversario = new JLabel("Data de Nascimento");
        c.weightx = 1; // percentual de tamanho em relação aos demais
        c.gridx = 0; //localização da celula na linha
        c.gridy = 3; //localização da celula na coluna
        c.fill = GridBagConstraints.NONE;
        telaAtual.add(lugaraniversario, c);

        //JFormattedTextField dataAniversario = new JFormattedTextField(DateFormat.getDateInstance(DateFormat.MEDIUM));
        //GregorianCalendar data = new GregorianCalendar();
        //dataAniversario.setText(data.get(Calendar.DAY_OF_MONTH) + "/" + (data.get(Calendar.MONTH) + 1) + "/" + (data.get(Calendar.YEAR)));
        DateFormat df = new SimpleDateFormat("dd/mm/yyyy");
        JFormattedTextField dataAniversario = new JFormattedTextField(df);
        try {
            MaskFormatter dateMask = new MaskFormatter("##/##/####");
            dateMask.install(dataAniversario);

        } catch (ParseException ex) {
            ex.printStackTrace();
        }
        definicao = "aniversario";
        c.weightx = 2; // percentual de tamanho em relação aos demais
        c.gridx = 1; //localização da celula na linha
        c.gridy = 3; //localização da celula na coluna
        c.fill = GridBagConstraints.HORIZONTAL;
//      limpaCaixaTexto(dataAniversario, definicao);
        telaAtual.add(dataAniversario, c);

        //--------- FIM CAMPO DATA -------------
        return telaAtual;
    }

    public class Background extends JPanel {

        private BufferedImage backgroundImage;

        public Background() throws IOException {
            this.backgroundImage = ImageIO.read(new File("..."));
            setLayout(new BorderLayout());
        }

        @Override
        public Dimension getPreferredSize() {
            return backgroundImage == null ? new Dimension(200, 200) : new Dimension(backgroundImage.getWidth(), backgroundImage.getHeight());
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(backgroundImage, 0, 0, this);
        }
    }
}

【讨论】:

    【解决方案2】:

    您不能将多个组件添加到内容窗格的中心。您需要在组件之间建立父/子关系。

    基本逻辑应该是:

    JPanel background = new BackgroundPanel(); // this is where you paint the image
    background.setLayout( new BorderLayout() );
    
    JPanel child = new JPanel(); // this is the panel with your other components
    child.setOpaque( false );
    
    background.add( child );
    frame.add( background );
    

    【讨论】:

    • @AcauãPitta,您的代码不符合我的建议。我在哪里使用 setContentPane() 我的代码???我在框架中添加了什么组件???如果你不能效仿我的榜样,我不知道我能提供什么帮助
    • @camickr 问题是 OP 的代码在每次调用 painelCadastro 方法时都会创建一个新的 JPanel ,而不是维护对返回组件的引用,它们只是与不同的组件进行交互例如,demo.painelCadastro().setOpaque(false);,然后是frame.add(demo.painelCadastro());,这显然只是要在框架中添加一个不透明的组件。你暗示了这一点,但 OP 看不到森林的树木:P
    • @MadProgrammer,我知道问题出在哪里,他没有遵循我建议的简单结构。当然,如果人们继续为他编写代码,那么他就没有理由学习如何阅读建议并简化问题。
    • @camickr 相应地,如果您指出了引用问题,OP 可能会意识到他们做错了什么(然后理解代码 sn-p 试图建议的内容),但您只是指出BorderLayout,这实际上不是“真正的”问题,而是一个复合问题,但至少 OP 不能抱怨“代码不起作用”,因为他们现在有一个可运行的示例,他们可以从中进行实验和比较并支持我对他们的代码问题所做的陈述:P
    • @camickr 我认为我们可以同意的一件事是,代码是一团糟,OP 正在做一些没有意义的事情(比如重复添加一个新的背景实例):P
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-01
    • 1970-01-01
    • 2019-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    相关资源
    最近更新 更多