When I set the visibility of components (mainly JPanels that have other child components) to false or back to true later, do I have to call .revalidate() and .repaint() on the parent container explicitly or do the LayoutManagers handle this automatically?
When I tried this with a component in BorderLayout-North position for example, everything looked fine without calling revalidate. Just not sure if it will work on all platforms and with all LayoutManagers.
when u set the visibility of components like JPanels. JVM automatically call revalidate() and repaint() method when u set the visibility to true. u does not need to call the all these method. and it will work for all layout
The following code may solve your problem
p2_wrkrreg=new JPanel();
p2_wrkrreg.setBounds(201,0,830,720);
// p2_wrkrreg.setLayout(null);
//p2_wrkrreg.setBackground(Color.white);
p2_wrkrreg.setVisible(false);
In this code,
The JPanel declared and make it invisible, it will be visible on a button click
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==btn_wrkrreg)
{
p2_wrkrreg.setVisible(true);
}
here btn_wrkrreg is a JButton
Related
So, I've wrote a code where you get a rectangle after you click the button on the south region of the frame.
But the code didn't seem to work after the button is clicked because of this
public void actionPerformed(ActionEvent ev){
Drawing d = new Drawing();
frame.add(d);
frame.repaint();
}
and the I add revalidate() inside the block.
public void actionPerformed(ActionEvent ev){
Drawing d = new Drawing();
frame.add(d);
frame.revalidate();
frame.repaint();
}
now the code works just fine, but from where I've been studying they didn't use revalidate() and their code worked.
why is this happening?
So, the example you've cited is using a custom painting approach to paint the component. This does not (directly) affect the size or location of the component, so it doesn't need the container to perform a new layout pass.
See Performing Custom Painting and Painting in Swing for more details
Your code is adding a new component to the container, so you need to tell the container when you want the container to be laid out again.
So, from the JavaDocs
public void revalidate() Supports deferred automatic layout. Calls
invalidate and then adds this component's validateRoot to a list of
components that need to be validated. Validation will occur after all
currently pending events have been dispatched. In other words after
this method is called, the first validateRoot (if any) found when
walking up the containment hierarchy of this component will be
validated. By default, JRootPane, JScrollPane, and JTextField return
true from isValidateRoot.
This method will automatically be called on this component when a
property value changes such that size, location, or internal layout of
this component has been affected. This automatic updating differs from
the AWT because programs generally no longer need to invoke validate
to get the contents of the GUI to update.
I have three JPanel, fatherPanel, childPanel1, childrenPanel2.
When I click a button, I remove the current children panel from the father panel, and add another children in the father panel.
Everytime I should call revalidate() and repaint() to update the UI.
Then, I know the SwingUtilities.updateComponentTreeUI() has the same effect.
I want to know are there any difference between the twos?
Swing supports pluggable Look-n-Feel's. When you change the L&F at runtime you need to inform all your components, about this change using the method updateComponentTreeUI. Because due to new L&F the component sizes can be changed, Swing must call revalidate to recalculate the layout. Here is the code of the method updateComponentTreeUI
/**
* A simple minded look and feel change: ask each node in the tree
* to <code>updateUI()</code> -- that is, to initialize its UI property
* with the current look and feel.
*/
public static void updateComponentTreeUI(Component c) {
updateComponentTreeUI0(c);
c.invalidate();
c.validate();
c.repaint();
}
So yes, you can invoke SwingUtilities.updateComponentTreeUI to inform your GUI about layout change but it's huge overhead (and can theoretically have some side-effects). Combination of revalidate and repaint is better in your case.
I have a CardDetailsPanel class which contains several JLabels and JTextFields. This class in contained in a AddCardsPanel and is initialized as follows:
cardDetailsPanel = new CardDetailsPanel(true);
add(cardDetailsPanel, java.awt.BorderLayout.CENTER);
I also have a JLabel that contains instructions. I want to update this label when the CardDetailsPanel first appears and when focus changes to each JTextField. I have found the addFocusListener() method that will work for the later. However, my compenentShown() method isn't working for the former:
addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentShown(java.awt.event.ComponentEvent evt) {
formComponentShown(evt);
}
});
(Okay, I know this is ugly. It was generated by NetBeans.)
private void formComponentShown(java.awt.event.ComponentEvent evt) {
this.frame = (BaseballFrame) this.getParent().getParent().getParent().getParent().getParent().getParent();
}
(Yah, this is even uglier. I'll deal with the chained getParent() calls later. I want to do other things here as well.)
So why doesn't my listener get called? And how do I write a listener that will perform some actions whenever my CardDetailsPanel appears on the screen?
Use an AncestorListener as described in dialog focus.
When a JDialog (or JFrame for that matter) is made visible, focus is placed on the first focusable component by default. There may be times when you want to change this behaviour. The obvious solution would be to invoke the requestFocusInWindow() method on the component you wish to receive focus. The problem is that this doesn’t work all the time.
...
The problem is .. a component can’t request focus unless it has been added to a “realized” dialog. A realized dialog basically means that the Swing JDialog has been added to a peer component that represents a dialog on the underlying OS. This occurs when you invoke the pack() or setVisible(true) methods on the JDialog.
And that is where the ancestor listener comes in handy. For a component in a modal dialog, it will be fired once the component becomes visible, and is realized & focusable.
Edit:
The above comment applies to components in any Swing container, including JFrame and JPanel.
I add my customized panel onto JScrollPane. I also have another set of "tool" that will attach itself to my custom panel. The problem is, in these tool, it invokes attached.addMouseListener(this). Normally, everything would function well, but when I have it inside JScrollPane, it won't function at all. My deduction is JScrollPane never gives window focus to its child component. Is there a way to get this around without having to change my attachment procedure? I want my 'tool' to specifically attach to my custom panel, not the scrollpane.
I hope I have understood the problem.
What about adding a MouseListener to the JScrollPane and then dispatch the event to the JPanel?
Somenthing like this:
//JScrollPane Listener
public void mousePressed(MouseEvent me) {
jpanel.dispatchEvent(me);
}
It's a little bit tricky, but so you don't have to change the JPanel Listener.
I dont know how to make this with simple and easy code.
I can just go to each piece of my code and use setEnabled to false on each component, but I want a easy way.
I want to disable the entire frame, but still want to close/maximize/minize it. do you understand?
And if I use setEnabled(false) on my frame, it disables that options too, the options of windows menu bar you know?
Thanks alot in advance..
Simple,Put all your components in a JPanel and disable the JPanel :-)
You can use a code snippet like below. Insert this method/routine in a utility class. Since the method is static you can call it without that class's instance. And make invocations to this method to enable/disable components (menu items, buttons, text fields etc.)
// Let's say you have a JFrame object called myFrame
// and a reference to its content pane.
// Container container = myFrame.getContentPane();
public static void toggleAbilities(Container container, boolean enabled)
{
Component[] components = container.getComponents();
for(Component component: components)
component.setEnabled( enabled );
}
If you get stuck, I can post overall working code as well.
(Toggling the ability of a set of buttons in a JFrame)