Why is componentShown() not called? - java

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.

Related

Is frame.revalidate() important to get output after an event?

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.

Swing: Dynamically change visibility of components

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

Java requestFocus() not working at the constructor

In my Java Swing Application Reuestfocus method not working at the Constructor. But it works if I used requestfocus along with button action listener. I want set Requestfocus at the form load. I dont understand whats the wrong here. P.S I use JInternal Frame
txtItemName.requestFocusInWindow (); // did not work
txtItemName.requestFocus (); // did not work
public ItemMgt() {
initComponents();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
txtItemName.requestFocus(); // did not work
}
});
}
private void formInternalFrameActivated(javax.swing.event.InternalFrameEvent evt) {
txtItemName.requestFocus(); // did not work.
}
The case might by that your component is not visible, so the GUI manager can not set focus on it.
As is specified in documentation:
(..) component must be displayable, focusable, visible and all of its ancestors (with the exception of the top-level Window) must be visible for the request to be granted.
Generally you should avoid to have so robust logic in constructor. Your graphic components should be constructed first. When this is finished they should be adjusted to your preferences.
Instead of requestFocus(), it is recomended to use requestFocusInWindow() for more please visit the tutorial: How to Use the Focus Subsystem
If you are using Netbeans IDE, then its much easier. Just make sure that all controls before your textbox are not focusable by unchecking the 'focusable' property in the Properties window. This will leave your textbox as the first focusable control thus allowing it to receive focus when the internal frame is opened

Java Swing: dispose() a JFrame does not clear its controls

I have a closeWindow() method which uses dispose() for the current JFrame to close down. When I show the window again, the controls (textboxes, lists, tables etc.) still have their previous values in place that were there when I dispose():d the frame... Why is that? Is there another way to completley close and clear a frame?
This is the code that another JFrame uses to show the other window, am I doing something wrong here?
#Action
public void showAddProductToOrderView() {
if (addProductToOrderView == null) addProductToOrderView = new AddProductToOrderView(this);
addProductToOrderView.setVisible(true);
}
Disposing a window will not clear its child text components. Dispose will release native resources. The javadoc for java.awt.Window also states:
The Window and its subcomponents can be made displayable again by rebuilding the native resources with a subsequent call to pack or show. The states of the recreated Window and its subcomponents will be identical to the states of these objects at the point where the Window was disposed (not accounting for additional modifications between those actions).
As suggested by others, create a new instance each time instead. If that's to expensive I believe your best option is to clear sub components when the view becomes visible, e.g. by overriding setVisible.
EDIT:
Remove the null check to create a new frame each time.
#Action
public void showAddProductToOrderView() {
addProductToOrderView = new AddProductToOrderView(this);
addProductToOrderView.setVisible(true);
}
I don't know about the rest of your code, if there's something else depending on the frame being reused. For example, if you have attached listeners, ensure they are unregistered to not leak them.
The simplest thing to do would be to re-create the whole frame (using its constructor) before using show() to show it again. That will give you a whole new set of components, assuming that the constructor creates and places them.

Obtaining focus on a JPanel

I have a JPanel inside a JFrame. I have registered a KeyListener, based on which I want to update the JPanel. The problem I am having is that I cannot get the focus on the JPanel and therefore my KeyListener won't work. I already know that the KeyListener is functional because I registered it with the JFrame and it worked fine. My code goes something like this at the moment:
myFrame.setFocusable(false);
myPanel.setFocusable(true);
myPanel.addKeyListener(myKL);
myFrame.add(myPanel);
Has anyone encountered a problem like this before? Is there something I am missing in regards to this?
P.S.: I do not have any components inside the JPanel I just draw an Image on the background, so I need the focus to be on the JPanel itself and not on something inside it.
Although you're indicating that the panel can be focusable, the panel isn't asking for focus. Try using myPanel.requestFocus();.
Use setFocusable(true) and then requestFocusInWindow(). But the latter must be done after the window containing the panel is made visible, for which you will likely need to register a window listener and do the requestFocusInWindow() in the window activated handler code.
Note: Specifically after the window is visible, not just after calling setVisible(true).
I sometimes face a similar problem. I've noticed that in some cases it is better to make or request focus on a specific control within the panel that is within the frame (e.g., the input box to which you want keyboard input to go), rather than request focus for the pane itself.
Try
panel.setFocusable(true);
panel.setRequestFocusEnabled(true);
// some code here
panel.grabFocus();
Try something like this:
myFrame.addFocusListener(new FocusAdapter() {
/**
* {#inheritDoc}
*/
#Override
public void focusGained(FocusEvent aE) {
myPanel.requestFocusInWindow();
}
});

Categories

Resources