JPanel布局图像截止

时间:2010-03-17 14:10:04

标签: java swing graphics layout java-2d

我正在向JPanel添加图像,但图像正在被切断。我最初尝试BorderLayout,但只适用于一个图像,并添加其他添加图像截止。所以我切换到其他布局,我能得到的最好和最接近的是BoxLayout,但是这增加了一个非常大的截止,这是不可接受的。

所以基本上;如何将图像(从自定义JComponent)添加到自定义JPanel而不会产生诸如代码中存在的不良影响。

自定义JPanel:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.Timer;

public class GraphicsPanel extends JPanel implements MouseListener {
    private Entity test;
    private Timer timer;
    private long startTime = 0;
    private int numFrames = 0;
    private float fps = 0.0f;

    GraphicsPanel() {      
        test = new Entity("test.png");
        Thread t1 =  new Thread(test);
        t1.start();

        Entity ent2 = new Entity("images.jpg");
        ent2.setX(150);
        ent2.setY(150);
        Thread t2 = new Thread(ent2);
        t2.start();

        Entity ent3 = new Entity("test.png");
        ent3.setX(0);
        ent3.setY(150);
        Thread t3 = new Thread(ent3);
        t3.start();

        //ESSENTIAL COMMENT ANY OF THESE and you will see the problem immediately
        //You can use ANY image to reproduce the problem
        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
        add(test);
        add(ent2);
        add(ent3);

        //GAMELOOP
        timer = new Timer(30, new Gameloop(this));
        timer.start();
        addMouseListener(this);
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setClip(0, 0, getWidth(), getHeight());

        g2.setColor(Color.BLACK);
        g2.drawString("FPS: " + fps, 1, 15);
    }

    public void getFPS()
    {
        ++numFrames;
        if (startTime == 0) {
            startTime = System.currentTimeMillis();
        } else {
            long currentTime = System.currentTimeMillis();
            long delta = (currentTime - startTime);
            if (delta > 1000) {
                fps = (numFrames * 1000) / delta;
                numFrames = 0;
                startTime = currentTime;              
            }
        }
    }

    public void mouseClicked(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) { }
    public void mouseExited(MouseEvent e) { }

    class Gameloop implements ActionListener
    {
        private GraphicsPanel gp;

        Gameloop(GraphicsPanel gp) {
            this.gp = gp;
        }

        public void actionPerformed(ActionEvent e) {
            try {
                gp.getFPS();
                gp.repaint();
            } catch (Exception ez) { }
        }
    }
}

主要课程:

import java.awt.EventQueue;
import javax.swing.JFrame;

public class MainWindow
{
    public static void main(String[] args)
    {
        new MainWindow();
    }

    private JFrame frame;
    private GraphicsPanel gp = new GraphicsPanel();

    MainWindow()
    {
        EventQueue.invokeLater(new Runnable() {
            public void run() {

                frame = new JFrame("Graphics Practice");
                frame.setSize(680, 420);
                frame.setVisible(true);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                frame.add(gp);
            }
        });
    }
}

自定义JComponent

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JComponent;

public class Entity extends JComponent implements Runnable {
    private BufferedImage bImg;
    private int x = 0;
    private int y = 0;
    private int entityWidth, entityHeight;
    private String filename;

    Entity(String filename) {
        this.filename = filename;       
    }

    public void run() {
        bImg = loadBImage(filename);
        entityWidth = bImg.getWidth();
        entityHeight = bImg.getHeight();
        setPreferredSize(new Dimension(entityWidth, entityHeight));
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();

        g2d.drawImage(bImg, x, y, null);

        g2d.dispose();
    }

    public BufferedImage loadBImage(String filename) {
        try {
            bImg = ImageIO.read(getClass().getResource(filename));
        } catch (Exception e) { }
        return bImg;
    }

    public int getEntityWidth() { return entityWidth; }
    public int getEntityHeight() { return entityHeight; }

    public int getX() { return x; }
    public int getY() { return y; }
    public void setX(int x) { this.x = x; }
    public void setY(int y) { this.y = y; }
}

2 个答案:

答案 0 :(得分:2)

我注意到的一件事是您的首选尺寸计算不正确。您将首选大小设置为图像的大小。问题是你在(x,y)处绘制图像。因此,首选大小需要考虑到这一点。

否则我不明白这个问题并且运行代码没有帮助,因为我不知道你的图像大小是否应该是大,小,相同大小等。

答案 1 :(得分:1)

@camickr可能是正确的,为什么你现有的方法没有得到你想要的结果。

作为替代方案,您可以考虑在JInternalFrame内使用JDesktopPane。通过这种方式,您的图像将是可以单独移动,调整大小和滚动的文档。文章How to Use Internal Frames概述了这种实现的外观。这个example显示了一种简单的方法来交错框架并从菜单中选择它们。