Search code examples
javaswingjbuttonjscrollpanejtextfield

Java can't focus on JTextField inside JPanel inside JPanel as viewport in JScrollPane


I have to admit, maybe the question seems strange how is written, but I'll explain here:

I have a JScrollPane, in which i correctly add a JPanel, let'sa say that for now JScrollPane variable is "JSP" and JPanel is "JP"

In my JP i have an ArrayList of JPanel (let's call it AJP) which i can control visibility from outside the JSP, i can control this visibility by clicking different buttons, every button is "linked" with a number so if i click button1, the first AJP element get visibility set to true, and all the others set to false.

Every of these AJP elements has a different elements inside, so for example, AJP at first position has two JTextFields and 1 JButton, AJP at position 2 has 1 JTextField only.

The fact is that seems that i can't click a JButton or edit a JTextField, like the mouse can't focus them, I'll post here some code

This is the class which contains the JP and it's an extension of JScrollPane

private int x, y, width, height;

private JPanel internalPanel = new JPanel();
private ArrayList<KPanel> kPanels = new ArrayList<KPanel>();

JViewport viewport = new JViewport();

public KScrollPanel(int x, int y, int width, int height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;


    this.internalPanel.setBorder(new LineBorder(Color.black, 1));
    this.internalPanel.setSize(new Dimension(this.width - 10, this.height - 10));
    this.internalPanel.setPreferredSize(new Dimension(this.width - 10, this.height - 10));

    this.setSize(new Dimension(this.internalPanel.getWidth() + 10, this.internalPanel.getHeight() + 10));
    this.setPreferredSize(this.internalPanel.getSize());

    this.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    this.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

    viewport.add(this.internalPanel);

}

This other is the class which pratically is composed the ArrayList in the class KScrollPanel i just posted, as you can see, the method initialize adds dinamically the elements (KButton and KTextFields are two classes extendind JButton and JTextField)

This class of course is an extension of JPanel

private int x, y, width, height;

KTextField textfield_nodeName, textfield_relationshipName;
KButton button_saveNode, button_saveRelationship;

public KPanel(int x, int y, int width, int height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    initGUI();
}

public KPanel() {

}

public void initGUI() {
    this.setBounds(this.x, this.y, this.width, this.height);
    this.setBorder(new LineBorder(Color.gray, 1));
}

public void initialize(String type) {
    switch(type) {
        case "Node": 
            textfield_nodeName = new KTextField(5, 5, 200, 30);
            this.add(textfield_nodeName);
            button_saveNode = new KButton(5, 35, 200, 30, "Save Node");
            this.add(button_saveNode);
            break;
        case "Relationship": 
            textfield_relationshipName = new KTextField(5, 5, 250, 30);
            this.add(textfield_relationshipName);

            break;
    }
    this.revalidate();
    this.repaint();
}

Solution

  • Why are you extending JScrollPane?

    Why are you creating a JViewport?

    Why are you createing an internal JPanel to add to the viewport?

    You should not be attempting to play with the sizes of any of your components. The layout manager will determine the size of each component.

    The component you want to add to the scrollpane should be created separately from the scrollpanel. You can then set the Border of this component when you create it.

    JViewport viewport = new JViewport();
    
    ...
    
    viewport.add(this.internalPanel);
    

    So it looks to me like you create an internal panel and add it to the viewport but you never add the viewport to the scroll pane, so there are no components to display.

    So my suggestion is to get rid of the custom JScrollPane class then is no need to extend it because you are not adding any functionality to the class. Just use a JScrollPane the way it was designed to be used:

    JPanel internalPanel = new JPanel();
    internalPanel.setBorder(...);
    internalPanel.add(...);
    JScrollPane scrollPane = new JScrollPane( internalPanel );
    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);