问题
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