猿问

JPanel 位置被 BufferStrategy 重击

我有一个 JFrame,我向其中添加了一个 JPanel。我正在做一些动画,所以我实现了一个 BufferStrategy 来渲染。我还有一个渲染循环,以在运行时保持渲染。


如果我像往常一样运行程序,JPanel 就会正确呈现。当然,然后没有动画。如果我使用循环和 hte BufferedStrategy 运行它,则 JPanel 将扩展到应用程序的完整大小,并位于 JFrame 的标题栏下方。我找不到发生这种情况的充分理由,但这令人沮丧,因为我需要做一些精确的绘图,并且不能将其中的一些隐藏在标题栏下方。


我认为这是因为我没有调用super.paintComponent(),但无论如何我真的不应该调用它,因为我是自己渲染的,而不是在正常的 Swing 管道中。


是否需要进行一些 API 调用才能使 JPanel 在渲染调用中正确定位?


import java.awt.Graphics;

import java.awt.image.BufferStrategy;

import javax.swing.JFrame;


public class MainFrame extends JFrame implements Runnable {


    private static final long serialVersionUID = 2190062312369662956L;


    protected ViewPanel _viewPanel = null;


    public MainFrame() {

        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );


        createGui();

    }


    protected void createGui() {


        setSize( 600, 400 );

        setTitle( "Exact Positioning" );

        setVisible( true );

        setResizable( false );


        _viewPanel = new ViewPanel();

        _viewPanel.init();


        // the layout type shouldn't matter since this is the only component in the frame

        add( _viewPanel );

    }


    @Override

    public void run() {


        // setup

        this.createBufferStrategy( 2 );

        BufferStrategy buffStrategy = this.getBufferStrategy();


        // render loop

        while( true ) {


            Graphics g = null;

            try {

                g = buffStrategy.getDrawGraphics();

                _viewPanel.render( g );

            } finally {

                g.dispose();

            }

            buffStrategy.show();


            // pause a tad

            try {

                Thread.sleep( 500 );

            } catch (InterruptedException e) {

                // Required catch block

                e.printStackTrace();

            } catch (Exception e) {

                System.out.println( "Sorry, don't know what happened: " + e.toString() );

                e.printStackTrace();

            }

        }

    }


RISEBY
浏览 134回答 1
1回答

PIPIONE

Swing 使用它自己的渲染引擎,这是一种被动实现。你试图用你自己的、主动的、渲染引擎来规避这个问题,这两者会发生冲突。因为BufferStrategy属于JFrame,它是在它的范围内创建的,所以0x0将是 的左上角位置,而JFrame不是JPanel。Swing 的渲染引擎会自动为您进行这种翻译。您有两个基本选择。不要以 a 为基础进行渲染,JPanel而只是有一个独立执行此操作的“渲染”类(并使用 aCanvas而不是 theJFrame作为 的基础BufferStrategy)使用 SwingTimer作为主要渲染引擎Timer基于Swing的示例...import java.awt.Color;import java.awt.Dimension;import java.awt.EventQueue;import java.awt.Graphics;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.util.Random;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.Timer;public class Test {    public static void main(String[] args) {        new Test();    }    public Test() {        EventQueue.invokeLater(new Runnable() {            @Override            public void run() {                JFrame frame = new JFrame();                frame.add(new ViewPanel());                frame.pack();                frame.setLocationRelativeTo(null);                frame.setVisible(true);            }        });    }    public static class ViewPanel extends JPanel {        private static int APP_WIDTH = 600;        private static int APP_HEIGHT = 400;        private static final long serialVersionUID = -8019663913250286271L;        public ViewPanel() {            setBackground(Color.GRAY);            Timer timer = new Timer(5, new ActionListener() {                @Override                public void actionPerformed(ActionEvent e) {                    repaint();                }            });            timer.start();        }        public void init() {        }        @Override        public Dimension getPreferredSize() {            return new Dimension(APP_HEIGHT, APP_HEIGHT);        }        @Override        protected void paintComponent(Graphics g) {            super.paintComponent(g);            render(g);        }        // Where I do the drawing. It's called from the rendering loop in the JFrame        public void render(Graphics g) {            // refresh the background since we're not relying on paintComponent all the time            Color bgc = getBackground();            g.setColor(bgc);            g.fillRect(0, 0, APP_WIDTH, APP_HEIGHT);            // just paint a moving box            drawBox(g);            // draw a line to prove correctness. In the loop, you can see part of this line is hidden            // underneath the title bar            g.setColor(Color.red);            g.drawLine(0, 0, APP_WIDTH, APP_HEIGHT);        }        protected void drawBox(Graphics g) {            // get a random color            Random ran = new Random();            int red = ran.nextInt(255);            int grn = ran.nextInt(255);            int ble = ran.nextInt(255);            Color colour = new Color(red, grn, ble);            g.setColor(colour);            // get a random position                    int x = ran.nextInt(APP_WIDTH - 50);            int y = ran.nextInt(APP_HEIGHT - 50);            // draw it            g.fillRect(x, y, 50, 50);        }    }}
随时随地看视频慕课网APP

相关分类

Java
我要回答