我开始自学Java,我的触及可能超出了我的掌握。不过,这是最好的学习方式,对吧?
我试图玩简单的图形。我已经找到了各种关于如何将形状绘制到JFrame中的资源,并使它们起作用,但据我所知,代码总是需要进入paint方法,它会被自动调用,这意味着我可以&# 39;弄清楚如何传递它的论据。
我尝试做的是编写一些可以将坐标作为参数的代码,然后在这些坐标处放置一个简单的形状(让10×10像素的正方形)。我确信这一定是可能的,但我不能为我的生活找到方法。
代码到目前为止,纳入了@resueman和@Mikle的帮助:
public class Robots {
public static void main(String[] args) {
Window window = new Window();
window.Window();
new PlayArea();
Point p = new Point(50,50);
Entity player1 = new Entity();
player1.Entity(p);
}
}
public class Window extends JFrame{
int x;
int y;
public void Window(){
Window window = new Window();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setTitle("Robots");
window.setSize(800,600);
window.getContentPane().add(new PlayArea());
window.setLocationRelativeTo(null);
window.setBackground(Color.white);
window.setVisible(true);
}
}
public class PlayArea extends JComponent{
// I keep all added and displayed entities here for easier access
public final List<Entity> entities = new ArrayList<Entity> ();
public PlayArea(){
super();
}
public void addEntity(final Entity entity){
//add new entity and repaint area
entities.add(entity);
}
@Override
protected void paintComponent (final Graphics g)
{
super.paintComponent (g);
// Painting entities
final Graphics2D g2d = (Graphics2D) g;
for (final Entity entity : entities)
{
g2d.setPaint ( Color.BLACK );
g2d.fill (getEntityShape (entity));
}
}
protected Shape getEntityShape ( final Entity entity )
{
// Simple entity shape, you can replace it with any other shape
return new Rectangle ( entity.entPos.x - 5, entity.entPos.y - 5, 10, 10 );
}
}
public class Entity extends JComponent{
protected Point entPos = null;
public void Entity(Point p){
entPos = p;
repaint();
}
@Override
public void paintComponent (Graphics g){
super.paintComponent(g);
if (entPos != null){
g.fillRect(entPos.x, entPos.y, 10,10);
}
}
}
我希望能够在Entity类中创建一个对象,并将其放在x,y坐标的窗口中。
我最终希望能够移动实体,但是一旦我知道如何绘制实体,我就会完成这个实体!
仍未在窗口中绘制任何内容。我可能会遗漏一些非常明显的东西。
答案 0 :(得分:3)
有很多方法可以解决你的任务 以下是我想到的前两个选项:
使用自定义组件并在其中绘制所有Entity
个对象
这个实现简单快捷。 实施实体拖累也不是一个大问题。如何在这里完成绘画还有一些选择。如果您只想在该区域绘制一些简单的元素并且不想让您的代码过于复杂,这种方法很有用。
在单独的组件上绘制每个Entity
,并使用布局管理器放置它们
这很难实现,但由于Swing重新绘制优化,它将使用更少的资源并且绘制得更快。如果您的目标是大量元素或大面积区域,这种方法会好得多。但这可能对你的案件来说太过分了。
以下是第一种方法的简单示例(包括实体拖动):
public class SingleComponent extends JFrame
{
public SingleComponent () throws HeadlessException
{
super ();
setTitle ( "Robots" );
setBackground ( Color.white );
// Adding our custom component into the frame
getContentPane ().add ( new EntitiesArea () );
setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
setSize ( 800, 600 );
setLocationRelativeTo ( null );
setVisible ( true );
}
public class Entity
{
int x;
int y;
public Entity ( final int x, final int y )
{
this.x = x;
this.y = y;
}
}
public class EntitiesArea extends JComponent
{
// I keep all added and displayed entities here for easier access
public final List<Entity> entities = new ArrayList<Entity> ();
public EntitiesArea ()
{
super ();
// Adding mouse adapter that will add/drag entities
final MouseAdapter mouseAdapter = new MouseAdapter ()
{
// Currently dragged entity
private Entity dragged = null;
@Override
public void mousePressed ( final MouseEvent e )
{
// Looking for entity under mouse
Entity underPoint = null;
for ( final Entity entity : entities )
{
if ( getEntityShape ( entity ).contains ( e.getPoint () ) )
{
underPoint = entity;
break;
}
}
// Either dragging existing entity or adding new one
if ( underPoint != null )
{
dragged = underPoint;
}
else
{
addEntity ( new Entity ( e.getX (), e.getY () ) );
}
}
@Override
public void mouseDragged ( final MouseEvent e )
{
if ( dragged != null )
{
// Change entity coordinate and repaint area
dragged.x = e.getX ();
dragged.y = e.getY ();
repaint ();
}
}
@Override
public void mouseReleased ( final MouseEvent e )
{
if ( dragged != null )
{
dragged = null;
}
}
};
addMouseListener ( mouseAdapter );
addMouseMotionListener ( mouseAdapter );
}
public void addEntity ( final Entity entity )
{
// Add new entity and repaint area
entities.add ( entity );
repaint ();
}
@Override
protected void paintComponent ( final Graphics g )
{
super.paintComponent ( g );
// Painting entities
final Graphics2D g2d = ( Graphics2D ) g;
for ( final Entity entity : entities )
{
g2d.setPaint ( Color.BLACK );
g2d.fill ( getEntityShape ( entity ) );
}
}
protected Shape getEntityShape ( final Entity entity )
{
// Simple entity shape, you can replace it with any other shape
return new Rectangle ( entity.x - 20, entity.y - 20, 40, 40 );
}
}
public static void main ( final String[] args )
{
new SingleComponent ();
}
}
我没有为此示例添加任何重新优化以使其尽可能简单,但请记住,此示例中的任何操作都会重新绘制整个区域并强制从头开始绘制每个实体。在该区域出现大量元素之前,这一点甚至不会引人注意,但请确保您稍后处理优化的repaint(...)
调用,因为这是使Swing如此快速和如此好的事情之一
答案 1 :(得分:2)
虽然可以直接绘制到组件上,但这是一个非常糟糕的主意。将自动调用paint方法,并删除您绘制的任何内容 - 可能在您看到所做的更改之前。
更好的方法是创建一个自定义组件(通常只是一个jcomponent),它具有描述你想要绘制的内容的属性(在这种情况下是一个描述方形位置的点),它们被引用涂料方法。然后,当调用绘制内容的方法时,设置这些属性并调用重绘方法。
示例:
public class Example extends JPanel{
protected Point squarePos = null;
public void setSquare(Point p){
squarePos = p;
repaint()
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
if(squarePos != null){
g.setColor(Color.red);
g.fillRect(squarePos.x, squarePos.y, 10, 10);
}
}
}
答案 2 :(得分:1)
如果您想独立于演示文稿/渲染进行绘制,您可以使用BufferedImage进行绘制。您可以使用Graphics
和BufferedImage
方法获取与getGraphics()
相关联的createGraphics()
个对象。
如果以后要显示此内容,则可以使用Graphics.drawImage()
内的JComponent.paintComponent()
方法。