1

I'm learning Java and testing a simple note taking program. I have a panel that is hidden at startup, and made visible by the click of a button. But I can't see this panel until I resize the window of the program ! I sincerely tried everything I could find online here and there, and still didn't manage to get it running properly. Here is the code :

//Main JFrame "Fenetre"
//imports
...

public class Fenetre extends JFrame implements ActionListener {

    private static final long serialVersionUID = 1L;
    private JPanel west = new JPanel();
    private CEPan CEPan = new CEPan();
    private JPanel container = new JPanel();
    private JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, west, CEPan);
    private JButton nouvelleNote = new JButton("Nouvelle note");

    public Fenetre() {
        this.setMinimumSize(new Dimension(800, 700));
        this.setTitle("Notes");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setContentPane(container);
        container.setBackground(Color.GREEN);
        west.setMinimumSize(new Dimension(100, 700));
        west.add(nouvelleNote);
        nouvelleNote.addActionListener(this);
        CEPan.setMinimumSize(new Dimension(200, 700));
        CEPan.setBackground(Color.RED);

        split.setDividerSize(4);
        container.setLayout(new BorderLayout());
        container.add(split, BorderLayout.CENTER);

        //At first this panel is hidden until the click of the button
        CEPan.setVisible(false);

        this.setContentPane(container);
    }


    public void nouvelleNote() {
        CEPan.setVisible(true);
        container.repaint();
        west.repaint();
        this.repaint();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        nouvelleNote();
    }

}

CEPan

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class CEPan extends JPanel {

    private static final long serialVersionUID = 1L;
    private TextArea titleTF = new TextArea(35);
    private TextArea contentTA = new TextArea(16);
    private JScrollPane scroll = new JScrollPane(contentTA, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

    private JScrollPane scrollTitle = new JScrollPane(titleTF);
    public boolean hide;

    public CEPan() {        
        titleTF.setBackground(Color.BLUE);
        this.setLayout(new BorderLayout());
        this.add(scrollTitle, BorderLayout.NORTH);
        this.add(scroll, BorderLayout.CENTER);
        titleTF.setEditable(true);

        contentTA.setLineWrap(true);
        scrollTitle.setBackground(Color.GRAY);
    }
}

TextArea

public class TextArea extends JTextArea {

    private static final long serialVersionUID = 1L;
    private Color couleur = new Color(1, 168, 135);

    public TextArea(int fs) {
        Font font = new Font("Arial", Font.BOLD, fs);
        this.setFont(font);
        this.setForeground(couleur);
        //this.setPreferredSize(new Dimension(40, 40));
    }
}

Notes

public class Notes {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Fenetre fenetre = new Fenetre();
        fenetre.pack();
        fenetre.setVisible(true);
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Yasston
  • 35
  • 4
  • 1
    `public class TextArea extends JTextArea {` This is a confusing name for the class, given there is a `java.awt.TextArea`. Further, a factory method would be better to produce the text areas. – Andrew Thompson Jul 17 '17 at 15:20
  • Just calling `repaint()` on the root object will repaint all of its children, so `nouvelleNote()` should only call `this.repaint()` or even better `repaint()` as the `this` is implied – CraigR8806 Jul 17 '17 at 15:20
  • 3
    *"I have a panel that is hidden at startup, and made visible by the click of a button."* Use a [`CardLayout`](http://download.oracle.com/javase/8/docs/api/java/awt/CardLayout.html) as shown in [this answer](http://stackoverflow.com/a/5786005/418556). – Andrew Thompson Jul 17 '17 at 15:22
  • @AndrewThompson has the best solution, but another option would be to call `revalidate()` alongside `repaint()` when adding or removing `Component`s or `JComponent`s – CraigR8806 Jul 17 '17 at 15:23
  • Thanks to all for the usefuls comments. It turned out that the problem wasn't exactly about resizing the window. It was only OK when I resized the right side of the window, more precisely the CEPan. It was only when the Divider was dragged even a millimeter that the CEPan appeared. I still don't understand the problem but I was able to patch it only by instanciating the JSplitPanel when the button is clicked, otherwise I only have the "west" panel alone with the button – Yasston Jul 17 '17 at 17:25
  • Based on your example, `CEPan` is never added to anything. If you need to dynamically update the UI at runtime, then you will need to call `revalidate` followed by `repaint` to trigger a layout and paint pass - Also, beware, that most layout managers don't calculate the size of hidden components during a layout pass, this may mean that your window is initially to small to support it – MadProgrammer Jul 17 '17 at 20:39

3 Answers3

0

When a JComponent has already been displayed and some event causes a modification of such JCompoment, the best way to avoid problems is to always call repaint() and revalidate() on the involved component. The first method causes the component to be repainted in order to show any change involving the components look (e.g change a color), the second one notifies the layout manager to recalculate the layout, as it is necessary if some component has been added or removed.

kernel_panic
  • 119
  • 11
0

Just add one line of code: resize(900,700) after you make your CEPan visible.

`public void nouvelleNote() {
   CEPan.setVisible(true);
   resize(900, 700);
 }`

This would resize your JFrame and then it will automatically repaint and revalidate all of the components.

bhavna garg
  • 270
  • 2
  • 19
-2

I've had this problem before. All you need to replace all repaint method calls with:

yourJFrame.setVisible(true);

Eg.:

public void nouvelleNote() {
    CEPan.setVisible(true);
    this.setVisible(true);
}

Even if the frame is already visible this method will reassure that everything is rendered correctly.

Chaoz
  • 2,119
  • 1
  • 20
  • 39