简体   繁体   中英

JInternalFrame selection

I have a JDesktopPane containing some JInternalFrames. I want some menus on the menubar to be activated only when one of the JInternalFrames is selected. I've tried using VetoableChangeListener, with the following code in it:

JInternalFrame selectedFrame = desk.getSelectedFrame(); 
if ((selectedFrame != null)) {  
    imageMenu.setEnabled(Boolean.TRUE);         
} else {
    imageMenu.setEnabled(Boolean.FALSE);            
}

But the results are not what I expected - for example, the menu is enabled only the second time I add a frame. when I close all frames, it remains enabled.

How can I make this work?

you have to read basic tutorial about JInternalFrames with link to the InternalFrameListener ,

but another and look like as better way is programatically to know those event in all cases and evety times is by adding PropertyChangeListener as shows examples Getting All Frames in a JDesktopPane Container , by adding PropertyChangeListener you can listeng for these events

I would just create a custom event and fire it when a JInternalFrame gets focus ( isActivated ) . The menu items would listen for this event, intercept it and set their status enabled or disabled accordingly. The advantage here is that you don't have to handle what menu items should be available for which types of internal frames, just fire the appropriate event. It'll make your life easier if you add more internal frames in the future.

Add an InternalFrameListener to each internal frame added to the desktop pane, and each time an event is triggered, execute the code you have shown in your question.

This code could be better written though:

  • setEnabled takes a primitive boolean as argument, not a java.lang.Boolean . Use true and false rather than Boolean.TRUE and Boolean.FALSE .
  • The expression (selectedFrame != null) evaluates as a boolean. Just write

imageMenu.setEnabled(selectedFrame != null);

instead of

if ((selectedFrame != null)) {  
    imageMenu.setEnabled(Boolean.TRUE);         
} else {
    imageMenu.setEnabled(Boolean.FALSE);            
}

This answer is based on the answer by @mKorbel. This example shows one of the ways to detect focus between internal frames as is demonstrated here:

JInternalFrame窗口焦点侦听器示例

package com.apexroot.sandbox;

import java.awt.Dimension;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;

/**
 * author grants unlimited license to modify, reuse and redistribute. based on 
 * the suggestion by @mKorbel on stackoverflow at
 * http://stackoverflow.com/questions/7219860/jinternalframe-selection
 * please keep a URL to the original version in the source code.
 * http://javajon.blogspot.com/2015/08/windowfocuslistener-for-jinternalframe.html
 *
 * @author Apexroot
 */
public class InternalFrameFocusListenerExample {

    public static final String INTERNAL_FRAME_FOCUS_EVENT_PROPERTY = "selected";

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                final JFrame jFrame = new JFrame();
                final JDesktopPane jDesktopPane = new JDesktopPane();
                final JInternalFrame[] jInternalFrames = new FocusInternalFrame[3];
                for (int i = 0; i < jInternalFrames.length; i++) {
                    jInternalFrames[i] = new FocusInternalFrame();
                }
                jFrame.dispose();
                jFrame.setContentPane(jDesktopPane);
                jDesktopPane.setPreferredSize(new Dimension(400, 200));
                jFrame.pack();
                jFrame.setVisible(true);
                for (int i = 0; i < jInternalFrames.length; i++) {
                    jDesktopPane.add(jInternalFrames[i]);
                    jInternalFrames[i].setLocation(10 + 60 * i, 10 + 40 * i);
                    jInternalFrames[i].setVisible(true);
                }

            }

        });

    }

    public static class FocusInternalFrame extends JInternalFrame {

        public FocusInternalFrame() {

            final JLabel jLabel = new JLabel("placeholder for pack();");
            setContentPane(jLabel);
            pack();

            this.addPropertyChangeListener(
                    INTERNAL_FRAME_FOCUS_EVENT_PROPERTY,
                    new LabelFocusListener(jLabel));

        }

    }

    private static class LabelFocusListener implements PropertyChangeListener {

        private final JLabel jLabel;

        public LabelFocusListener(JLabel jLabel) {
            this.jLabel = jLabel;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            // please keep a URL to the original version in the source code.
            // http://javajon.blogspot.com/2015/08/windowfocuslistener-for-jinternalframe.html
            if (INTERNAL_FRAME_FOCUS_EVENT_PROPERTY.equals(
                    evt.getPropertyName())) {
                final Object oldValue = evt.getOldValue();
                final Object newValue = evt.getNewValue();
                if (oldValue instanceof Boolean
                        && newValue instanceof Boolean) {
                    boolean wasInFocus = (Boolean) oldValue;
                    boolean isInFocus = (Boolean) newValue;
                    if (isInFocus && !wasInFocus) {
                        EventQueue.invokeLater(new Runnable() {
                            @Override
                            public void run() {

                                // focus gained
                                jLabel.setText("focus gained");
                            }
                        });
                    } else if (wasInFocus && !isInFocus) {
                        EventQueue.invokeLater(new Runnable() {
                            @Override
                            public void run() {

                                // focus lost
                                jLabel.setText("focus lost");
                            }
                        });
                    }
                }
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM