Working with layout managers

假如想象 提交于 2019-12-25 18:33:37

问题


I'm trying to make a kitchen display system using a FlowLayout and I'm trying to figure out a way to add another panel on the 2nd row when the first row is already full. The width of the GUI will change according to user preference. When wider, it should show more of the components per row.


回答1:


Approach - Variable width with WrapLayout

The GridLayout solution presumes the GUI requires 6 components per row.

For as many cols as needed to fill the width, & then show the components in as many rows as required, look to WrapLayout.

Approach - Variable width with JList

A JList can also be used here, since it seems all the components consist of a single (GUI) object.

import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.border.*;

public class ListComponents {

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                String[] listData = {
                    "Component 1", "Component 2", "Component 3",};
                final DefaultListModel<String> model
                        = new DefaultListModel<String>();
                for (String datum : listData) {
                    model.addElement(datum);
                }
                JList list = new JList(model);
                list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
                list.setVisibleRowCount(-1);
                list.setCellRenderer(new ObjectCellRenderer());

                Action addAction = new AbstractAction("Add New") {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        model.addElement("New Component");
                    }
                };
                JButton addNew = new JButton(addAction);

                JPanel ui = new JPanel(new BorderLayout(3, 3));
                ui.setBorder(new EmptyBorder(4, 4, 4, 4));
                ui.add(new JScrollPane(list), BorderLayout.CENTER);

                ui.add(addNew, BorderLayout.PAGE_START);

                JFrame f = new JFrame("Component List");
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setContentPane(ui);
                f.pack();
                f.setLocationByPlatform(true);
                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }

}

class ObjectCellRenderer extends DefaultListCellRenderer {

    Border border = new EmptyBorder(20, 5, 20, 5);

    public Component getListCellRendererComponent(
            JList list,
            Object value,
            int index,
            boolean isSelected,
            boolean cellHasFocus) {
        JLabel label = (JLabel) super.getListCellRendererComponent(
                list, value, index, isSelected, cellHasFocus);
        label.setBorder(border);
        return label;
    }
}

Approach - Fixed width with GridLayout

Using a GridLayout, when we know we always want a fixed number per row, regardless of width.

JPanel mainPanel = new JPanel(new GridLayout(0,6));

See new GridLayout(rows,cols):

Creates a grid layout with the specified number of rows and columns. All components in the layout are given equal size.

One, but not both, of rows and cols can be zero, which means that any number of objects can be placed in a row or in a column.

See this code for an example using a GridLayout(0,2) for the labels beneath Add Another Label




回答2:


You can use a FlowLayout. From the tutorial How to Use FlowLayout:

The FlowLayout class puts components in a row, sized at their preferred size. If the horizontal space in the container is too small to put all the components in one row, the FlowLayout class uses multiple rows. If the container is wider than necessary for a row of components, the row is, by default, centered horizontally within the container.

EDIT If you want your layout to scroll vertically when there are too many rows, you can use a JScrollPane with horizontal scrolling disabled. You can do that with:

js.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

(where js is the JScrollPane that contains your FlowLayout panel).

EDIT 2 Well, the above isn't enough. You also need to set a viewport view on the JScrollPane that will track the JScrollPane width. Here's a class that does this (taken from here):

static class MyPanel extends JPanel implements Scrollable{

    @Override
    public Dimension getPreferredScrollableViewportSize() {

        return this.getPreferredSize();
    }

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

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

    /*
     * (non-Javadoc)
     * @see javax.swing.Scrollable#getScrollableTracksViewportWidth()
     */
    @Override
    public boolean getScrollableTracksViewportWidth() {
        return true;
    }

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

}

You would use this by adding your current FlowLayout layout to an instance of MyPanel (instead of directly to the JScrollPane) and then calling

js.setViewportView(myPanelInstance);


来源:https://stackoverflow.com/questions/26080696/working-with-layout-managers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!