2015-03-05 14 views
0

Я изо всех сил, чтобы сделать что-то я думаю, довольно просто:Создание формы с фоновым изображением (JLayeredPane)

Я хочу, чтобы создать форму (JTextField) с фоновым изображением. Чтобы форма не охватывала фоновое изображение, я использую JLayeredPane. Я пробовал разные вещи, ничего не работает: по какой-то причине я либо показываю только фон, либо только JTextField, но никогда и то, и другое. Моя цель состояла бы в том, чтобы иметь фоновое изображение, которое никогда не меняется, и просто используйте мои кнопки/текстовые поля поверх него.

package gestion; 

import java.awt.*; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class Main extends JFrame{ 
JLayeredPane layeredPane; 
JPanel board; 
JPanel background; 


public Main(){ 
    super("Test"); 
    background = new JPanel(); 
    layeredPane = new JLayeredPane(); 
    board = new JPanel(); 

    // Creating frame with LayeredPane 
    Dimension boardSize = new Dimension(1280, 1024); 
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    this.setResizable(false); 
    this.setSize(boardSize.width, boardSize.height); 
    this.setVisible(true); 
    this.setLocationRelativeTo(null); 

    layeredPane.setPreferredSize(boardSize); 
    this.add(layeredPane); 


    // Add a background to the Layered Pane 
    JLabel picLabel = new JLabel(new ImageIcon("background.jpg")); 
    background.add(picLabel); 
    background.setPreferredSize(boardSize); 
    background.setBounds(0,0,boardSize.width, boardSize.height); 
    layeredPane.add(background, JLayeredPane.DEFAULT_LAYER); 

    // Add a JTextField 
    final JTextField jtf = new JTextField("Default Value"); 

    Font police = new Font("Arial", Font.BOLD, 14); 
    jtf.setFont(police); 
    jtf.setPreferredSize(new Dimension(600, 800)); 
    background.setBounds(0,0,boardSize.width, boardSize.height); 
    jtf.setForeground(Color.BLUE); 

    board.add(jtf); 
    layeredPane.add(board, JLayeredPane.PALETTE_LAYER); 

} 

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

}

только изображение, кажется, появляются, и по какой-то причине (Мой лучший выбор темной магии) JTextField не существует. Любые идеи или помощь будут очень благодарны! Спасибо !

+0

Где вы установите размер компонента форума? –

+1

Было бы проще использовать «JPanel» в качестве фона (переопределяя его метод «paintComponent»), а затем добавляя к нему компоненты. – MadProgrammer

ответ

2

Каждый раз, когда вы полагаетесь на все, что использует макет null (например, JLayeredPane), у вас возникнут проблемы.

Вы должны использовать что-то вроде ...

board.setBounds(new Rectangle(new Point(0, 0), board.getPreferredSize())); 
layeredPane.add(board, JLayeredPane.PALETTE_LAYER); 

установить размер и расположение board.

Есть также стропила других вопросов с null макетов, которые просто делают их полная боль в коде и в конечном итоге тратить больше времени, чем они экономят ...

Честно говоря, более простым и более удобным решением будет чтобы создать пользовательский компонент, который может рисовать фоновое изображение для вас, таким образом, вы можете использовать то, что вам нужно, и не страдать от этих проблем. Прежде чем кто-нибудь скачет ко мне, используйте «можно» с помощью менеджера макетов с JLayeredPane, но это добавляет больше проблем с необходимостью перекрытия компонентов, чтобы фоновый слой мог выступать в качестве фона ... просто больше беспорядка

Кроме того, перед тем, как кто-либо прыгает со мной, вы можете использовать JLabel в качестве компонента фона, установить на нем менеджер компоновки и добавить к нему свои компоненты, но JLabel не вычисляет требуемый размер на основе дочернего элемента которые он содержит, но вместо этого использует свойства icon и text. Возможно, это не проблема, если фоновое изображение достаточно велико, но всегда кажется слабым местом, ожидающим разрыва.

Banana

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.GridBagLayout; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.border.EmptyBorder; 

public class Test { 

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

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       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.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      setLayout(new BorderLayout()); 
      BackgroundPane bgPane = new BackgroundPane(); 
      bgPane.setLayout(new GridBagLayout()); 
      add(bgPane); 

      try { 
       BufferedImage bg = ImageIO.read(new File("C:\\Users\\shane\\Dropbox\\MegaTokyo\\thumnails\\megatokyo_omnibus_1_3_cover_by_fredrin-d4oupef.jpg")); 
       bgPane.setBackgroundImage(bg); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 

      JLabel show = new JLabel("Bananas are yellow"); 
      show.setOpaque(true); 
      show.setForeground(Color.RED); 
      show.setBackground(Color.YELLOW); 
      show.setBorder(new EmptyBorder(20, 20, 20, 20)); 
      bgPane.add(show); 

     } 

    } 

    public class BackgroundPane extends JPanel { 

     private BufferedImage img; 

     @Override 
     public Dimension getPreferredSize() { 
      BufferedImage img = getBackgroundImage(); 

      Dimension size = super.getPreferredSize(); 
      if (img != null) { 
       size.width = Math.max(size.width, img.getWidth()); 
       size.height = Math.max(size.height, img.getHeight()); 
      } 

      return size; 
     } 

     public BufferedImage getBackgroundImage() { 
      return img; 
     } 

     public void setBackgroundImage(BufferedImage value) { 
      if (img != value) { 
       BufferedImage old = img; 
       img = value; 
       firePropertyChange("background", old, img); 
       revalidate(); 
       repaint(); 
      } 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      BufferedImage bg = getBackgroundImage(); 
      if (bg != null) { 
       int x = (getWidth() - bg.getWidth())/2; 
       int y = (getHeight() - bg.getHeight())/2; 
       g.drawImage(bg, x, y, this); 
      } 
     } 

    } 

} 

Эта реализация пропавшие вещи, как автоматическое масштабирование или повторение, но вы получите идею

+0

Может ли/не вызывать 'super.paintComponent()' после рисования фона? Или это не имеет значения? – Foumpie

+1

Неважно, вы хотите нарисовать фон ПОСЛЕ того, как вы вызываете 'super.paintComponent', поскольку одна из вещей, которые он делает, заполняет компонент цветом фона (поэтому важно его называть) – MadProgrammer