gpt4 book ai didi

java - JPanel 位置被 BufferStrategy 重击

转载 作者:行者123 更新时间:2023-12-02 10:38:37 26 4
gpt4 key购买 nike

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

如果我像平常一样运行程序,JPanel 会正确呈现。当然,那就没有动画了。如果我使用循环和 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();
}
}
}


public static void main(String[] args) {

Thread t1 = new Thread(new MainFrame());
t1.start();
// if I start the app this way, the JPanel draws correctly
// MainFrame a = new MainFrame();
}
}

JPanel:

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

import javax.swing.JPanel;

public 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);
}

public void init() {
}

@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 );
}
}

最佳答案

Swing 使用它自己的渲染引擎,这是一种被动实现。您试图使用自己的主动渲染引擎来规避此问题,两者将会发生冲突。

由于 BufferStrategy 属于 JFrame,因此它是在 JFrame 的范围内创建的,因此 0x0 将是该 JFrame 的左上角位置JFrame,而不是 JPanel

Swing 的渲染引擎会自动为您完成此转换。

您有两个基本选择。

  1. 不要基于 JPanel 进行渲染,而只需使用一个独立执行此操作的“渲染”类(并使用 Canvas 而不是 JFrame 作为 BufferStrategy 的基础)
  2. 使用 Swing Timer 作为主要渲染引擎

基于 Swing Timer 的示例...

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);
}
}
}

关于java - JPanel 位置被 BufferStrategy 重击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53092231/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com