Cardlayout画

时间:2012-06-04 09:52:19

标签: java image swing paintcomponent cardlayout

我之前的帖子解释了我在卡片布局中绘制图像的问题。我得到了有限的帮助,并没有解决问题。所以我在这篇文章中再次解释它,希望得到一些有效的帮助。

我正在尝试为我的java游戏制作标题画面。我制作了两个java文件。第一个文件加载cardlayout,下一个文件加载标题屏幕。但不知何故,在第二个文件中,我无法得到它来绘制我的背景图像。我没有收到任何错误消息。它根本不会画任何东西。

第一档:

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

public class MainScreen extends JFrame{

    public static CardLayout cardLayout = new CardLayout();//set a new cardlayout

    // *** JPanel to hold the "cards" and to use the CardLayout:
    static JPanel cardContainer = new JPanel(cardLayout);//some variable for the cardlayout
    public static JComboBox cardCombo = new JComboBox();//some variable for the cardlayout
    public static JPanel comboPanel = new JPanel();;//some variable for the cardlayout
    Image background = Toolkit.getDefaultToolkit().createImage("data/images/title.png");//loads the background image

    public MainScreen() {

        JFrame frame = new JFrame();
        frame.setTitle("Project");//Title of the screen
        frame.setSize(800,600);//Size of the window
        frame.setResizable(false);//Is the window resizable?
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//Exit the frame when the default red cross is clicked
        frame.setVisible(true);//is the frame visible?
        frame.getContentPane().add(cardContainer, BorderLayout.CENTER);//add the cardcontainer to flip panels
        frame.setLocationRelativeTo(null);
    }

    public static void debug(){//makes an extra card, this is a debug card and is not used for anything but debugging

        JPanel debugPanel = new JPanel(new BorderLayout());//Debug panel, not used for anything, script does not work if not here
        debugPanel.setBackground(Color.BLACK);//set the background color to black
        String debug = "Debug Panel";//name the card or something like that
        cardContainer.add(debugPanel, debug);//add the card to the panel
        cardCombo.addItem(debug);//add the item??
    }

    public static void main(String[] args){//this runs when the script opens

        new MainScreen();//run the main screen class, that loads the window and card layout
        debug();//run the next class that initializes the mainmenu
        new MainMenu(null);//load the main menu
    }
}

第二档:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class MainMenu extends JPanel{

    Image background = Toolkit.getDefaultToolkit().createImage("data/images/title.png");//loads the background image

    public MainMenu(MainScreen frame){
        JPanel menuPanel = new JPanel();//This is the menu panel, where the main menu is loaded
        menuPanel.setBackground(Color.BLACK);//set the background color to black
        String menu = "Menu Panel";//name the card or something
        MainScreen.cardContainer.add(menuPanel, menu);//add the card to the panel
        MainScreen.cardCombo.addItem(menu);//add the item??
        MainScreen.cardLayout.show(MainScreen.cardContainer, menu);//choose what card to show. For this instance show the mainmenu
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(background, 0, 0, null);
        repaint();
    }

}

修改

  

您能否提取具有图像显示的代码的确切部分   进入SSCCE的问题?并将链接附加到使用过的图像 - 它   可能已损坏,在这种情况下,问题不在代码内。

你去吧

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

public class MainScreen extends JFrame{

    public static CardLayout cardLayout = new CardLayout();//set a new cardlayout

    // *** JPanel to hold the "cards" and to use the CardLayout:
    static JPanel cardContainer = new JPanel(cardLayout);//some variable for the cardlayout
    public static JComboBox cardCombo = new JComboBox();//some variable for the cardlayout
    public static JPanel comboPanel = new JPanel();;//some variable for the cardlayout
    Image background = Toolkit.getDefaultToolkit().createImage("data/images/title.png");//loads the background image

