Java: компоненты JPanel отклоняются в сторону при переключении панелей - PullRequest
0 голосов
/ 03 мая 2018

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

В моем примере я создал три панели:

  • login_page
  • home_page
  • exit_page

Если информация для входа верна, программа переключается на home_page.

Если данные для входа неверны, программа переключается на exit_page.

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

enter image description here enter image description here

Мне кажется, что я что-то упускаю, когда пытаюсь снова установить макет в конце метода actionPerformed, но несколько примеров, которые я нашел в Интернете, использовали именно этот способ.

Как установить компоненты следующей панели в правильные положения?

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class LoginForm extends JFrame implements ActionListener
{
    private JFrame frame;                               //main frame

    private JPanel login_page;                          //3 different panels/pages/states
    private JPanel home_page;
    private JPanel exit_page;

    private JLabel login_label;                         //login form components
    private JLabel username_label;
    private JLabel password_label;
    private JTextField username_text;
    private JPasswordField password_text;
    private JButton login_button;

    private JLabel home_label;                          //homepage components
    private JButton logout_button;

    private JLabel locked_label;                        //exit page components
    private JButton exit_button;

    LoginForm()                                         //initialization for the components and panels
    {                                                   
       frame = new JFrame("Login Form frame");
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


       //////////////////////////////////////////////////////
       /////////login form components initialization/////////
       //////////////////////////////////////////////////////
       login_page = new JPanel();

        login_label = new JLabel("Login label");

        username_label = new JLabel("Username");
        password_label = new JLabel("Password");

        username_text = new JTextField();
        password_text = new JPasswordField();

        login_button = new JButton("Login");
        login_button.addActionListener(this);


        login_label.setBounds(100,30,400,30);
        username_label.setBounds(80,70,200,30);
        username_text.setBounds(300,70,200,30);
        password_label.setBounds(80,110,200,30);
        password_text.setBounds(300,110,200,30);
        login_button.setBounds(150,160,100,30);


        login_page.add(login_label);
        login_page.add(username_label);
        login_page.add(username_text);
        login_page.add(password_label);
        login_page.add(password_text);
        login_page.add(login_button);
       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////


       //////////////////////////////////////////////////////
       //////////home page components initialization/////////
       //////////////////////////////////////////////////////
       home_page = new JPanel();


        home_label = new JLabel("Home label");

        logout_button = new JButton("Logout");
        logout_button.addActionListener(this);

        home_label.setBounds(100,30,400,30);
        logout_button.setBounds(150,160,100,30);

        home_page.add(home_label);
        home_page.add(logout_button);

       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////

       //////////////////////////////////////////////////////
       //////////exit page components initialization/////////
       ////////////////////////////////////////////////////// 
       exit_page = new JPanel();

        locked_label = new JLabel("You are now locked from the database");

        exit_button = new JButton("Exit");
        exit_button.addActionListener(this);

        locked_label.setBounds(100,30,400,30);
        exit_button.setBounds(150,160,100,30);

        exit_page.add(locked_label);
        exit_page.add(exit_button);
       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////



       frame.setContentPane(login_page);        //first page to get seen
       frame.setSize(550,250);                  //size of the window
       frame.setLayout(new BorderLayout());
       frame.setVisible(true);  
       frame.setResizable(false);
    }

    @Override
    public void actionPerformed(ActionEvent listener)
    {

        JButton button = (JButton) listener.getSource();

        if(button == login_button)
        {
            String name = username_text.getText();
            String password = new String(password_text.getPassword());

                if(name.equals("x") && password.equals("x"))
            {
                frame.remove(login_page);
                frame.setContentPane(home_page);
            }
            else
            {
                frame.remove(login_page);
                frame.setContentPane(exit_page);
            }
        }
        else if(button == logout_button)
        {
            frame.remove(home_page);
            frame.setContentPane(login_page);
        }
        else if (button == exit_button)
        {
            frame.dispose();
        }

        frame.setLayout(new BorderLayout());
        frame.validate();
        frame.repaint();  
    }

    public static void main(String args[])
    {
        LoginForm login = new LoginForm();
    }
}

Ответы [ 3 ]

0 голосов
/ 03 мая 2018

