JTextField disappears on some pages when being static, while appearing on others

梦想与她 提交于 2020-01-14 19:44:07

问题


While working on a program, I made some of my fields static i.e. a JTextField for a E-Number. But now this field behaves not as expected, on some of my pages it appears, on some others it disappears. Since I am not very experienced working with a lot of statics, there might be a concept I am not understanding.

I have created a very simplified but working example of my program (MCVE) if you want to test it.

It shows my overview page at first - the E-Number JTextField is missing.

If you click on the search button, it shows the tracking page - with the E-Number JTextField present.

Both pages contain the same workNumberPanel and I cant find a difference, that would explain the behaviour.

So why is the E-Number JTextField present on the overview page and missing on the tracking page? Any help / explanation is appreciated!

MainProgram.java

import java.awt.CardLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;

import net.miginfocom.swing.MigLayout;

public class MainProgram extends JFrame {
    private static final long serialVersionUID = 1L;

    public static JPanel centerPanel = new JPanel();

    public static CardLayout contentCardsLayout = new CardLayout();

    OverviewPage overviewPage = new OverviewPage();
    TrackingPage trackingPage = new TrackingPage();

    public void initialize() {
        createCenterPanel();
    }

    private void createCenterPanel() {
        centerPanel.setLayout(contentCardsLayout);

        overviewPage.setName("overviewPage");
        trackingPage.setName("trackingPage");

        centerPanel.add(overviewPage, "overviewPage");
        centerPanel.add(trackingPage, "trackingPage");

        add(centerPanel, "growx, wrap");
    }

    public MainProgram() {
        setBounds(300, 50, 1200, 900);
        setLayout(new MigLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                    MainProgram window = new MainProgram();
                        window.setVisible(true);
                        window.initialize();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

OverviewPage.java

import javax.swing.JPanel;

import net.miginfocom.swing.MigLayout;

public class OverviewPage extends JPanel {
    WorkNumberPanel workNumberPanel = new WorkNumberPanel();

    private static final long serialVersionUID = 1L;

    public OverviewPage() {
        setLayout(new MigLayout());
        add(workNumberPanel, "wrap, growx");
    }
}

TrackingPage.java

import javax.swing.JPanel;

import net.miginfocom.swing.MigLayout;

public class TrackingPage extends JPanel {
    private static final long serialVersionUID = 1L;

    WorkNumberPanel equipmentNumberPanel = new WorkNumberPanel();

    public TrackingPage(){
        setLayout(new MigLayout("", "grow, fill"));
        add(equipmentNumberPanel, "wrap, growx");
    }
}

WorkNumberPanel.java

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

import net.miginfocom.swing.MigLayout;

public class WorkNumberPanel extends JPanel {
    private static final long serialVersionUID = 1L;
    private static final Integer TEXTFIELD_LENGTH = 20;

    JPanel mainWorkNumberPanel = new JPanel();

    JLabel lblWorkNumber = new JLabel("E-Nr: ");
    JLabel lblN_Number = new JLabel("N-Nr.: ");
    JLabel lblSNumber = new JLabel("W-Nr.: ");

    public static JTextField txtWorkNumber = new JTextField(TEXTFIELD_LENGTH);
    JTextField txtNNumber = new JTextField(TEXTFIELD_LENGTH);
    JTextField txtSNumber = new JTextField(TEXTFIELD_LENGTH);

    JButton btnSearchEntry = new JButton("Search");

    public WorkNumberPanel() {
        createEquipmentNumberPanel();
        btnSearchEntry.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                MainProgram.contentCardsLayout.show(MainProgram.centerPanel, "trackingPage");
            }
        });
    }

    private void createEquipmentNumberPanel() {
        setLayout(new MigLayout());
        mainWorkNumberPanel.setLayout(new MigLayout("", "[][grow, fill][][grow, fill][][grow, fill][]"));
        mainWorkNumberPanel.add(lblWorkNumber);
        mainWorkNumberPanel.add(txtWorkNumber);
        mainWorkNumberPanel.add(lblN_Number);
        mainWorkNumberPanel.add(txtNNumber);
        mainWorkNumberPanel.add(lblSNumber);
        mainWorkNumberPanel.add(txtSNumber);
        mainWorkNumberPanel.add(btnSearchEntry);

        add(mainWorkNumberPanel, "push, span, growx");
    }
}

回答1:


Probably because when you create your "pages" with this code

OverviewPage overviewPage = new OverviewPage();
TrackingPage trackingPage = new TrackingPage();

the TrackingPage will be the last one to execute the following line

mainWorkNumberPanel.add(txtWorkNumber);

in private void createEquipmentNumberPanel(), and hence that Panel will "own" the JTextField. It only makes sense that a UI component can only be at one place at any given time, otherwise things would get very strange :)

Your statement

Both pages contain the same workNumberPanel and I cant find a difference, that would explain the behaviour.

is simply not true. You are creating a new instance of WorkNumberPanel in both OverViewPage and TrackingPage when you execute the following line

WorkNumberPanel equipmentNumberPanel = new WorkNumberPanel();

So my recommendation is that you find another way of implementing what you want without using a static JTextField (or any other UI component for that matter).




回答2:


Here you instantiate a OverviewPage, then a TrackingPage .

OverviewPage overviewPage = new OverviewPage();
TrackingPage trackingPage = new TrackingPage();

Both of these classes instantiate a WorkNumberPanel .

WorkNumberPanel add the static JTextField (txtWorkNumber) to their display panel (mainWorkNumberPanel).

A single Component can't be added to several Container objects. This is what happens to your textfield, since it is static and not an instance variable.

The last addition will win, so the textfield will appear in TrackingPage only, and not in OverviewPage anymore .

Just don't make it static.




回答3:


First off you need to understand what a static field is. A static field is not related to a particular instance of an object. The field is related to the class itself.
There's quite a good explanation here and here.


Now with regards to your case. A JComponent can only be added to one panel at a time. Adding it to another will remove it from the first.

In your code you are creating multiple instances of 'WorkingNumberPanel'. When you do this you add the text fields to the panel, including the static text field txtWorkNumber. Since the field txtWorkNumber is static you are adding the same object to multiple components, which as I mentioned above will remove it from anywhere it was previously added.

One possible way of solving this would be to store the value from txtWorkNumber in a static variable and create a new instance (non-static) text field to add to the panel.



来源:https://stackoverflow.com/questions/36329164/jtextfield-disappears-on-some-pages-when-being-static-while-appearing-on-others

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