Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
196 views
in Technique[技术] by (71.8m points)

java - Laying out a keyboard in Swing

I've been trying to reproduce this layout:

enter image description here

Here I am:

enter image description here

using:

import javax.swing.*;
import java.awt.*;

public class Keyb {

    private JFrame f = new JFrame("Keyboard");

    private JPanel keyboard = new JPanel();

    private static final String[][] key = {
        {"`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "Backspace"},
        {"Tab", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "[", "]", ""},
        {"Caps", "A", "S", "D", "F", "G", "H", "J", "K", "L", ";", "'", "Enter"},
        {"Shift", "Z", "X", "C", "V", "B", "N", "M", ",", ".", "/", "Shift", "u2191"},
        {" ", "u2190", "u2193", "u2192"}
    };

    public Keyb() {
        keyboard.setLayout(new GridBagLayout());

        JPanel pRow;
        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.WEST;
        c.weightx = 1d;

        for (int row = 0; row < key.length; ++row) {
            pRow = new JPanel(new GridBagLayout());

            c.gridy = row;

            for (int col = 0; col < key[row].length; ++col)
                pRow.add(new JButton(key[row][col]));

            keyboard.add(pRow, c);
        }

        f.add(keyboard);
    }

    public void launch() {
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.pack();
        f.setVisible(true);
    }

    public static void main(String[] args) {
        Keyb ui = new Keyb();
        ui.launch();
    }
}

How do I adjust the size of the buttons and align them perfectly, especially Tab, Caps, Shift, Backspace, Enter and the spacebar, perhaps without using the set?Size methods?

Can it be done in a better way with other layout managers?

New at Java, so any other suggestions are welcome.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

When all else fails, write it your self...

Keyboard

This uses a custom layout manager which defines a "basic" grid but allows components in a given row to expand into portions of the following column(s)...

The default cell size is defined by the largest width/height of the available components that doesn't expand beyond it's own column, makes things a little more even.

Currently the output is anchored to the top/left corner, but I'm sure you can figure out how to calculate the x/y offset needed to get it centered ;)

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.LayoutManager2;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Keyb {

    private static final Key[][] keys = new Key[][]{
        {
            createKey("`", 0, 0),
            createKey("1", 0, 1),
            createKey("2", 0, 2),
            createKey("3", 0, 3),
            createKey("4", 0, 4),
            createKey("5", 0, 5),
            createKey("6", 0, 6),
            createKey("7", 0, 7),
            createKey("8", 0, 8),
            createKey("9", 0, 9),
            createKey("0", 0, 10),
            createKey("-", 0, 11),
            createKey("=", 0, 12),
            createKey("Backspace", 0, 13, 2d)},
        {
            createKey("Tab", 1, 0, 1.5d),
            createKey("W", 1, 2),
            createKey("E", 1, 3),
            createKey("R", 1, 4),
            createKey("T", 1, 5),
            createKey("Y", 1, 6),
            createKey("U", 1, 7),
            createKey("I", 1, 8),
            createKey("O", 1, 9),
            createKey("P", 1, 10),
            createKey("[", 1, 11),
            createKey("]", 1, 12),
            createKey("", 1, 13)
        },
        {
            createKey("Caps", 2, 0, 1.5d),
            createKey("A", 2, 2),
            createKey("S", 2, 3),
            createKey("D", 2, 4),
            createKey("F", 2, 5),
            createKey("G", 2, 6),
            createKey("H", 2, 7),
            createKey("J", 2, 8),
            createKey("K", 2, 9),
            createKey("L", 2, 10),
            createKey(";", 2, 11),
            createKey("'", 2, 12),     
            createKey("Enter", 2, 13, 2d)
        },
        {
            createKey("Shift", 3, 0, 2d),
            createKey("Z", 3, 2),
            createKey("X", 3, 3),
            createKey("C", 3, 4),
            createKey("V", 3, 5),
            createKey("B", 3, 6),
            createKey("N", 3, 7),
            createKey("M", 3, 8),
            createKey(",", 3, 9),
            createKey(".", 3, 10),
            createKey("/", 3, 11),
            createKey("fill", 3, 12, 0.5d),
            createKey("u2191", 3, 13),
        },
        {
            createKey("fill", 4, 0, 4d),
            createKey(" ", 4, 1, 6d),
            createKey("fill", 4, 2, 1.5d),
            createKey("u2190", 4, 3),
            createKey("u2193", 4, 4),
            createKey("u2192", 4, 5),
        },
    };

    public static void main(String[] args) {
        new Keyb();
    }

    public Keyb() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new KeyBoardLayout());
            for (int row = 0; row < keys.length; row++) {
                for (int col = 0; col < keys[row].length; col++) {
                    Key key = keys[row][col];
                    add(createButton(key.getText()), key.getKeyConstraint());
                }
            }
        }

        protected JComponent createButton(String text) {
            JComponent comp = null;
            if (text == null || text.equalsIgnoreCase("fill")) {
                comp = new JLabel();
            } else {
                comp = new JButton(text);
            }
            return comp;
        }

    }

    public static Key createKey(String text, int x, int y, double span) {
        return new Key(text).setKeyConstraint(new KeyConstraint(x, y, span));
    }

    public static Key createKey(String text, int x, int y) {
        return new Key(text).setKeyConstraint(new KeyConstraint(x, y));
    }

    public static class Key {

        private String text;
        private KeyConstraint keyConstraint;

        public Key(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        public Key setKeyConstraint(KeyConstraint keyConstraint) {
            this.keyConstraint = keyConstraint;
            return this;
        }

        public KeyConstraint getKeyConstraint() {
            return keyConstraint;
        }

    }

    public static class KeyConstraint {

        public int row, column;
        public double span = 1d;

        public KeyConstraint(int row, int column) {
            this.row = row;
            this.column = column;
        }

        public KeyConstraint(int row, int column, double span) {
            this.row = row;
            this.column = column;
            this.span = span;
        }

    }

    public class KeyBoardLayout implements LayoutManager2 {

        private Map<Component, KeyConstraint> mapComponents;
        private Map<KeyConstraint, Component> mapConstraints;
        private Matrix<Integer, List<JComponent>> matrix = new Matrix<>(); // Virtual grid...

        private Dimension gridSize;

        public KeyBoardLayout() {
            mapComponents = new HashMap<>(25);
            mapConstraints = new HashMap<>(25);
        }

        @Override
        public void addLayoutComponent(String name, Component comp) {
            throw new UnsupportedOperationException("addLayoutComponent(String, Comp) is not supported");
        }

        @Override
        public void removeLayoutComponent(Component comp) {
            KeyConstraint kc = mapComponents.get(comp);
            mapComponents.remove(comp);
            if (kc != null) {
                mapConstraints.remove(kc);
                getCellContents(matrix, kc).remove(comp);
            }
        }

        @Override
        public Dimension preferredLayoutSize(Container parent) {
            int rowHeight = getRowHeight();
            Dimension size = new Dimension();
            size.width = getMaxRowWidth();
            size.height = rowHeight * matrix.getRowCount();
            return size;
        }

        @Override
        public Dimension minimumLayoutSize(Container parent) {
            return preferredLayoutSize(parent);
        }

        protected List<JComponent> getCellContents(Matrix matrix, KeyConstraint constraint) {
            return getCellContents(matrix, constraint.column, constraint.row);
        }

        protected List<JComponent> getCellContents(Matrix<Integer, List<JComponent>> matrix, int col, int row) {
            if (!matrix.contains(col, row)) {
                matrix.add(col, row, new ArrayList<>());
            }
            return matrix.get(col, row);
        }

        protected Dimension getGridSize() {
            if (gridSize == null) {
                int maxCellWidth = 0;
                int maxCellHeight = 0;
                for (int row = 0; row < matrix.getRowCount(); row++) {
                    for (int col = 0; col < matrix.getColumnCount(); col++) {
                        List<JComponent> cell = getCellContents(matrix, col, row);
                        int cellWidth = 0;
                        int cellHeight = 0;
                        for (JComponent comp : cell) {
                            KeyConstraint kc = mapComponents.get(comp);
                            if (kc.span == 1) {
                                cellWidth = Math.max(cellWidth, comp.getPreferredSize().width);
                            }
                            cellHeight = Math.max(cellHeight, comp.getPreferredSize().height);
                        }
                        maxCellWidth = Math.max(cellWidth, maxCellWidth);
                        maxCellHeight = Math.max(cellHeight, maxCellHeight);
                    }
                }
                gridSize = new Dimension(maxCellWidth, maxCellHeight);
            }
            return gridSize;
        }

        protected int getRowHeight() {
            Dimension size = getGridSize();
            return size.height;
        }

        protected int getRowWidth(int row) {
            int rowWidth = 0;
            for (int col = 0; col < matrix.getColumnCount(); col++) {
                Dimension size = getCellSize(col, row);
                rowWidth += size.width;
            }
            return rowWidth;
        }

        protected int getMaxRowWidth() {
            int rowWidth = 0;
            for (int row = 0; row < matrix.getRowCount(); row++) {
                rowWidth = Math.max(getRowWidth(row), rowWidth);
            }
            return rowWidth;
        }

        protected int getColumnWidth(int col) {
            int width = 0;
            for (int row = 0; row < matrix.getRowCount(); row++) {

                Dimension size = getCellSize(col, row);
                width = Math.max(size.width, width);

            }
            return width;
        }

        protected Dimension getCellSize(int col, int row) {
            List<JComponent> comps = matrix.get(col, row);
            Dimension size = new Dimension();
            size.height = getRowHeight();
            for (JComponent comp : comps) {
                Dimension subSize = getCellSize(col, row, comp);
                size.width = Math.max(size.width, subSize.width);
            }

            return size;
        }

        protected Dimension getCellSize(int col, int row, JComponent comp) {
            List<JComponent> comps = matrix.get(col, row);
            Dimension size = new Dimension();
            size.height = getRowHeight();
            int defaultWidth = getGridSize().width;
            KeyConstraint kc = mapComponents.get(comp);
            if (kc.span == 1) {
                size.width = defaultWidth;
            } else {
                int totalWidth = (int)Math.round(defaultWidth * kc.span);
                size.width = totalWidth;
            }

            return size;
        }

        @Override
        public void layoutContainer(Container parent) {
            int rowHeight = getRowHeight();
            int y = 0;
            for (int row = 0; row &

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...