gpt4 book ai didi

java - 在 JScrollPane 中重新绘制 JPanel

转载 作者:搜寻专家 更新时间:2023-11-01 01:02:21 26 4
gpt4 key购买 nike

我正在从事的项目是一个用于玩桌面游戏的计算机间实用程序,其中的一个关键部分是交互式网格/ map 。好吧,我内置了自定义 map 创建功能,并希望屏幕能够显示非常大的 map 以及非常小的 map 。为此,我创建了一系列类,使用这些类可以显示任意大小的网格。但是我想做的是将完成此操作的 JPanel 放入 JScrollPane 中,从而为 map 创造无限空间。当我尝试执行此操作时,从 JScrollPane 中完美显示的 map 根本不会绘制。我怀疑它与图形上下文有关,但到目前为止一直无法找到解决方案。

在下面的代码中,注释滚动线并在初始化中切换 grid.draw 方法调用以查看我希望它看起来像什么。

完整代码如下:

package pac;

import javax.swing.*;
import javax.swing.text.*;

import java.awt.*;

public class MainScreen extends JFrame
{
int width, height, x, y;
Grid grid;

public static void main(String[] args)
{
MainScreen mainScreen = new MainScreen();
mainScreen.setVisible(true);
}

public MainScreen()
{
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
float factor = 1.25f;
width = (int)(dim.width / factor);
height = (int)(dim.height / factor);
x = (int)(dim.width / (factor * 8));
y = (int)(dim.height / (factor * 8));

setBounds(x,y,width,height);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("DnD Main Screen");
setVisible(true);
grid = new Grid();

JScrollPane scrollPane = new JScrollPane(grid);
scrollPane.setBounds(212,0,650,500);
scrollPane.setViewportView(grid);
add(scrollPane);
this.setLayout(null);

Thread draw = new Thread()
{
public void run()
{
while(true)
{
Graphics g = getGraphics();

grid.repaint();
//grid.paintComponents(getGraphics());

g.setColor(Color.blue);
g.fillRect(0 + 8, 0 + 30, 212, 200);
g.fillRect(863 + 8, 0 + 30, 212, 200);

g.setColor(Color.red);
g.fillRect(0 + 8, 200 + 30, 212, 375);
g.fillRect(863 + 8, 200 + 30, 212, 375);

try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
Thread.yield();
}
}
};
draw.start();
}

public class Grid extends JPanel
{
Tile[][] tiles;
public int x, y, across, down;
public int topBar = 30;
public int skinnyBar = 8;
public Grid()
{
this.setPreferredSize(new Dimension(600,600));

x=212 + skinnyBar;
y=0+topBar;
across = 13;
down = 9;
tiles = new Tile[across][down];
for(int i = 0; i<across; i++)
for(int j = 0; j<down; j++)
{
tiles[i][j] = new Tile(x+(i*50),y+(j*50),50);
}
this.setVisible(true);
}
public void paintComponents(Graphics g)
{
//super.paintComponents(g);
draw(g);
}
public void draw(Graphics g)
{
for(int i = 0; i<across; i++)
for(int j = 0; j<down; j++)
{
g.setColor(Color.black);
for(int k =0; k< 5; k++)
g.drawRect(tiles[i][j].x+k, tiles[i][j].y+k, tiles[i][j].side-k*2, tiles[i][j].side-2*k);
}
}
private class Tile
{
int x, y, side;
public Tile(int inX, int inY, int inSide)
{
x=inX;
y=inY;
side=inSide;
}
}
}

我已经为此工作了一段时间,但未能找到与我的问题足够相似的问题来找到修复方法。有什么建议吗?请谢谢。

最佳答案

1.不要对JScrollPane使用空布局,使用一些标准的LayoutManager

2.不要使用getGraphics(),此方法用于打印到打印机或将GUI作为快照保存到文件图像

3.没有理由使用draw(),在paintComponent()之前准备所有的Objects并绘制所有内容

4.大部分例子太老了,基于Thread,不要用Thread,改用Swing Timer

5.最简单的方法可以

JFrame -> JScrollPane -> JPanel -> 通过使用 GridLayout 放置所需数量的 JPanels 与所需的 Color,将这些 JPanels 放入某种类型的数组,并使用 Swing Timer 来获取 JPanel 并更改其 Backgroung

例如,必须添加 Swing Timer 以在周期内绘画

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;

public class TilePainter extends JPanel implements Scrollable {

private static final long serialVersionUID = 1L;

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {

@Override
public void run() {
JFrame frame = new JFrame("Tiles");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(new TilePainter()));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private final int TILE_SIZE = 50;
private final int TILE_COUNT = 100;
private final int visibleTiles = 10;
private final boolean[][] loaded;
private final boolean[][] loading;
private final Random random;

public TilePainter() {
setPreferredSize(new Dimension(TILE_SIZE * TILE_COUNT, TILE_SIZE * TILE_COUNT));
loaded = new boolean[TILE_COUNT][TILE_COUNT];
loading = new boolean[TILE_COUNT][TILE_COUNT];
random = new Random();
}

public boolean getTile(final int x, final int y) {
boolean canPaint = loaded[x][y];
if (!canPaint && !loading[x][y]) {
loading[x][y] = true;
Timer timer = new Timer(random.nextInt(500),
new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
loaded[x][y] = true;
repaint(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
}
});
timer.setRepeats(false);
timer.start();
}
return canPaint;
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle clip = g.getClipBounds();
int startX = clip.x - (clip.x % TILE_SIZE);
int startY = clip.y - (clip.y % TILE_SIZE);
for (int x = startX; x < clip.x + clip.width; x += TILE_SIZE) {
for (int y = startY; y < clip.y + clip.height; y += TILE_SIZE) {
if (getTile(x / TILE_SIZE, y / TILE_SIZE)) {
g.setColor(Color.GREEN);
} else {
g.setColor(Color.RED);
}
g.fillRect(x, y, TILE_SIZE - 1, TILE_SIZE - 1);
}
}
}

@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(visibleTiles * TILE_SIZE, visibleTiles * TILE_SIZE);
}

@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return TILE_SIZE * Math.max(1, visibleTiles - 1);
}

@Override
public boolean getScrollableTracksViewportHeight() {
return false;
}

@Override
public boolean getScrollableTracksViewportWidth() {
return false;
}

@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return TILE_SIZE;
}
}

关于java - 在 JScrollPane 中重新绘制 JPanel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11858348/

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