Russiancold
Russiancold

Reputation: 1311

Put component inside the smaller one

I wanna get Frame(640x640) with DrawCanvas(960x960) inside like this: enter image description here

So the part of DrawCanvas must be hidden and frame centered. What layout should I choose? Now I put DrawCanvas inside the frame like this:

    class extends JFrame {
        canvas = new DrawCanvas();
        canvas.setPreferredSize(new Dimension(960, 960));
        Container cp = getContentPane();
        cp.add(canvas);
        setPreferredSize(new Dimension(640, 640));
    }

Upvotes: 0

Views: 56

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

Again as stated in your previous question, a way to do this is to embed the inner component within a JScrollPane, but rid the scrollpane of scrollbars.

For example, say you had a class called DrawPanel that extended JPanel and held a 12 x 12 grid of cells, but you only wanted to show 8 x 8 of them. You could have this class implement the Scrollable interface, have its getPreferredScrollableViewportSize method return the dimensions of what you want displayed, while its getPreferredSize method would return the actual dimensions of the component:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Rectangle;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Scrollable;

@SuppressWarnings("serial")
public class DrawPanel extends JPanel implements Scrollable {
    public static final int VISIBLE_ROW_COUNT = 8;
    private static final int ROW_COUNT = 12;
    private static final Color DARK_COLOR = Color.DARK_GRAY;
    private static final Color LIGHT_COLOR = Color.WHITE;
    private int cellWidth;

    public DrawPanel(int cellWidth) {
        super(new GridLayout(ROW_COUNT, ROW_COUNT));
        this.cellWidth = cellWidth;
        Dimension prefSize = new Dimension(cellWidth, cellWidth);
        for (int i = 0; i < ROW_COUNT; i++) {
            for (int j = 0; j < ROW_COUNT; j++) {
                JPanel cell = new JPanel();
                cell.setPreferredSize(prefSize);
                Color c = i % 2 == j % 2 ? DARK_COLOR : LIGHT_COLOR;
                cell.setBackground(c);
                add(cell);

                // TODO: delete the code below. For demo/debug purposes only
                String text = String.format("[%d, %d]", j, i);
                JLabel label = new JLabel(text);
                c = c == DARK_COLOR ? LIGHT_COLOR : DARK_COLOR;
                label.setForeground(c);
                cell.add(label);
                // TODO: end delete block
            }
        }
    }

    @Override
    public Dimension getPreferredScrollableViewportSize() {
        Dimension viewportSize = new Dimension(VISIBLE_ROW_COUNT * cellWidth, VISIBLE_ROW_COUNT * cellWidth);
        return viewportSize;
    }

    @Override
    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation,
            int direction) {
        return cellWidth;
    }

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

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

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

    // note that getPreferredSize already returns the size of the 12 x 12 grid
    // since it is composed of a grid sized JPanels

}

You could then place this within your JScrollPane,

private static final int CELL_WIDTH = 80;
private DrawPanel drawPanel = new DrawPanel(CELL_WIDTH);
private JScrollPane drawPanelScrollPane = new JScrollPane(drawPanel); 

get rid of the scrollbars,

    drawPanelScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    drawPanelScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);

and scroll it to the spot where you want the upper left point:

    int x = 2 * CELL_WIDTH;
    int y = x;
    Point pt = new Point(x, y);
    drawPanelScrollPane.getViewport().setViewPosition(pt);

The example GUI:

import java.awt.BorderLayout;
import java.awt.Point;

import javax.swing.*;

@SuppressWarnings("serial")
public class FrameAGrid extends JPanel {
    private static final int CELL_WIDTH = 80;
    private DrawPanel drawPanel = new DrawPanel(CELL_WIDTH);
    private JScrollPane drawPanelScrollPane = new JScrollPane(drawPanel); 

    public FrameAGrid() {
        drawPanelScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        drawPanelScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        setLayout(new BorderLayout());
        add(drawPanelScrollPane);

        int x = 2 * CELL_WIDTH;
        int y = x;
        Point pt = new Point(x, y);
        drawPanelScrollPane.getViewport().setViewPosition(pt);
    }


    private static void createAndShowGui() {
        FrameAGrid mainPanel = new FrameAGrid();

        JFrame frame = new JFrame("FrameAGrid");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

This displays as: enter image description here

Note that the upper left hand corner is at 2, 2 not at 0, 0

Upvotes: 4

Related Questions