Установите макет панели в CardLayout

Я пытаюсь создать пользовательский интерфейс для воображаемого автомобиля с автоматическим и ручным режимами. Когда пользователь устанавливает транспортное средство в один из режимов, он должен отображать только элементы управления, относящиеся к этому режиму, и я сделал это, используя CardLayout.

Однако я также хотел бы иметь возможность указать расположение различных элементов макета для каждой карты вручную - для статического макета я бы сделал что-то вроде mainPanel.setLayout(null), но это просто дает пустое окно при использовании на CardLayout (отсюда и две закомментированные строки в приведенном ниже коде).

Как мне достичь обеих этих целей? Мой текущий код ниже:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class UI extends JFrame implements ActionListener{

public UI() {
    initUI();
}

private JPanel cardPanel;
private CardLayout cardLayout = new CardLayout();

public final void initUI() {

    cardPanel = new JPanel();
    cardPanel.setLayout(cardLayout);

    JPanel manualPanel = new JPanel();
    getContentPane().add(manualPanel);
    //manualPanel.setLayout(null);
    cardPanel.add(manualPanel, "manual");

    JPanel autoPanel = new JPanel();
    //autoPanel.setLayout(null);
    cardPanel.add(autoPanel, "auto");

    JButton startButton = new JButton("START/STOP");
    startButton.setBounds(50, 150, 200, 50);
    startButton.addActionListener(new startListener());
    manualPanel.add(startButton);
    autoPanel.add(startButton);

    JButton autoButton = new JButton("SWITCH TO AUTO");
    autoButton.setBounds(50, 250, 200, 50);
    autoButton.addActionListener(new autoListener());
    manualPanel.add(autoButton);

    JButton upButton = new JButton("^");
    upButton.setBounds(125, 320, 50, 50);
    upButton.addActionListener(new returnListener());
    manualPanel.add(upButton);

    JButton downButton = new JButton("\\/");
    downButton.setBounds(125, 380, 50, 50);
    downButton.addActionListener(new returnListener());
    manualPanel.add(downButton);

    JButton ccwButton = new JButton("<-");
    ccwButton.setBounds(55, 350, 50, 50);
    ccwButton.addActionListener(new returnListener());
    manualPanel.add(ccwButton);

    JButton cwButton = new JButton("->");
    cwButton.setBounds(195, 350, 50, 50);
    cwButton.addActionListener(new returnListener());
    manualPanel.add(cwButton);

    JButton ngzButton = new JButton("SOMETHING ELSE");
    ngzButton.setBounds(50, 450, 200, 50);
    ngzButton.addActionListener(new returnListener());
    manualPanel.add(ngzButton);

    JButton manualButton = new JButton("SWITCH TO MANUAL");
    manualButton.setBounds(50, 250, 200, 50);
    manualButton.addActionListener(new manualListener());
    autoPanel.add(manualButton);

    JButton returnButton = new JButton("SOMETHING ELSE");
    returnButton.setBounds(50, 350, 200, 50);
    returnButton.addActionListener(new returnListener());
    autoPanel.add(returnButton);

    setTitle("UI");
    setSize(800, 600);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    add(cardPanel, BorderLayout.NORTH);
}

public static void main(String[] args) {

    UI ui = new UI();
    ui.setVisible(true);
}

public void actionPerformed(ActionEvent e){
}

private class returnListener implements ActionListener {
    public void actionPerformed (ActionEvent event) {
    }
}

private class autoListener implements ActionListener {
    public void actionPerformed (ActionEvent event) {
        cardLayout.show(cardPanel, "auto");
    }
}

private class startListener implements ActionListener {
    public void actionPerformed (ActionEvent event) {
    }
}

private class manualListener implements ActionListener {
    public void actionPerformed (ActionEvent event) {
        cardLayout.show(cardPanel, "manual");
    }
}


}

person DTR    schedule 21.08.2015    source источник


Ответы (1)


В вашем примере вы создаете startButton, но затем пытаетесь добавить один и тот же экземпляр на две разные панели. Поскольку компонент может занимать только один контейнер, вам потребуется создать две кнопки, по одной для каждой панели.

Кроме того, вместо использования макета null дайте каждой панели BorderLayout, добавьте кнопки в JPanel со значением по умолчанию FlowLayout и добавьте панель кнопок в SOUTH. Затем вы можете вложить свои иллюстрации в CENTER, используя любой подходящий макет.

Приложение: как @Frakcool комментирует, используя макет улучшит кроссплатформенный внешний вид ваших кнопок. Вызовите pack() в окружающем окне и переопределите getPreferredSize() на вложенной панели иллюстраций, чтобы придать ей необходимый размер. В этом связанном примере панель CENTER используется только для рисования; не имея компонентов, его расположение становится неактуальным.

person trashgod    schedule 21.08.2015
comment
Спасибо за указание на это, но это не решает основную проблему. Например, удаление строки autoPanel.add(startButton); на данный момент по-прежнему не приведет к тому, что элементы будут соблюдать setBounds() — пользовательский интерфейс либо игнорирует границы с кодом как есть, либо показывает пустое окно, если две строки с комментариями раскомментированы. - person DTR; 21.08.2015
comment
Метод @DTR setBounds() означает макет null, который не является лучшим вариантом для создания приложения, поскольку он может генерировать визуальные ошибки из-за разных платформ/разрешений экрана и т. д. Вместо этого используйте Диспетчер компоновки, как уже сказал трэшбод с BorderLayout Таким образом, ваш код должен работать нормально. Я мог бы попробовать помочь с этим, когда буду дома еще через 6 часов, если вы еще не решили его. - person Frakcool; 21.08.2015
comment
Попробуйте предложенные макеты и вызовите pack(); переопределите getPreferredSize() на вложенной панели иллюстраций, чтобы придать ей размер, необходимый для ваших иллюстраций. - person trashgod; 21.08.2015
comment
В этом связанном примере панель CENTER используется только для рисования; не имея компонентов, его расположение не имеет значения. - person trashgod; 21.08.2015
comment
Я рад, что это помогло! :) Что ж, удачи - person Frakcool; 21.08.2015