java - 在 JScrollingPanel 中滚动 JPanel

标签 java swing jpanel jscrollpane

我正在尝试为我的平台游戏制作一个关卡编辑器,我希望我的关卡大小为 100 x 100 个正方形。

到目前为止,编辑器可以正常工作,但我无法滚动浏览 JPanel。我一直在玩,我做了一个小测试课来摆弄我将发布的内容。
如果你运行它,它所做的一切都会显示网格。但是,如果我交换两个变量(我会在其中评论),它可以显示图像并根据该图像的大小滚动。

我希望只为 JPanel 提供滚动功能,这样我就可以滚动我的100 x 100 方形级别

import java.awt.BorderLayout;

public class ScrollPaneJ extends JFrame {

    // setting the panels
    private JPanel contentPane;
    private JScrollPane scrollPane;

    // dimensions/ variables of the grid
    int size = 16;
    int startX = 112;
    int startY = 48;
    int width = 30;
    int height = 30;

    // this is the grid
    String[][] grid = new String[width][height];

    // this is from the full editor class
    String currentImage = new String("platform");

    ImageIcon currentBackIcon = new ImageIcon("Resources/backdirttile.jpg");

    /**
     * Launch the application.
     */
    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    // adding the scrollpane
                    ScrollPaneJ frame = new ScrollPaneJ();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public ScrollPaneJ() {

        setTitle("Scrolling Pane Application");
        setSize(new Dimension(300, 200));
        setBackground(Color.gray);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // defining the top and bottom panels, bottom is what I think I'm
        // drawing on, top is where the scrollpanel goes, I copied this code
        // from the internet and I'm not too sure how it works
        JPanel topPanel = new JPanel();
        JPanel bottomPanel = new JPanel(new GridLayout());

        bottomPanel.setLayout(new BorderLayout());
        getContentPane().add(bottomPanel);

        topPanel.setLayout(new BorderLayout());
        getContentPane().add(topPanel);

        // this is the label I was talking about
        Icon image = new ImageIcon("src/MenuDesign.jpg");
        JLabel label = new JLabel(image);

        // Create a tabbed pane
        // if you set it to say label instead of bottomPanel, you can scroll
        // through the size of the label
        scrollPane = new JScrollPane(bottomPanel);
        scrollPane.setBounds(40, 40, 100, 100);
        // set it label here as well.
        scrollPane.getViewport().add(bottomPanel);

        // I was hoping this would force the scrollbar in but it does nothing
        scrollPane
                .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scrollPane
                .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setBounds(50, 30, 300, 50);
        JPanel contentPane = new JPanel(null);
        contentPane.setPreferredSize(new Dimension(500, 400));
        contentPane.add(scrollPane);

        topPanel.add(scrollPane, BorderLayout.CENTER);
        init();
    }

    public void init() {
        // this sets the grid to empty
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                grid[x][y] = "";

            }

        }
    }

    @Override
    public void paint(Graphics g) {
        // this paints the grid
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.black);

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                g2d.drawRect(x * size + startX, y * size + startY, size, size);

                if (grid[x][y].equals("")) {

                    g2d.drawImage(currentBackIcon.getImage(),
                            x * size + startX, y * size + startY, null);

                }

                g2d.setColor(Color.black);
                g2d.drawRect((x * size) + 1 + startX, (y * size) + 1 + startY,
                        size, size);

            }
        }
    }

    public void drawTile() {
        // this isn't enabled which is why you can't paint the grid, however it
        // would change the tile of the square you're mouse is on, to the
        // current tile, it works and isn't really important for what i need
        // help with
        PointerInfo a = MouseInfo.getPointerInfo();
        Point b = a.getLocation();
        int mouseX = (int) b.getX();
        int mouseY = (int) b.getY();
        int gMX = ((mouseX - 48) / 16) - 4;
        int gMY = ((mouseY - 48) / 16) - 3;

        grid[gMX][gMY] = currentImage;
        repaint();
    }
}

最佳答案

  1. scrollPane.getViewport().add(bottomPanel); 应该更像 scrollPane.getViewportView(bottomPanel);
  2. 您不应该直接在框架上绘制,因为可以在不通知父组件的情况下绘制子组件,这意味着您绘制的内容可能会被部分删除。相反,这种绘画应该在充当 JScrollPane 的、JViewport 的 View 的自定义组件中完成。
  3. JScrollPane 需要两件事,首先是组件希望的大小(preferredSize)和视口(viewport) View 的大小。如果组件未实现 Scrollable 接口(interface),则组件的 preferredSize 也用于确定它。这就是 JLabel 起作用的原因。

JScrollPane 有一个 JViewport 作为它的主要子组件。 JViewport 应该只有一个组件,通常通过 JScrollPane#setViewportViewJViewport#setView 方法分配

JScrollPane

参见 How to Use Scroll Panes了解更多详情

创建一个扩展 JPanel 的自定义组件并覆盖它的 getPreferredSize 方法以返回您想要的组件的大小。覆盖它的 paintComponent 方法并执行自定义绘制。

将自定义绘画叠加到其他组件上更加困难

关于java - 在 JScrollingPanel 中滚动 JPanel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30691508/

相关文章:

java - 我如何在 Kryo 中检测到 "End of File"?

java - 如何以编程方式到达/触发 JEditorPane/JTextPane 内超链接的目标

java - 从其他类实例化时 JPanel 未打开

Java - JPanel 和 KeyListener 问题

java - JPanel 图像和组件

java - 单点登录范式是否遵守 HTTP 协议(protocol)规则?

java - 一般问题+如何: object that can copy another object's values?

java - 在 Java 中创建类型的通用实例

java - jtable 仅从数据库返回一行

java - 沿着路径移动对象: How to call actionPerformed only after previous actionPerformed has finished?