【问题标题】:Scrolling through a JPanel within a JScrollingPanel在 JScrollingPanel 内滚动 JPanel
【发布时间】:2015-06-07 08:25:09
【问题描述】:

我正在尝试为我的平台游戏制作关卡编辑器,我希望我的关卡大小为 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();
    }
}

【问题讨论】:

  • 担心:scrollPane.setBounds(40, 40, 100, 100);;错误:scrollPane.getViewport().add(bottomPanel);
  • 这个JPanel contentPane = new JPanel(null);也是个很糟糕的主意

标签: java swing jpanel jscrollpane


【解决方案1】:
  1. scrollPane.getViewport().add(bottomPanel); 应该更像scrollPane.getViewportView(bottomPanel);
  2. 您不应该直接在框架上绘制,因为子组件可以在不通知父母的情况下绘制,这意味着您绘制的任何内容都可能被部分清除。相反,这种绘画应该在充当JScrollPaneJViewport 视图的自定义组件中完成。
  3. JScrollPane 需要两件事,首先,组件想要的大小(preferredSize)和视口视图的大小。如果组件没有实现Scrollable 接口,那么组件的preferredSize 也用于确定这一点。这就是为什么 JLabel 会起作用的原因。

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

详情请见How to Use Scroll Panes

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

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

【讨论】:

    【解决方案2】:

    您也可以像这样在面板中添加 JScrollPane

    JPanel p = new JPanel();
    add(new JScrollPane(p));
    

    【讨论】:

    • 对零投票的解释,1. JPanel 具有(在这种情况下,如您的代码中一样)FlowLayout,2. 此 LayoutManager 仅接受来自其子项(JScrollPane)的 PreferredSize,JScrollPane 和 JComboBox 不不知道正确返回 Dimension
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多