    public MainScreen() {

        JFrame frame = new JFrame();
        frame.setTitle("Project");//Title of the screen
        frame.setSize(800,600);//Size of the window
        frame.setResizable(false);//Is the window resizable?
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//Exit the frame when the default red cross is clicked
        frame.setVisible(true);//is the frame visible?
        frame.getContentPane().add(cardContainer, BorderLayout.CENTER);//add the cardcontainer to flip panels
        frame.setLocationRelativeTo(null);
    }

    public static void debug(){//makes an extra card, this is a debug card and is not used for anything but debugging

        JPanel debugPanel = new JPanel(new BorderLayout());//Debug panel, not used for anything, script does not work if not here
        debugPanel.setBackground(Color.BLACK);//set the background color to black
        String debug = "Debug Panel";//name the card or something like that
        cardContainer.add(debugPanel, debug);//add the card to the panel
        cardCombo.addItem(debug);//add the item??

        JPanel titlePanel = new JPanel(new BorderLayout());//Debug panel, not used for anything, script does not work if not here
        titlePanel.setBackground(Color.BLACK);//set the background color to black
        String title = "Title Panel";//name the card or something like that
        cardContainer.add(titlePanel, title);//add the card to the panel
        cardCombo.addItem(title);//add the item??

        cardLayout.show(cardContainer, title);//choose what card to show. For this instance show the mainmenu
    }

    public static void main(String[] args){//this runs when the script opens

        new MainScreen();//run the main screen class, that loads the window and card layout
        debug();//run the next class that initializes the mainmenu
    }

    //Here the i try to paint the image. No error messages show.
    public void paintComponent(Graphics g){//<-------------HERE
        g.drawImage(background, 0, 0, null);//<-------------HERE
        repaint();//<-------------HERE
    }
}

对于图片: http://i.stack.imgur.com/F3nHF.png

2 个答案:

答案 0 :(得分:7)

嗯,您的代码中存在很多问题......

首先 - 看看你的MainScreen类 - “MainScreen扩展JFrame” - 你不要将它用作主框架。您可以在其构造函数中创建新的单独JFrame:

public MainScreen() {

    JFrame frame = new JFrame();
    frame.setTitle("Project");//Title of the screen
    frame.setSize(800,600);//Size of the window
    frame.setResizable(false);//Is the window resizable?
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//Exit the frame when the default red cross is clicked
    frame.setVisible(true);//is the frame visible?
    frame.getContentPane().add(cardContainer, BorderLayout.CENTER);//add the cardcontainer to flip panels
    frame.setLocationRelativeTo(null);
}

请改为:

public MainScreen ()
{
    super();
    setTitle ( "Project" );//Title of the screen
    setSize ( 800, 600 );//Size of the window
    setResizable ( false );//Is the window resizable?
    setDefaultCloseOperation (
            JFrame.EXIT_ON_CLOSE );//Exit the frame when the default red cross is clicked
    setVisible ( true );//is the frame visible?
    getContentPane ()
            .add ( cardContainer, BorderLayout.CENTER );//add the cardcontainer to flip panels
    setLocationRelativeTo ( null );
    repaint (  );
}

如果你覆盖它,你的“paint()”方法(不是paintComponent())将会起作用。

下一个问题 - 永远不要在paint *方法中使用repaint()方法......永远不要!它可能会导致界面死锁/卡住。如果你需要调用重绘 - 在paint方法之外做。

我在谈论代码的这一部分:

//Here the i try to paint the image. No error messages show.
public void paintComponent(Graphics g){//<-------------HERE
    g.drawImage(background, 0, 0, null);//<-------------HERE
    repaint();//<-------------HERE
}

只需在绘画方法中绘制任何你需要的东西,而不是更多。所有重绘逻辑都应移到它们之外。试想一下 - 你是从油漆中调用重绘方法 - 这将再次导致油漆,而不是再次重新粉刷e.t.c。

再一次 - 您的“paintComponent”方法将无法在JFrame上运行,因为JFrame不会扩展JComponent。所以这种方法完全没用。有一种绘画方法,但你也不应该使用它。要设置背景图像 - 使用一些框架范围的面板并在其上绘制背景。之后,您可以在该面板上放置任何内容(最后查看示例)。

