9
votes

Java: Faire une fenêtre clic-vitrée (y compris text / images)

Je veux créer une superposition dans Java qui est transparent forte>, toujours sur le dessus fort>, et que je peux clic-throws forte>. J'ai trouvé des Similaire Posts À propos de ce problème, mais même après avoir suivi leurs réponses, j'ai un problème.

Mon problème fait la fenêtre toute la fenêtre entière forte> clic-through-threille. Je n'ai aucun problème à faire fonctionner avec un jframe, mais une fois que j'ajoute des composants forts> à celui-ci (Jlabel ou un ImagePanel), l'attribut clic ne porte pas sur à eux. p>

Comme je veux avoir une image d'arrière-plan pour mon application, cela fait fondamentalement le code que j'ai inutile de voir comment la fenêtre se concentre chaque fois que je clique sur la zone des couvre-texte / image.

Avant d'afficher le code que j'utilise, je voudrais d'abord faire référence à ces threads qui décrit essentiellement exactement ce que je veux, sauf en C #. P>

Mon objectif est de créer une superposition avec une image transparente .png et du texte en haut cela changera sur les événements clés. S'il utilise Jframe ou toute autre bibliothèque n'a pas d'importance. J'en ai seulement besoin compatible avec Windows. P>

J'aimerais aussi mentionner que j'ai une certaine expérience avec Java, mais je suis un novice à utiliser jframe. P>

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

import com.sun.jna.platform.WindowUtils;


public class Overlay {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Overlay Window");
        frame.setUndecorated(true);
        frame.setAlwaysOnTop(true);
        frame.getRootPane().putClientProperty("apple.awt.draggableWindowBackground", false);
        frame.setLocation(400, 400);
        frame.getContentPane().setLayout(new java.awt.BorderLayout());

        JLabel textLabel = new JLabel("I'm a label in the window", SwingConstants.CENTER);
        frame.getContentPane().add(textLabel, BorderLayout.CENTER); 
        frame.pack();

        System.setProperty("sun.java2d.noddraw", "true");
        WindowUtils.setWindowTransparent(frame, true);
        WindowUtils.setWindowAlpha(frame, 1.0f);

        //Using AWTUtilities gives the same result as WindowUtils
        //AWTUtilities.setWindowOpaque(frame, false);
        //AWTUtilities.setWindowOpacity(frame, 1.0f);

        frame.setVisible(true);
    }
}


2 commentaires

Vous devez probablement définir le drapeau WS_EX_TRANSPARENT sur la fenêtre du JFRAME pour vous assurer que les événements de la souris sont passés à travers cette fenêtre. Voici un exemple: codeproject.com/articles/12877/transparent-cliquez -Through-pour MS


Voulez-vous simplement avoir tous les clics d'aller à un seul composant du JFRAME ou de les faire passer à ce qui pourrait être sous le jframe (y compris le bureau)?


3 Réponses :


0
votes

J'ai essayé de faire entièrement "événement-transparent" (clic à mesure que vous appelez cela) fenêtre, mais il semble y avoir des restrictions natives sur cette astuce.

Vérifiez cette fenêtre Exemple: P>

public static void main ( String[] args )
{
    Window w = new Window ( null );

    w.add ( new JComponent ()
    {
        protected void paintComponent ( Graphics g )
        {
            g.setColor ( Color.BLACK );
            g.fillRect ( 0, getHeight () / 2 - 10, getWidth (), 20 );
            g.fillRect ( getWidth () / 2 - 10, 0, 20, getHeight () );
        }

        public Dimension getPreferredSize ()
        {
            return new Dimension ( 100, 100 );
        }

        public boolean contains ( int x, int y )
        {
            return false;
        }
    } );

    AWTUtilities.setWindowOpaque ( w, false );
    AWTUtilities.setWindowOpacity ( w, 0.5f );

    w.pack ();
    w.setLocationRelativeTo ( null );
    w.setVisible ( true );
}


0 commentaires

4
votes

Le problème avec une fenêtre soit "Cliquez sur", c'est qu'il est manipulé sur un niveau système, en dehors de la portée des API standard. Cela signifie que tout code écrit pour faire une fenêtre "cliquer sur" sera dépend du système. Cela étant dit, le processus d'accomplissement de cette fenêtre sous Windows est plutôt simple.

sous Windows 2000 et plus tard, en définissant les indicateurs ws_ex_layered and ws_ex_transparent sur une fenêtre, la fenêtre sera ensuite cliquée sur. Exemple de code utilise JNA pour accomplir ceci: p>

public static void main(String[] args) {
    Window w = new Window(null);

    w.add(new JComponent() {
        /**
         * This will draw a black cross on screen.
         */
        protected void paintComponent(Graphics g) {
            g.setColor(Color.BLACK);
            g.fillRect(0, getHeight() / 2 - 10, getWidth(), 20);
            g.fillRect(getWidth() / 2 - 10, 0, 20, getHeight());
        }

        public Dimension getPreferredSize() {
            return new Dimension(100, 100);
        }
    });
    w.pack();
    w.setLocationRelativeTo(null);
    w.setVisible(true);
    w.setAlwaysOnTop(true);
    /**
     * This sets the background of the window to be transparent.
     */
    AWTUtilities.setWindowOpaque(w, false);
    setTransparent(w);
}

private static void setTransparent(Component w) {
    WinDef.HWND hwnd = getHWnd(w);
    int wl = User32.INSTANCE.GetWindowLong(hwnd, WinUser.GWL_EXSTYLE);
    wl = wl | WinUser.WS_EX_LAYERED | WinUser.WS_EX_TRANSPARENT;
    User32.INSTANCE.SetWindowLong(hwnd, WinUser.GWL_EXSTYLE, wl);
}

/**
 * Get the window handle from the OS
 */
private static HWND getHWnd(Component w) {
    HWND hwnd = new HWND();
    hwnd.setPointer(Native.getComponentPointer(w));
    return hwnd;
}


0 commentaires

1
votes

Pourquoi ne pas simplement utiliser le JLayeredpane existant ? Ce blog Publiez démontre une grande variété de superpositions sur un jframe , y compris le texte, les images et les pixels dessinés dynamiquement.


0 commentaires