I have a component (JPanel) inside a Window.
I always get false when calling panel.isShowing(),
when calling from a windowGainedFocus() event (when the parent window gets focus).
I assume that when the windowGainedFocus() event is called, the painting of the JPanel within this Window had not been finished yet.
I was trying to place that call isShowing() on the paint() method of this Window,
but I always get isShowing() = false.
Is there a way I could get an event when the JPanel is fully shown on screen and the isShowing() method will return true ?
Thanks
You should probably best approach this with a hierarchy listener on the panel itself:
panel.addHierarchyListener(new HierarchyListener() {
public void hierarchyChanged(HierarchyEvent e) {
if ((HierarchyEvent.SHOWING_CHANGED & e.getChangeFlags()) !=0
&& panel.isShowing()) {
//do stuff
}
}
});
If you don't want an event but have some specific code that needs to be run after your component has been drawn, you can override addNotify(), which gets called to make the component displayable. Example:
public void addNotify()
{
super.addNotify();
// at this point component has been displayed
// do stuff
}
You component will be fully displayed after you receive WindowListener.windowActivated. You will also run into timing problems and race conditions trying to assign focus before the windowActivated event.
Related
Here is my code
boolean boo = true;
ItemListener itemListener = new ItemListener() {
public void itemStateChanged(ItemEvent event) {
boo= false;
aSwingObj.repaint();
boo = true;
}
}
I want the repaint() method to run while boo is set to false, before it becomes true .
The problem is that repaint() function is only executed after the variable boo has been set to true again. I have tried other methods like revalidate(), validate() but it didn't work. How should I fix my code?
This is an XY problem. You don't want to force JPanel to immediately repaint. You want to enter a particular state immediately before painting begins and exit that state as soon as painting is over.
One way of accomplishing that would in fact be to enter that state, force a repaint right on the spot, and then exit that state. But as you have seen, this is a bit hard to accomplish.
So, another approach is to create a new class that does extend JPanel (or whatever the class of aSwingObj is) so that you can override the paintComponent() method and make it exit your special state once painting is done.
So, the paintComponent() method of your extended JPanel would look like this:
#Override
public void paintComponent( Graphics g )
{
super.paintComponent( g );
resetBoo();
}
where resetBoo() is a method which does boo = true;
class GameFrameClass extends javax.swing.JFrame {
public void MyFunc()
{
UserButton.setText(Str);
UserButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
UserButtonActionPerformed(evt);
}
});
getContentPane().add(UserButton);
}
private void UserButtonActionPerformed(java.awt.event.ActionEvent evt) {
//print some stuff after mouse click
}
}
In someother class i define this function
void functionAdd()
{
GameFrameClass gfc = new GameFrameClass()
gfc.MyFunc()
System.out.println("PRINT THIS AFTER MOUSE CLICK")
}
If someone can look into this code. I want to wait on the mouse click . Is there a way i can print the line System.out.println("PRINT THIS AFTER MOUSE CLICK") after the mouse is being clicked . For now this happens immediately and i am not able to wait for the mouse click . Is there a way of doing it ? Apart from doing it inside the function UserButtonActionPerformed() . Please let me know .
This is a really "bad" way to do it...
private void UserButtonActionPerformed(java.awt.event.ActionEvent evt) {
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
System.out.println("PRINT THIS AFTER MOUSE CLICK");
removeMouseListener(this);
}
});
}
A better way would be to have a flag in the actionPerformed method that would "enable" a mouse listener (which you added earlier). This listener would check the flag on each click and when set to true it would flip the flag (to false) and process the event...
It's hard to tell from the wording, but I assume he or she simply wants to execute code after the button is triggered (and not actually wait). For that, you need to add the code inside the method being invoked inside the actionlistener (in this case UserButtonActionPerformed).
So:
private void UserButtonActionPerformed(java.awt.event.ActionEvent evt) {
System.out.println(...);
}
Also, following the Java coding conventions will help people answering your questions in the future.
You can always wait in UserButtonActionPerformed by defining it in the same class. If that is the case then you should not have the problem you are facing
Events are managed on a different thread which is the event dispatching thread, they are not managed by the thread that is executing your code (which presumably is the main thread).
This means that you can attach listeners to GUI elements but the only thing you can do to "wait" for the click is to execute the code inside the actionPerformed callback.
There is no way to pause the execution since the addActionListener doesn't do anything to effectively catch the event, it just adds the listener. Theoretically you could lock the main thread waiting to be notified by the event dispatch one but that would just be bad design.
I tried this
private void botaoConfIOMouseClicked(java.awt.event.MouseEvent evt) {
ConfigurarIO popup = new ConfigurarIO();
popup.setVisible(true);
botaoConfIO.setEnabled(false); //this line to avoid multiple dialogues
setIO=popup.getConfig(); //i need to get this boolean from the dialogue "ConfigurarIO"
//part of the program only to make my logic from the setIO
if(setIO[0]==false){
jToggleButton1.setEnabled(false);
jToggleButton1.setText("SaĆda");
}
else{
jToggleButton1.setEnabled(true);
if(jToggleButton1.isSelected()) jToggleButton1.setText("Pino 1 ON");
else jToggleButton1.setText("Pino 1 OFF");
}
}
And this is the dialogue
public class ConfigurarIO extends javax.swing.JFrame {
boolean[] inOut=new boolean[8];
boolean ok=false;
/** Creates new form ConfigurarIO */
public ConfigurarIO() {
initComponents();
}
public boolean[] getConfig(){
return inOut;
}
public boolean getOK(){
return ok;
}
public void setOK(){
ok=false;
}
//the logic was emited
private void botaoOKMouseClicked(java.awt.event.MouseEvent evt) {
dispose();
ok=true;
System.out.println(ok);
}
The problem is that the setIO is not modified by the second interface and, If I set this to make a loop broken only by the "ok" boolean, the window with the setting interface doesn't open. This is a very explored problem but I am new to Netbeans and I couldn't find it on Google. Thanks for the attention
Print screen: http://4.bp.blogspot.com/-B7VWmPelJek/T2ysJV8PJcI/AAAAAAAABqQ/0waWxxEEHkw/s320/temp.png
You haven't said whether a frame is required for some reason, or whether a dialog would do, or whether whatever it is needs to be modal.
The reason the frame doesn't show up if you loop is that you're on the Swing dispatch thread (since you are in a routine that responded to a mouse click), and until it returns, it isn't going to update the screen.
You cannot just call a method on the "frame dialog" to get a value until you know that the dialog has set the value. I would pass my calling class to the dialog as a parameter on the constructor, and then have the dialog code call a method on the calling class when it's all done. If you need to know when this happens, then you'll have to treat it as an event in your calling class; I can't guess what you need for that without knowing more about what you're trying to do overall.
If you need to wait until the dialog is done, and don't need the user to be able to do anything until it is done, then what you want is a "modal" dialog, and I recommend looking at JOptionPane and its various dialog options for what you want to do. THEN the call from your class can be synchronous, i.e., you can call the dialog and, when the call completes, the dialog is all done. Then you don't need to pass the calling class to the frame, since it doesn't need to notify you that it's done; you know it's done when your call completes, and you can call a method such as you have already done to get the value that you want.
Incidentally, your subclass-of-JFrame constructor doesn't call super(); I recommend you do that...
rc
// we will make this modal=true, to block access to the parent frame
public class ConfigurarIO extends javax.swing.JDialog {
For more details, see:
How to Make Dialogs
How to Use Modality in Dialogs
I'm trying to listen for a window close event on the parent JFrame of a JPanel. In the WindowClosing event I'd like to de-register a listener to a different component.
Unfortunately the only code I can gaurantee to have run is the constructor for the panel. What this means is that the panel itself doesn't have an ancestor window yet, so simply calling SwingUtilities.getWindowAncestor doesn't work. So what I do is register a hierarchy listener, and in the hierarchyChanged event look for SHOWING_CHANGED event. When that even fires, now I can look for the window ancestor of the panel.
So basically I have the following:
class ShapeControlPanel extends JPanel{
public ShapeControlPanel(){
final ShapeControlPanel me = this;
me.addHierarchyListener(new HierarchyListener() {
#Override
public void hierarchyChanged(HierarchyEvent e) {
if((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) == HierarchyEvent.SHOWING_CHANGED){
SwingUtilities.getWindowAncestor(me).addWindowListener(new WindowListener() {
/* Snipped some empty handlers */
#Override
public void windowClosing(WindowEvent e) {
/* Finally get to remove the handler. */
me.getApparent().removeLocationSelectionListener(me.GUID(), me);
}
});
}
}
});
}
}
Is this sane? Is there a more reasonable way of getting a handle on the frame closing event?
It's not the ugliest thing I've seen (I wouldn't even say it's all that bad), but you have to ask yourself: why does your panel really need to know when the window is closed? It seems to be an odd coupling that would best be removed.
I don't know enough about your context and what you are truly trying to accomplish to suggest an alternative right now. But if a panel needs to know about the container in which it resides, there is probably some bad design with harmful coupling.
When I use setSelectedComponent or setSelectedIndex on a JTabbedPane object, the panel always comes up in my UI. However, sometimes the tab associated with the panel remains hidden. In other words, the tab does not scroll to a visible portion of the tabbed pane.
How can I fix this? I have tried the cheesy select one index, then select desired index, as well as several other more elegant things, but arrrrgh!!
Help me if you can.
Thanks,
Todd
I think your call is not done on EDT. Wrap it with SwingUtilities.invokeLater
Here is a patter you can use if you have a method that alters swing components, or their models and so must be called on the EDT, but may be called from a background thread. This ensures func always runs on the EDT:
void func(final Type1 arg1, final Type2 arg2) {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
func(arg1, arg2);
}
});
return;
}
// method code goes here
}