установить макет всех ваших JPanels на ноль. По умолчанию будет установлено FlowLayout, что является причиной проблемы.

добавить login_page.setLayout(null) после инициализации.

добавить home_page.setLayout(null) после инициализации.

добавить exit_page.setLayout(null) после инициализации.

это должно решить вашу проблему. Хотя это быстрое решение проблемы, это не правильное решение.

Установка нулевого макета не является предпочтительной в Java-качелях, потому что:

Диспетчер макетов упрощает настройку в зависимости от внешнего вида внешний вид компонентов, для разных размеров шрифта, для контейнера изменение размера, и в разных регионах. Менеджеры по раскладке также могут быть легко используется другими контейнерами, а также другими программами

Так что всегда используйте менеджер раскладки. Поэтому вместо использования оператора setBounds() для установки местоположения компонентов вручную используйте менеджер компоновки для размещения компонентов. См. здесь для получения дополнительной информации о том, как использовать различные менеджеры компоновки. Я бы предпочел GridBagLayout здесь, так как он более гибкий.

0 голосов
/ 03 мая 2018

но несколько примеров, которые я нашел в Интернете, использовали именно этот способ.

Я сомневаюсь, потому что с кодом так много проблем, что он работает только случайно.

Давайте начнем с того, как Swing был спроектирован для использования:

  1. Каждая панель должна использовать менеджер раскладки. Диспетчер макета установит размер и расположение каждого компонента, добавляемого на панель. Диспетчером макета по умолчанию для панели содержимого фрейма является BorderLayout. Диспетчером макетов по умолчанию для JPanel является FlowLayout.

  2. Обычный порядок кодирования - создать панель и установить менеджер раскладки. Затем вы добавляете компоненты на панель. Затем вы добавляете панель в рамку.

  3. Далее вы вызываете pack () и setVisible () для фрейма. Это вызовет диспетчер компоновки для всех панелей, добавленных к фрейму, и компоненты будут отображаться логически на основе правил каждого диспетчера компоновки.

  4. Теперь при изменении размера фрейма компоненты будут увеличиваться / уменьшаться в соответствии с правилами менеджера компоновки, и вы создали себе красивый динамический графический интерфейс.

Теперь, что вы делаете:

  1. Вы пытаетесь использовать setBounds (), чтобы установить размер и расположение каждого компонента. Размер - просто случайное предположение. Вы понятия не имеете, каким должен быть правильный размер. Что если вы захотите изменить шрифт на больший размер? Теперь вы начнете получать усеченный текст. Не пытайтесь устанавливать границы компонентов Swing. Каждый компонент имеет логику для определения своего предпочтительного размера.

  2. Далее вы устанавливаете панель содержимого фрейма (что нормально), но затем вы вызываете setLayout () и validate (). Вы даже знаете, что делают эти заявления?

  3. Смысл использования setLayout () состоит в том, чтобы сообщить панели, какой менеджер компоновки использовать при добавлении компонентов в фрейм, но затем никогда не добавлять какие-либо панели в фрейм.

  4. Далее вы используете validate () (который должен быть revalidate () при использовании Swing). Цель этого метода - вызвать менеджер макета. Поэтому менеджер компоновки затем сбросит размер / расположение всех компонентов и полностью проигнорирует оператор setBounds (), который вы использовали.

  5. Ваш код работает только случайно, потому что вы изменили макет на BorderLayout ПОСЛЕ того, как вы добавили панель к фрейму. Поскольку вы никогда не добавляете какие-либо компоненты во фрейм, когда он использует BorderLayout, диспетчеру компоновки делать нечего.

Итак, решение:

  1. Не использовать setBounds ().

  2. Используйте соответствующий менеджер раскладки для каждой из ваших 3 панелей.

  3. Используйте CardLayout на раме. Затем вы можете просто поменять местами каждую из вышеперечисленных панелей. Не пытайтесь изобретать велосипед.

  4. Прочтите учебник Swing по Менеджерам компоновки для получения дополнительной информации и рабочих примеров.

0 голосов
/ 03 мая 2018

ваша проблема может дать frame.setSize(550,250);

при использовании макета лучше использовать pack() после добавления всех компонентов и панелей

...