lum*_*est 1 java swing image object jframe
我试图在JFrame中制作游戏,但遇到了问题.我创建了一个由四个图像组成的对象.我的问题是,我如何在JFrame中绘制这个对象?
这是代码:
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.*;
public class t4
{
static boolean running;
public static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
public static double width = screenSize.getWidth();
public static double height = screenSize.getHeight();
public static int x = ( 250 );
public static int y = ( 150 );
public static final int sx = (int)width;
public static final int sy = (int)height;
public static void main( String[] args ) throws IOException, InterruptedException
{
Image ur = new ImageIcon("redBlock.gif").getImage();
Image ll = new ImageIcon("redBlock.gif").getImage();
Image ul = new ImageIcon("blueBlock.gif").getImage();
Image lr = new ImageIcon("blueBlock.gif").getImage();
// Create game window...
JFrame app = new JFrame();
app.setIgnoreRepaint( true );
app.setUndecorated( true );
// Add ESC listener to quit...
app.addKeyListener( new KeyAdapter()
{
public void keyPressed( KeyEvent e )
{
if( e.getKeyCode() == KeyEvent.VK_ESCAPE )
running = false;
if((e.getKeyCode()==KeyEvent.VK_LEFT)||(e.getKeyCode()==KeyEvent.VK_KP_LEFT))
x-=10;
if((e.getKeyCode()==KeyEvent.VK_RIGHT)||(e.getKeyCode()==KeyEvent.VK_KP_RIGHT))
x+=10;
if((e.getKeyCode()==KeyEvent.VK_UP)||(e.getKeyCode()==KeyEvent.VK_KP_UP))
y-=10;
if((e.getKeyCode()==KeyEvent.VK_DOWN)||(e.getKeyCode()==KeyEvent.VK_KP_DOWN))
y+=10;
}
});
// Get graphics configuration...
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
// Change to full screen
gd.setFullScreenWindow( app );
if( gd.isDisplayChangeSupported() )
{
gd.setDisplayMode(new DisplayMode( sx, sy, 32, DisplayMode.REFRESH_RATE_UNKNOWN ));
}
// Create BackBuffer...
app.createBufferStrategy( 2 );
BufferStrategy buffer = app.getBufferStrategy();
// Create off-screen drawing surface
BufferedImage bi = gc.createCompatibleImage( sx, sy );
// Objects needed for rendering...
Graphics graphics = null;
Graphics2D g2d = null;
Color background = Color.BLACK;
Random rand = new Random();
// Variables for counting frames per seconds
int fps = 0;
int frames = 0;
long totalTime = 0;
long curTime = System.currentTimeMillis();
long lastTime = curTime;
running = true;
while( running )
{
try
{
// wait(500);
// count Frames per second...
lastTime = curTime;
curTime = System.currentTimeMillis();
totalTime += curTime - lastTime;
if( totalTime > 1000 )
{
totalTime -= 1000;
fps = frames;
frames = 0;
}
++frames;
// clear back buffer...
g2d = bi.createGraphics();
g2d.setColor( background );
g2d.fillRect( 0, 0, sx, sy );
// draw some rectangles...
/* int r = 45;
int g = 232;
int b = 163;
g2d.setColor( new Color(r,g,b) );
int w = ( 250 );
int h = ( 150 );
g2d.fillRect( x+25, y+25, w, h );*/
if(y<775)
{
y++;
}
else
{
y=0;
}
// display frames per second...
g2d.setFont( new Font( "Courier New", Font.PLAIN, 12 ) );
g2d.setColor( Color.GREEN );
g2d.drawString( String.format( "FPS: %s", fps ), 20, 20 );
// Blit image and flip...
graphics = buffer.getDrawGraphics();
graphics.drawImage( bi, 0, 0, null );
graphics.drawImage(ur,x,y,null);
graphics.drawImage(ll,x+50,y+50,null);
graphics.drawImage(ul,x,y+50,null);
graphics.drawImage(lr,x+50,y,null);
if( !buffer.contentsLost() )
buffer.show();
}
finally
{
// release resources
if( graphics != null )
graphics.dispose();
if( g2d != null )
g2d.dispose();
}
}
gd.setFullScreenWindow( null );
System.exit(0);
}
public static void wait(int x) throws InterruptedException
{
Thread.currentThread().sleep(x);
}
}
Run Code Online (Sandbox Code Playgroud)
我想创建一个包含图像ur,ll,ul和lr的对象,并能够在屏幕上绘制它.
这是你应该做的:
javax.swing.JComponent.paintComponent(Graphics).javax.swing.Timer以管理帧速率.getPreferredSize().首先(根据DavidB的要求)我会告诉你为什么要做这些事情,然后我会告诉你如何做.
add方法兼容(实际上,它属于Container,但这并不重要).如果您查看JavaDoc文档add,您会发现它不会接受任何文档Object ; 相反,它需要一个Component(或其子类)的实例.您可以使用子类Component代替JComponent,但Component更多的是AWT应用程序而不是Swing应用程序.JComponent因此JFrame.add将其作为参数接受.JComponent,你需要实际告诉窗口管理器要绘制什么.您可以将绘图代码放在任何位置,但请记住,除非实际调用该方法,否则不会调用(使用)它.图形环境调用以启动绘制过程的方法称为paintComponent*.如果重写此方法,则图形环境将调用您的自定义绘制代码.paintComponent因为这是图形环境所关心的.repaint每秒调用该方法指定的次数(每帧一次).这是Swing计时器的要点.你给它一个代码块和几毫秒,它将在每次指定的间隔过去时运行该代码.getPreferredSize允许您返回所需的任何大小,从而控制组件的大小.**getPreferredSize以便窗口管理器和图形环境正确地获得所有大小.*实际上并不是paintComponent这样的; 它是paint.然而,该paint方法调用paintComponent,paintBorder以及paintChildren:
此方法实际上将绘制工作委托给三个受保护的方法:paintComponent,paintBorder和paintChildren.它们按列出的顺序调用,以确保子项出现在组件本身之上.一般来说,组件及其子组件不应在分配给边框的insets区域中绘制.子类可以像往常一样覆盖此方法.一个只想专门化UI(外观)委托的paint方法的子类应该只覆盖paintComponent.
(来源:JavaDoc)
**覆盖getPreferredSize实际上并不能保证组件显示的大小.它仅指定应显示的大小.一些布局管理器会选择忽略它(例如BorderLayout).但是,当您调用pack正确调整窗口大小时,它应根据此大小计算首选大小.
要使类扩展JComponent,只需将类签名更改为:
import javax.swing.JComponent;
public class MyGameDisplay extends JComponent {
...
}
Run Code Online (Sandbox Code Playgroud)
paintComponent您需要导入java.awt.Graphics该类.请参阅此示例代码以了解如何使用paintComponent:
import javax.swing.JComponent;
import java.awt.Graphics;
public class MyGameDisplay extends JComponent {
// Some code here
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g); // this line is crucial; see below
g.drawString(100,100,"Hello world");
}
}
Run Code Online (Sandbox Code Playgroud)
注意:上面,我提到了super.paintComponent从paintComponent方法中调用的必要性.这样做的原因是它(除其他外)将清除您之前显示的所有图形.因此,例如,如果您的程序在屏幕上绘制一个圆圈,则除非您调用,否则绘图的每次迭代都将包含前一个绘图中的圆圈轨迹super.paintComponent.
Timer要获得所需的FPS速率,请修改类以包含Swing计时器,如下所示:
// Include these imports:
import javax.swing.Timer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MyGameDisplay extends JComponent {
private Timer t;
public MyGameDisplay() {
ActionListener al = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
t = new Timer(1000 / 30 /* frame rate */, al);
t.start();
}
}
Run Code Online (Sandbox Code Playgroud)
getPreferredSize覆盖的原因getPreferredSize是布局管理器将知道如何正确调整容器的大小.
虽然编写实际逻辑来计算大小可能很困难,但覆盖getPreferredSize本身并非如此.这样做:
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400); // for example
}
Run Code Online (Sandbox Code Playgroud)
完成后,您只需运行以下代码:
import javax.swing.JFrame;
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame();
MyGameDisplay mgd = new MyGameDisplay();
frame.add(mgd);
frame.pack();
frame.setVisible(true);
}
}
Run Code Online (Sandbox Code Playgroud)