在单个 JFrame 上显示多个 JPanel 图像
Show multiple JPane images on a single JFrame
首先,我是 JFrame 和所有相关 classes 的新手,所以我仍在学习如何执行此操作。
我当前的目标是在单个 JFrame 上绘制多个图像。到目前为止,我可以 test2.png 进行绘制,但不能 test1.png。感谢任何建议或帮助理解 JFrame。这是我的主要 class:
package com.osj.oneshotjava;
import java.awt.Dimension;
import javax.swing.JFrame;
/**
*
* @author BCG04
*/
public class actorTest {
public static void main(String []args){
JFrame jFrame = new JFrame("OSJ actor test");
jFrame.setPreferredSize(new Dimension(640, 480)); // sets window size
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Actor2 Background = new Actor2(jFrame, "test1.png");
Actor2 testActor = new Actor2(jFrame, "test2.png");
jFrame.pack(); // automatically adjusts window size (also sets window size based on the maximum and minimum sizes)
jFrame.setVisible(true);
}
}
这是演员 2:
package com.osj.oneshotjava;
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
*
* @author BCG04
*/
public class Actor2 { //Purpose: make it easer to add multiple images to a single JFrame using only a single call to Actor2's constuctor rather than repeating the same section of code for each image.
private BufferedImage image = null;
private JLabel jLabel = null;
public Actor2(JFrame jFrame, String filename){
try
{ // try to load a image 'filename' into 'image'
image = ImageIO.read(new File(filename));
}
catch (Exception e)
{
e.printStackTrace(); // if loading fails, print the error
System.exit(1); // then exit with an error code 1 'unsuccessful exit'
}
ImageIcon imageIcon = new ImageIcon(image); // create a new ImageIcon that contains 'image'
JPanel jPanel = new JPanel();
jLabel = new JLabel();
jLabel.setIcon(imageIcon); // set JLabel 'jLabel' to contain 'imageIcon'
jPanel.add(jLabel);
jFrame.getContentPane().add(jPanel, BorderLayout.CENTER); // makes window visible?
}
public JLabel getJLabel(){
return jLabel;
}
}
编辑:
-删除了 Thread.sleep(1000);
和 setLocation(90, 90);
,因为它们与问题或问题无关,我最初让它们测试我是否可以移动图像。
-删除了 jLabel.setBounds
,因为它似乎什么也没做。
+添加了说明 Actor2 目标的评论。
我想阐明我的最终目标,我想创建一个使用 Java 的简单 2d 游戏。
这是一个完整的、自包含的示例,它与您所追求的很接近。用于演示布局管理器的使用。
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
public class DuelingJLabels{
public static void startGui(){
JFrame frame = new JFrame();
JPanel scene = new JPanel();
Actor red = new Actor(Color.RED);
Actor blue = new Actor(Color.BLUE);
//scene.setLayout( null );
scene.add(red.image);
scene.add(blue.image);
//scene.setPreferredSize( new Dimension(512, 512) );
frame.add(scene, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
static class Actor{
int x, y;
JLabel image;
public Actor(Color c){
BufferedImage a = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics g = a.getGraphics();
g.setColor(c);
g.fillOval(0, 0, 64, 64);
image = new JLabel();
image.setIcon(new ImageIcon(a));
image.setLocation( x, y );
image.setSize( 64, 64);
image.addMouseListener( new MouseAdapter(){
@Override
public void mouseClicked(MouseEvent evt){
x = x+64;
if(x>=448){
x = 0;
y += 64;
}
image.setLocation(x, y);
}
});
}
}
public static void main(String[] args){
EventQueue.invokeLater( DuelingJLabels::startGui );
}
}
记下 scene.setLayout(null);
行,如果您 运行 将该行的示例注释掉,那么您将看到两个并排的圆圈。那是因为我们让 swing 处理布局。 scene
是默认带有 FlowLayout
的 JPanel。
现在,当您单击圆圈时,没有任何反应*,因为我们告诉了新位置,但布局管理器重置了位置。
*实际上它们有时会移动,但如果您触发重新验证,它们就会被布局管理器移动。
所以现在删除 scene.setLayout(null);
上的评论并注意区别。
- 框架很小,我们必须手动调整它的大小才能看到我们的场景。
- 只有一个圆圈。
- 如果您单击圆圈,它会移动。
那是因为我们已经告诉 swing 不要为 JPanel 场景使用布局管理器。这意味着它不会为我们重新定位场景中的组件,也不会为我们调整大小。
注释的另一行 setPreferredSize
使场景告诉父组件它想要的大小。如果您取消对该行的注释,那么 JFrame 将不会开始非常小。您应该只将它与自定义组件一起使用,否则最终可能会与布局管理器发生冲突。
我发现另一个有用的工具是 JLayeredPane,因为它可以让您深入了解。我也觉得这个例子很好
最后,还有一个任意放置自定义图形的技巧就是@Override paintComponent。这样你就可以在你的组件上随时随地绘制任何东西。
首先,我是 JFrame 和所有相关 classes 的新手,所以我仍在学习如何执行此操作。 我当前的目标是在单个 JFrame 上绘制多个图像。到目前为止,我可以 test2.png 进行绘制,但不能 test1.png。感谢任何建议或帮助理解 JFrame。这是我的主要 class:
package com.osj.oneshotjava;
import java.awt.Dimension;
import javax.swing.JFrame;
/**
*
* @author BCG04
*/
public class actorTest {
public static void main(String []args){
JFrame jFrame = new JFrame("OSJ actor test");
jFrame.setPreferredSize(new Dimension(640, 480)); // sets window size
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Actor2 Background = new Actor2(jFrame, "test1.png");
Actor2 testActor = new Actor2(jFrame, "test2.png");
jFrame.pack(); // automatically adjusts window size (also sets window size based on the maximum and minimum sizes)
jFrame.setVisible(true);
}
}
这是演员 2:
package com.osj.oneshotjava;
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
*
* @author BCG04
*/
public class Actor2 { //Purpose: make it easer to add multiple images to a single JFrame using only a single call to Actor2's constuctor rather than repeating the same section of code for each image.
private BufferedImage image = null;
private JLabel jLabel = null;
public Actor2(JFrame jFrame, String filename){
try
{ // try to load a image 'filename' into 'image'
image = ImageIO.read(new File(filename));
}
catch (Exception e)
{
e.printStackTrace(); // if loading fails, print the error
System.exit(1); // then exit with an error code 1 'unsuccessful exit'
}
ImageIcon imageIcon = new ImageIcon(image); // create a new ImageIcon that contains 'image'
JPanel jPanel = new JPanel();
jLabel = new JLabel();
jLabel.setIcon(imageIcon); // set JLabel 'jLabel' to contain 'imageIcon'
jPanel.add(jLabel);
jFrame.getContentPane().add(jPanel, BorderLayout.CENTER); // makes window visible?
}
public JLabel getJLabel(){
return jLabel;
}
}
编辑:
-删除了 Thread.sleep(1000);
和 setLocation(90, 90);
,因为它们与问题或问题无关,我最初让它们测试我是否可以移动图像。
-删除了 jLabel.setBounds
,因为它似乎什么也没做。
+添加了说明 Actor2 目标的评论。
我想阐明我的最终目标,我想创建一个使用 Java 的简单 2d 游戏。
这是一个完整的、自包含的示例,它与您所追求的很接近。用于演示布局管理器的使用。
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
public class DuelingJLabels{
public static void startGui(){
JFrame frame = new JFrame();
JPanel scene = new JPanel();
Actor red = new Actor(Color.RED);
Actor blue = new Actor(Color.BLUE);
//scene.setLayout( null );
scene.add(red.image);
scene.add(blue.image);
//scene.setPreferredSize( new Dimension(512, 512) );
frame.add(scene, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
static class Actor{
int x, y;
JLabel image;
public Actor(Color c){
BufferedImage a = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics g = a.getGraphics();
g.setColor(c);
g.fillOval(0, 0, 64, 64);
image = new JLabel();
image.setIcon(new ImageIcon(a));
image.setLocation( x, y );
image.setSize( 64, 64);
image.addMouseListener( new MouseAdapter(){
@Override
public void mouseClicked(MouseEvent evt){
x = x+64;
if(x>=448){
x = 0;
y += 64;
}
image.setLocation(x, y);
}
});
}
}
public static void main(String[] args){
EventQueue.invokeLater( DuelingJLabels::startGui );
}
}
记下 scene.setLayout(null);
行,如果您 运行 将该行的示例注释掉,那么您将看到两个并排的圆圈。那是因为我们让 swing 处理布局。 scene
是默认带有 FlowLayout
的 JPanel。
现在,当您单击圆圈时,没有任何反应*,因为我们告诉了新位置,但布局管理器重置了位置。 *实际上它们有时会移动,但如果您触发重新验证,它们就会被布局管理器移动。
所以现在删除 scene.setLayout(null);
上的评论并注意区别。
- 框架很小,我们必须手动调整它的大小才能看到我们的场景。
- 只有一个圆圈。
- 如果您单击圆圈,它会移动。
那是因为我们已经告诉 swing 不要为 JPanel 场景使用布局管理器。这意味着它不会为我们重新定位场景中的组件,也不会为我们调整大小。
注释的另一行 setPreferredSize
使场景告诉父组件它想要的大小。如果您取消对该行的注释,那么 JFrame 将不会开始非常小。您应该只将它与自定义组件一起使用,否则最终可能会与布局管理器发生冲突。
我发现另一个有用的工具是 JLayeredPane,因为它可以让您深入了解。我也觉得这个例子很好
最后,还有一个任意放置自定义图形的技巧就是@Override paintComponent。这样你就可以在你的组件上随时随地绘制任何东西。