Вопрос по user-interface, java, swing, layout – JButtons внутри JPanels с помощью GridLayout JFrame

7

Java / Eclipse IDE здесь.

У меня есть один JFrame, который установлен в GridLayout размером NxN. N задается пользователем в виде командной строки в начале программы. Кнопки J в шаблоне NxN добавляются в окно в JPanels, устанавливаемое с помощью GridLayout (я думаю).

Каждый JButton нуждается в своем собственном JPanel, чтобы использовать GridLayout? У меня сложилось впечатление, что вы можете установить только одну JPanel для всех кнопок и установить для JPanel значение GridLayout для кнопок J. Я хочу добавить еще одну JPanel слева от массива кнопок для отображения нажатий кнопок (JLabel) и кнопку сброса в том же левом JPanel.

Вот (немного) мой код, где N задается пользователем, system является моим классом фоновых процессов, а ButtonEvent является классом для ActionListener / actionPerformed:

<code>JFrame window = new JFrame("");
GridLayout layout = new GridLayout(N,N);
window.setLayout(layout);

for (int row = 0; row < N; row++){
    for (int col = 0; col < N; col++){
        JPanel panel = new JPanel();
        JButton b = new JButton ("("+row+","+col+")");
        window.add(b).setLocation(row, col);
        panel.add(b);
        b.addActionListener(new ButtonEvent(b, system, row, col));
        window.add(panel);
    }
}

window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack();
window.setVisible(true);
</code>

И вот что у меня есть (N = 4):

http://i.imgur.com/nbQoM.png

Вот (приблизительно) то, что я ищу (N = 4):

http://i.imgur.com/SiVWO.png

Все, что мне нужно / нужно, - это два (или более) JPanel, которые настроены примерно так, как описано выше, и все менеджеры компоновки, которые я пробовал, не очень хорошо играют с макетом GridLayout JFrame.

Любые рекомендации относительно лучшего решения приветствуются.

Спасибо!

Ваш Ответ

3   ответа
7

Does each JButton need its own JPanel to use GridLayout?

Нет. Добавить и установить Layout на JFrame не делать то, что они кажутся. JFrame - это контейнеры верхнего уровня, и лучше организовать ваш контент в JPanels.

Вы должны организовать свои панели в такой форме:

----JPanel----------------------------|
| ---LeftPanel---  ---ButtonsPanel--- |
| |             |  |                | |
| |             |  |                | |
| |             |  | GridLayout(N,N)| |
| |             |  |                | |
| |             |  |                | |
| ---------------  ------------------ |
---------------------------------------

Затем добавьте JPanel в JFrame. Также ставьте панели в отдельных классах:

class BPanel extends JPanel {
    public BPanel() {
        GridLayout layout = new GridLayout(N,N, hgap, vgap);
        setLayout(layout);
        for (int row = 0; row < N; row++){
            for (int col = 0; col < N; col++){
                JButton b = new JButton ("("+row+","+col+")");
                add(b).setLocation(row, col);
                b.addActionListener(new ButtonEvent(b, system, row, col));
            }
        }
    }
}
class LeftPanel extends JPanel {
....
}

class MainFrame extends JFrame {
    public MainFrame() {
        JPanel p = new JPanel();
        p.add(new LeftPanel());
        p.add(newButtonsPanel());
        add(p);
    }
}
Да, похоже, это сработало для меня. У меня есть все мои JPanels в разных классах и один JPanel для GridLayout. Спасибо за объяснение! Avertheus
Хороший ответ. Отличное искусство ASCII! Смотрите такжеNested Layout Example.
12

Вот попробуйте этот пример кода:

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

public class LayoutExample extends JFrame
{
    private static final String INITIAL_TEXT = "Nothing Pressed";
    private static final String ADDED_TEXT = " was Pressed";
    private JLabel positionLabel;
    private JButton resetButton;
    private static int gridSize = 4;

    public LayoutExample()
    {
        super("Layout Example");
    }

    private void createAndDisplayGUI()
    {       
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        contentPane.setLayout(new FlowLayout(FlowLayout.LEFT, 20, 20));
        contentPane.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 2));

        JPanel leftPanel = new JPanel();
        leftPanel.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 2));
        leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));    
        JPanel labelPanel = new JPanel();
        positionLabel = new JLabel(INITIAL_TEXT, JLabel.CENTER);
        JPanel buttonLeftPanel = new JPanel();
        resetButton = new JButton("Reset");
        resetButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                positionLabel.setText(INITIAL_TEXT);
            }
        });
        labelPanel.add(positionLabel);
        buttonLeftPanel.add(resetButton);
        leftPanel.add(labelPanel);
        leftPanel.add(buttonLeftPanel);

        contentPane.add(leftPanel);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridLayout(gridSize, gridSize, 10, 10));
        for (int i = 0; i < gridSize; i++)
        {
            for (int j = 0; j < gridSize; j++)
            {
                JButton button = new JButton("(" + i + ", " + j + ")");
                button.setActionCommand("(" + i + ", " + j + ")");
                button.addActionListener(new ActionListener()
                {
                    public void actionPerformed(ActionEvent ae)
                    {
                        JButton but = (JButton) ae.getSource();
                        positionLabel.setText(
                            but.getActionCommand() + ADDED_TEXT);                           
                    }
                });
                buttonPanel.add(button);
            }
        }
        contentPane.add(buttonPanel);

        setContentPane(contentPane);
        pack();
        setLocationByPlatform(true);
        setVisible(true);
    }

    public static void main(String[] args)
    {
        if (args.length > 0)
        {
            gridSize = Integer.parseInt(args[0]);
        }
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new LayoutExample().createAndDisplayGUI();
            }
        });
    }
}

OUTPUT :

Start After Click

@trashgod: Спасибо, что удалили эту большую ошибку, так как теперь, по крайней мере, она будет работать, даже без предоставления аргументов :-). Мой чек раньше был бесполезен, лол.
@Avertheus: Точно, слишком верно, поэтому мне тоже понравился этот ответ, лучше, чем мой, чтобы быть правдой :-)
+1 Смотрите также это связаноexample.
Ницца! Мне нравится, как это изменяет размеры (или фактически не изменяет размер). В посте trashgod ниже объясняется, почему это так. Спасибо! Avertheus
4

Одним из преимуществ предоставления каждой кнопке (или группе кнопок) отдельной панели является то, что вложенная панель может иметь разную компоновку. В этомпримеркаждый вложенныйButtonPanel имеет значение по умолчаниюFlowLayoutТаким образом, размер кнопки остается постоянным, когда размер окружающего контейнера изменяется.

На самом деле это интересно, вот что я понял, когда прочитал первый ответ на эту ветку от @ixos, поэтому ради интереса я сел, чтобы сделать то, что хотел OP, и понял, что этоsize aspect штуковина вызывает проблемы наLeft Panel вот почему эти два отдельныхJPanelс дляJButton а такжеJLabel , но то, что вы предложили для каждогоJButton JPanelМне понравилось это :-)

Похожие вопросы