还有更多 - 你的调试板上有黑色背景而不是cardContainer - 它会隐藏你在容器或框架上绘制的任何东西(我会再说一遍 - 不要在框架上画画,这是一个糟糕的习惯)。因此,您必须通过将opaque(setOpaque)设置为false来禁用位于背景上的组件中的任何背景。您可以将cardContainer背景设置为BLACK,然后在其上绘制图像。

最后一个 - 确保“data / images / title.png”路径与您的应用程序工作目录相关。我总是用另一种方式加载图片:

Toolkit.getDefaultToolkit ()
        .createImage ( MainScreen.class.getResource ( "some/path/image.png" ) );

此代码将加载相对于包内类位置放置的图像。这样,您可以在最终应用程序jar中包含任何图像而不会出现任何问题。但这只是一个建议。

在框架内绘制背景的最终代码:

public class MainScreen extends JFrame
{
    public JPanel comboPanel;
    public JComboBox cardCombo;

    public CardLayout cardLayout;
    public JPanel cardContainer;

    public static ImageIcon background =
            new ImageIcon ( MainScreen.class.getResource ( "icons/title.png" ) );

    public MainScreen ()
    {
        super ();
        setTitle ( "Project" );

        comboPanel = new JPanel ();
        cardCombo = new JComboBox ();

        cardLayout = new CardLayout ();
        cardContainer = new BackgroundPanel ( cardLayout );
        cardContainer.setOpaque ( true );
        cardContainer.setBackground ( Color.BLACK );
        getContentPane ().add ( cardContainer, BorderLayout.CENTER );

        initializeGUI ();

        setSize ( 800, 600 );
        setResizable ( false );
        setLocationRelativeTo ( null );
        setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
        setVisible ( true );
    }

    public void initializeGUI ()
    {
        JPanel debugPanel = new JPanel ( new BorderLayout () );
        debugPanel.setOpaque ( false );
        String debug = "Debug Panel";
        cardContainer.add ( debugPanel, debug );
        cardCombo.addItem ( debug );

        JPanel titlePanel = new JPanel ( new BorderLayout () );
        titlePanel.setOpaque ( false );
        String title = "Title Panel";
        cardContainer.add ( titlePanel, title );
        cardCombo.addItem ( title );

        cardLayout.show ( cardContainer, title );
    }

    private class BackgroundPanel extends JPanel
    {
        public BackgroundPanel ( LayoutManager layout )
        {
            super ( layout );
        }

        protected void paintComponent ( Graphics g )
        {
            super.paintComponent ( g );
            g.drawImage ( background.getImage (), 0, 0, BackgroundPanel.this );
        }
    }

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

我还使用ImageIcon代替Image来确保在显示帧之前加载图像。否则,您必须手动检查图像加载状态,并在加载后更新背景。

P.S。不要使用注释重载代码 - 如果代码足够干净则不需要它们:)

答案 1 :(得分:3)

看看这个,你好像在我看来,好像你画错了。在我看来,你的代码写得非常错误,没有任何意义。每当你覆盖paintComponent(...) JPanel/JComponent的{​​{1}}时,总是让这个习惯性的习惯覆盖它getPreferredSize(),这样它就可以有一个所谓的Dimension,而不是提供指定的大小到你的JFrame。此外,您的CardLayout的整个实现是任性的,似乎您需要再次遍历CardLayout Tutorials

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*;

public class DrawingImage
{
    private void displayGUI()
    {
        JFrame frame = new JFrame("Drawing Image Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        CustomPanel contentPane = new CustomPanel();
        frame.getContentPane().add(contentPane);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new DrawingImage().displayGUI();
            }
        });
    }
}

class CustomPanel extends JPanel
{
    private BufferedImage background;

    public CustomPanel()
    {
        try
        {
            background = ImageIO.read(new java.net.URL("http://i.stack.imgur.com/F3nHF.png"));
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    @Override       
    public Dimension getPreferredSize()
    {
        return (new Dimension(800, 600));
    }

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