我之前的帖子解释了我在卡片布局中绘制图像的问题。我得到了有限的帮助,并没有解决问题。所以我在这篇文章中再次解释它,希望得到一些有效的帮助。
我正在尝试为我的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
}
}
答案 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);
}
}