Как обновить форму JInternalFrame или JPanel при нажатии кнопки, где JPanel является отдельным классом и используется в JInternalFrame

#java #swing #jframe #jpanel #jinternalframe

#java #swing #jframe #jpanel #jinternalframe

Вопрос:

Я пытаюсь создать настольное приложение с несколькими экранами внутри одного JFrame. Таким образом, каждое событие нажатия кнопки приведет нас к отдельному экрану с обновленными компонентами на экране. Пока этот подход работает для меня, но проблема, с которой я сталкиваюсь, возникает даже после использования функций «.dispose(), .repaint(), .revalidate(), .invalidate()». Похоже, что JInternalFrame или Jpanel не обновляют свои компоненты.

Который работает примерно так, как показано ниже в gif.

Стиль с вкладками

Я знаю, что JTabbedPane существует, но для моего метода JTabbedPane нежизнеспособен.

Ниже я публикую сокращенный код, копируя проблему, с которой я сталкиваюсь.

MainMenu.Java (файл с основным классом)

 package test;

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JInternalFrame;

public class MainMenu extends JFrame {

    private JPanel contentPane;
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    MainMenu frame = new MainMenu();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    public MainMenu() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 841, 522);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);
        
        JPanel panel = new JPanel();
        panel.setBounds(10, 10, 807, 63);
        contentPane.add(panel);
        panel.setLayout(new GridLayout(1, 0, 0, 0));
        
        JButton Tab1 = new JButton("Tab1");
        panel.add(Tab1);
        
        JButton Tab2 = new JButton("Tab2");
        panel.add(Tab2);
        
        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(10, 88, 807, 387);
        contentPane.add(scrollPane);
        
        JInternalFrame internalFrame1 = new JInternalFrame();
        JInternalFrame internalFrame2 = new JInternalFrame();
        
        Tab1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Panel1 panel1 = new Panel1();
                if(internalFrame1 !=null) {
                    internalFrame1.dispose();
                    panel1.invalidate();
                    panel1.revalidate();
                    panel1.repaint();
                }
                internalFrame1.setTitle("Panel 1");
                scrollPane.setViewportView(internalFrame1);
                internalFrame1.getContentPane().add(panel1);
                internalFrame1.setVisible(true);
                
            }
        });
        
        Tab2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Panel2 panel2 = new Panel2();
                if(internalFrame2 !=null) {
                    internalFrame2.dispose();
                    panel2.invalidate();
                    panel2.revalidate();
                    panel2.repaint();
                }
                internalFrame2.setTitle("Panel 2");
                scrollPane.setViewportView(internalFrame2);
                internalFrame2.getContentPane().add(panel2);
                internalFrame2.setVisible(true);
            }
        });
    }
}

  

и соответствующие файлы класса Jpanel, где внутренние фреймы
Panel1.java

 package test;

import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;

public class Panel1 extends JPanel {
    private JTextField textField;

    /**
     * Create the panel.
     */
    public Panel1() {
        setLayout(null);
        
        textField = new JTextField();
        textField.setBounds(10, 60, 430, 19);
        add(textField);
        textField.setColumns(10);
        
        JButton btnNewButton = new JButton("Example Button");
        btnNewButton.setBounds(10, 156, 430, 21);
        add(btnNewButton);

    }
}
  

Panel2.java

 package test;

import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;

public class Panel2 extends JPanel {
    private JTextField textField;

    /**
     * Create the panel.
     */
    public Panel2() {
        setLayout(null);
        
        textField = new JTextField();
        textField.setBounds(10, 60, 430, 19);
        add(textField);
        textField.setColumns(10);
        
        JButton btnNewButton = new JButton("New button2");
        btnNewButton.setBounds(21, 157, 419, 21);
        add(btnNewButton);

    }
}
  

P.S: Я впервые задаю вопрос в Stackoverflow, поэтому простите меня и, если возможно, направьте меня, если я что-то упустил

Спасибо 🙂

Редактировать: Проблема, с которой я сталкиваюсь, заключается в том, что на первый взгляд кажется, что Jpanel был обновлен, но такие компоненты, как JTextField, по-прежнему скрывают ранее написанный текст в нем и показывают текст только при нажатии на это JTextField

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

Проблема, с которой я сталкиваюсь

Комментарии:

1. Похоже, что JInternalFrame или Jpanel не обновляют свои компоненты. — Я не уверен, чего вы ожидаете. Я вижу, что заголовок и текст на кнопке меняются каждый раз, когда вы нажимаете кнопку. Это означает, что компоненты обновляются. Другие проблемы: 1) имена переменных НЕ должны начинаться с символа верхнего регистра. 2) Не используйте нулевой макет и setBounds(). Swing был разработан для использования с менеджерами компоновки. Например, нет причин использовать JScrollPane, потому что он не работает, когда добавленные в него компоненты используют нулевой макет.

2. 3) revalidate() работает только при использовании менеджера макетов. Revalidate() и repaint() вызываются в контейнере после удаления / добавления в него компонентов.

3. @camickr Спасибо за другие проблемы, которые вы нашли в моем коде. Я обновил свой вопрос и опубликовал в определенной части, в которой я столкнулся с проблемой. Если возможно, пожалуйста, взгляните на это и предложите мне возможное решение. Прошу прощения, если я что-то пропустил в ваших комментариях. Спасибо

Ответ №1:

Метод dispose() не удаляет компоненты, поэтому вы продолжаете добавлять компоненты во внутренний фрейм при использовании следующего:

 internalFrame1.getContentPane().add(panel1);
  

Вместо этого вы могли бы сделать что-то вроде:

 Container contentPane = internalFrame1.getContentPane();
contentPane.removeAll();
contentPane.add( panel1 );
contentPane.revalidate();
contentPane.repaint();
  

Ответ №2:

Вы можете использовать JPanels в Jframes, а затем использовать CardLayout для изменения панели (которая может действовать как разные экраны)

Комментарии:

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