【问题标题】:Resize Images without JLabel不使用 JLabel 调整图像大小
【发布时间】:2016-05-24 18:00:48
【问题描述】:

我正在编写一个类似于 River-Raid 的游戏,所有图像都是用 g.drawImage(...) 绘制的。 我的问题是:当有人会调整 JFrame 的大小时,如何保持内容的纵横比,并缩放内容以适应新的窗口大小?

有没有这样的选择?我可以在不使用 JLabels 和布局的情况下做到这一点吗?如果不是,那要怎么做呢?

我在 JPanel 上绘制东西的代码

 private void doDrawing(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        drawStrings(g2);
        mapa.drawMap(g2);
        ArrayList ms = craft.getMissiles();

        for (Object m1 : ms) {
            Missile m = (Missile) m1;
            g2.drawImage(m.getImage(), m.getX(), m.getY(), this);
        }
        g2.drawImage(craft.getImage(), craft.getX(), craft.getY(), this);
        for (EnemyJet enemy : enemies) {
            g2.drawImage(enemy.getImage(), enemy.getX(), enemy.getY(), this);
        }
        for (Fuel fuel : fuels) {
            g2.drawImage(fuel.getImage(), fuel.getX(), fuel.getY(), fuel.getHeight(), fuel.getHeight(), this);
        }
        for (Obstacle o : obst) {
            g2.drawImage(o.getImage(), o.getX(), o.getY(), this);
        }
        drawStrings(g2);
    }

还有 Jpanel 构造函数:

  private void initBoard() {
        addKeyListener(new TAdapter());
        setFocusable(true);
        setBackground(Color.WHITE);
        setLayout(new GridBagLayout());
        craft = new Craft(ICRAFT_X, ICRAFT_Y);
        mapa = new Mapa();
        setMinimumSize(new Dimension(WIDTH, HEIGHT));
        initEnemiesAndAddThem();
        czas = new Timer(delay, this);
        czas.start();
    }

JFrame 构造函数:

 private void initGame()
    {
        add(new Plansza());
        setTitle("Reeevah Raaid");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(WIDTH, HEIGHT);
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
        setLocationRelativeTo(null);
        pack();
        setVisible(true);
        //setExtendedState(JFrame.MAXIMIZED_BOTH);
        //setResizable(false);
    }

【问题讨论】:

    标签: java swing


    【解决方案1】:

    你可以缩放整个东西:

    private void doDrawing(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
    
        AffineTransform originalTransform = g2.getTransform();
        g2.scale(getWidth() / (double) WIDTH, getHeight() / (double) HEIGHT);
    
        // Do all drawing here
    
        g2.setTransform(originalTransform);
    }
    

    一些注意事项:

    • 末尾的g2.setTransform(originalTransform) 很重要。 Graphics 对象不属于您 - 它可能用于绘制其他组件,因此您需要将其保持在与您提供时相同的状态。
    • WIDTH 和 HEIGHT 需要强制转换为 double,因为在 Java 中,如果任何一个除法运算的操作数是 double,则结果是 double,但如果它们都是 int,则执行整数除法,这绝对不是什么你要。 (例如,3 / (double) 2 是 1.5,但 3 / 2 正好是 1。)

    【讨论】:

    • 很抱歉,但它不起作用,因为比例可能非常大或太小,因为只有一个可见的背景,但出现的交叉点证明它们在某处可见(图像)。我喜欢这种方法,因为它适用于绘图中的所有图像,但最终比例有问题
    • 编辑:经过一些研究,发生了交叉,但没有图像可见......我厌倦了将比例乘以 0.5 或 2,看看它是否会使图像太小或太大以至于我看不到它们但它们是不可见的......
    【解决方案2】:

    任何图像都需要按如下方式绘制:

      double fct=1.0*image.getWidth()/getWidth();
      double fct2=1.0*image.getHeight()/getHeight();
      if(fct2>fct) fct=fct2;
      g2.drawImage(image, x, y, (int)(1.0*image.getWidth()/fct), (int)(1.0*image.getHeight()/fct), this);
    

    这会留下很多空白区域 - 但如果你想保持纵横比的话。

    --

    要使图像居中,请执行以下操作:

    int newWidth=(int)(1.0*image.getWidth()/fct);
    int newHeight=(int)(1.0*image.getHeight()/fct);
    g2.drawImage(image, getWidth()/2-newWidth()/2, getHeight()/2-newHeight()/2, newWidth, newHeight, this);
    

    【讨论】:

    • 效果很好,因为它实际上调整了可视部分的大小。我从图像中获取的矩形边界存在问题,它们已更改。你能告诉怎么做吗?
    • 还有,内容是向左浮动的,你能告诉jpanel如何居中吗?
    猜你喜欢
    • 2012-10-06
    • 2014-05-05
    • 2015-01-21
    • 2013-10-12
    • 1970-01-01
    • 2013-08-23
    • 2021-07-20
    • 1970-01-01
    相关资源
    最近更新 更多