3

カードレイアウトで画像を描画する際に発生した問題を説明する以前の投稿を作成しました。限られたサポートしか受けられず、問題を解決できませんでした。そのため、有効な助けが得られることを期待して、この投稿を再度説明しています。

Java ゲームのタイトル画面を作ろうとしています。私は2つのJavaファイルを作りました。最初のファイルは cardlayout をロードし、次のファイルはタイトル画面をロードします。しかし、どういうわけか、2番目のファイルで背景画像を描画できません。エラー メッセージは表示されません。単に何も描画しません。

最初のファイル:

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
    }
}

2 番目のファイル:

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

4

2 に答える 2

7

さて、あなたのコードには多くの問題があります...

まず第一に- あなたの MainScreen クラスを見てください - "MainScreen extends 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() メソッドを使用しないでください...絶対に!インターフェイスのデッドロック/スタックが発生する可能性があります。repaint を呼び出す必要がある場合は、ペイント メソッドの外で実行してください。

私はコードのその部分について話していました:

//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
}

ペイントメソッド内で必要なものをペイントするだけで、それ以上ではありません。すべての再描画ロジックは、それらの外に移動する必要があります。考えてみてください-ペイントからrepaintメソッドを呼び出しています-これにより、ペイントが再度行われ、再ペイントが行われます。

もう1つ-JFrameはJComponentを拡張しないため、「paintComponent」メソッドはJFrameでは機能しません。したがって、この方法はまったく役に立ちません。塗り方もありますが、これも使うべきではありません。背景画像を設定するには、フレーム幅のパネルを使用して背景をペイントします。その後、そのパネルに任意のコンテンツを配置できます (最後の例を見てください)。

さらに-cardContainerの上にBLACKの背景を持つdebugPanelがあります-コンテナまたはフレームに描画したものはすべて非表示になります(もう一度言います-フレーム自体にペイントしないでください、それは悪い習慣です)。そのため、不透明 (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 ();
    }
}

また、Image の代わりに ImageIcon を使用して、フレームを表示する前に画像が読み込まれるようにしました。それ以外の場合は、画像の読み込み状態を手動で確認し、読み込まれたときに背景を更新する必要があります。

PSコメントでコードを過負荷にしないでください-コードが十分にクリーンな場合は必要ありません:)

于 2012-06-04T12:29:02.867 に答える
3

これを見てください、あなたは間違った意味で描いているように思えます。あなたのコードは非常に間違った意味で書かれているようです。何も意味がありません。の をオーバーライドするときはいつでも、 に指定されたサイズを提供するのではなく、 1 つの前述の Dimension を持つことができるように、それもオーバーライドするこの 1 つの習慣的な習慣を常に作りpaintComponent(...)ます。さらに、CardLayout の実装全体がわがままです。CardLayout チュートリアルをもう一度確認する必要があるようです。JPanel/JComponentgetPreferredSize()JFrame

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);
    }
}   
于 2012-06-04T15:20:25.443 に答える