在JScrollPane中重新绘制JPanel [英] Repainting a JPanel in a JScrollPane

查看:109
本文介绍了在JScrollPane中重新绘制JPanel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The project that I am working on is an inter-computer utility for playing table top games, and a key part of that is an interactive grid/map. Well I have built in functionality for custom map creation, and want the screen to be able to display very large maps, as well as very small maps. To this effect I have created a series of classes with which I can display a grid of any size. However what I would like to do is to put the JPanel which this is accomplished with into a JScrollPane, thereby making infinite space for a map. When I try to do this the map that displays perfectly out of a JScrollPane does not paint at all. I suspect that it has to do with the Graphics context but have thus far been unable to find the solution.

在下面的代码中,标记滚动线并在初始化中切换grid.draw方法调用,以查看其外观.

In the following code, remark the scroll lines and switch the grid.draw method calls in the initialization to see what I would like it to look like.

完整代码如下:

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

}

一段时间以来,我一直在努力,并且没有发现足够类似的问题来找到解决方案.有什么建议吗?请,谢谢.

I have been working on this a while and have not been able to find and problems similar enough to mine to find the fix. Any advice? Please and thank you.

推荐答案

1.不要对JScrollPan e使用null布局,请使用某些标准LayoutManager

1.don't use null layout for JScrollPane, use some of Standard LayoutManager,

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

2.don't use getGraphics(), this method is for printing to the printer or for save GUI as snapshot to the image of file

3.没有理由使用draw()来预先准备所有Objects并在paintComponent()

3.there no reason to use draw(), to prepare all Objects before and painting everything inside paintComponent()

4.大多数示例都太旧了,基于Thread,请勿使用Thread,而应使用Swing Timer

4.most of examples are too old, based on Thread, don't use Thread, use Swing Timer instead

5.最简便的方法

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

JFrame -> JScrollPane -> JPanel -> by using GridLayout to put there required amount of JPanels with desired Color, put these JPanels to the some type of array and by using Swing Timer to pick up JPanel from array and to change its Backgroung

例如,必须添加Swing Timer才能进行定期印刷

example, have to add Swing Timer for paiting on period

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

这篇关于在JScrollPane中重新绘制JPanel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