Torna indietro   Hardware Upgrade Forum > Software > Programmazione

AMD Advancing AI 2026: l'hardware AMD per le elaborazioni IA del futuro, tra GPU, CPU e robot
AMD Advancing AI 2026: l'hardware AMD per le elaborazioni IA del futuro, tra GPU, CPU e robot
AMD Advancing AI è l'appuntamento annuale con il quale l'azienda americana mostra quelle che sono le proprie novità dal versante datacenter. Tra piattaforma Helios, GPU Instinct MI455X e processori EPYC di sesta generazione tutto quello che serve per processare l'IA sempre più complessa ed esigente
Tascabile e con Android: BOOX Go 6 Gen II è diverso da tutti gli altri e-reader
Tascabile e con Android: BOOX Go 6 Gen II è diverso da tutti gli altri e-reader
BOOX Go 6 Gen II porta per la prima volta il supporto allo stilo su un e-reader da 6 pollici, affiancando 3 GB di RAM al collaudato Snapdragon 665 e un design rivisto con scocca posteriore a costolature. Su carta la proposta è interessante, ma Android 11 fuori supporto, l'assenza di un alloggiamento per il pennino e un'autonomia ridotta rispetto agli e-reader tradizionali sono i compromessi da accettare
Recensione Lenovo Idea Tab Plus: il tablet da 12 pollici che costa meno di 300 euro
Recensione Lenovo Idea Tab Plus: il tablet da 12 pollici che costa meno di 300 euro
Lenovo Idea Tab Plus prova a portare un display da 12,1 pollici 2.5K, quattro speaker Dolby Atmos e una batteria da 10.200 mAh sotto la soglia psicologica dei 300 euro, penna inclusa. Lo abbiamo usato per oltre una settimana per capire dove l'azienda ha tagliato e dove invece ha tenuto il punto
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 11-07-2010, 19:36   #1
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
[JAVA-Swing] Hack: finestra trasparente

Uno degli aggiornamenti introdotti al tempo del rilascio di Java SE 6u10 è la possibilità di avere finestre trasparenti (completamente o parzialmente) e di avere finestre di dimensione arbitraria (Shaped Windows).
[info qui]

Cosa si può fare, se l'applicazione gira su una piattaforma che non le supporta?

Una tecnica consiste nel "simulare" la trasparenza di una finestra disegnando in background gli stessi pixel che comparirebbero sotto la finestra, nello schermo dell'utente.
Per farlo bisogna creare un'immagine dello schermo-utente e disegnarla nella finestra traslando opportunamente le coordinate di riferimento, in modo che la porzione visibile dell'immagine si sovvrapponga correttamente con quanto mostrato a video (idea brutalmente rubata in giro sul web, ovviamente, così come il primo codice grezzo che poi ho esteso).

Posto due classi che ho scritto in questi due giorni, che realizzano una finestra trasparente con questa tecnica, che mostra lo sfondo del desktop con un leggero effetto di blur e un colore semi-trasparente aggiunto sopra, per dare l'impressione di osservare in trasparenza attraverso un vetro (o almeno, questa era l'intenzione )

Ecco un'immagine che ne mostra l'effetto, sul mio pc:


A seguire il codice delle due classi implementate:
- JTransparentComponent, estensione di java.swing.JComponent
- JGhostFrame, estensione di java.swing.JFrame

JTransparentComponent gestisce l'effetto di trasparenza su se stesso, ed è pensato per essere usato come 'content pane' di un frame.

JGhostFrame invece realizza un frame che usa un JTransparentComponent come suo 'content pane' al posto di quello standard (un normale java.awt.Container)

Limiti attuali di JGhostPane:
- Non potendo rendere trasparente la 'title bar' di una finestra un JGhostFrame è sempre un JFrame 'undecorated' che gestisce e implementa la title bar internamente.
- Ha un supporto limitato per la trasparenza della 'menu bar' e di tutti i 'bottoni' (Dipende dal LnF)
- Non supporta componenti 'heavyweight', tipici di AWT, ma solo quelli 'lightweight' di Swing.


P.S.:
Commenti, critiche e quant'altro sono ben accetti.
Modifiche all'implementazione e alle idee anche.
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)

Ultima modifica di banryu79 : 11-07-2010 alle 21:14.
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 11-07-2010, 19:39   #2
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
JTransparentComponent.java

Riporto per comodità di lettura il commento alla classe:
Quote:
/**
* This class is a Swing container that paint itself with an image of the screen taken
* with java.awt.Robot, updated at appropriate times, to mimic a transparent background.
* <p>
* This class should be used as a substitute for the default content pane of a frame.
* In Swing the default content pane is a simple intermediate container that inherits from
* JComponent, and that uses a BorderLayout as its layout manager, so this class honors
* this fact.
* <p>
* To keep the background image updated this class add itself to the the given frame as a
* component listener and window focus event listener.
* <p>
* This class could also be used as a fake transparent background for an undecorated frame
* that shows images instead of components (think of an audio player user interface).<br>
* If the image used support transparency then the screen snapshot used as background will
* show through.
*
* @author francesco
*/
Codice:
package transparentbackground;

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 * This class is a Swing container that paint itself with an image of the screen taken 
 * with java.awt.Robot, updated at appropriate times, to mimic a transparent background.
 * <p>
 * This class should be used as a substitute for the default content pane of a frame.
 * In Swing the default content pane is a simple intermediate container that inherits from 
 * JComponent, and that uses a BorderLayout as its layout manager, so this class honors
 * this fact.
 * <p>
 * To keep the background image updated this class add itself to the the given frame as a
 * component listener and window focus event listener.
 * <p>
 * This class could also be used as a fake transparent background for an undecorated frame
 * that shows images instead of components (think of an audio player user interface).<br>
 * If the image used support transparency then the screen snapshot used as background will
 * show through.
 *
 * @author francesco
 */
public class JTransparentComponent extends JComponent
    implements ComponentListener, WindowFocusListener, WindowListener//, Runnable
{
    /** 
     * Transparency value for the background-color painted above the screenshot.<br>
     * It is used to mimic the effect of looking it through colored glass.
     */
    public static int backgroundTransparency = 192;

    private final Robot ROBOT;
    private final Rectangle SCREEN_RECT;
    private final ConvolveOp BLUR_OP;       // used to blur ligthly the screenshot
    private final Color BACKGROUND_COLOR;

    private JFrame frame;                   // the decorated frame, needed for position calculation
    private Image screenSnapshot;           // used to mimic transparent background
    private long lastUpdate;
    private boolean refreshRequested;
    private boolean frameIsNotClosing;
    

    /**
     * Create a new transparent component and bind it to the given frame.
     * @param frame  the JFrame instance for which to bind this component.
     */
    public JTransparentComponent(JFrame frame) {
        // this component is intended to be used as a replacement for the
        // content pane of a frame, so it is appropriate to init its layout
        // manager to BorderLayout.
        this.setLayout(new BorderLayout());

        this.frame = frame;

        try {
            ROBOT = new Robot();
        } catch (AWTException ex) {
            throw new HeadlessException("Cannot create java.awt Robot object on \"headless\" platform.");
        }
        
        SCREEN_RECT = getTotalScreenBounds();
        BLUR_OP = createBlurConvolution();
        BACKGROUND_COLOR = new Color(255, 255, 255, backgroundTransparency);

        takeScreenSnapshot();

        // We track some component events and window events that force the
        // updating of the screenshot.
        // To show constatly the correct portion of the screenshot at current
        // component location we respond to: componentMoved, componentResized,
        // componentShown with a repaint.
        frame.addComponentListener(this);

        // We track focus gained/lost events because we cannot know what the user is
        // doing with other windows on the system (moving them and so obscuring/reveal
        // again this component and the frame associated) or if the user is changing
        // desktop settings, so it is better to make a request for taking a fresh new
        // snapshot of the screen.
        frame.addWindowFocusListener(this);

        // We track the window opened/closing events to start/stop the thread responsible
        // for the correct updating of the screenshot.
        frame.addWindowListener(this);
    }

    // Used to init the convolution used for the blur effect on the screenshot.
    private ConvolveOp createBlurConvolution() {
        float[] lightBlur = { .07f, .13f, .07f,
                              .13f, .20f, .13f,
                              .07f, .13f, .07f };
        return new ConvolveOp(new Kernel(3, 3, lightBlur));
    }

    // Calculate the screen dimension used for taking the screenshot
    private Rectangle getTotalScreenBounds() {
        GraphicsEnvironment ge =
                GraphicsEnvironment.getLocalGraphicsEnvironment();

        // take account of multiple, side-by-side, screens
        int w = 0;
        for (GraphicsDevice d : ge.getScreenDevices())
            w += ge.getMaximumWindowBounds().width;

        int h = ge.getMaximumWindowBounds().height;
        return new Rectangle(0, 0, w, h);
    }

    private void takeScreenSnapshot() {
        BufferedImage buf = ROBOT.createScreenCapture(SCREEN_RECT);
        screenSnapshot = BLUR_OP.filter(buf, null);
    }

    // request a refresh
    private void refresh() {
        if (frame.isVisible()) {
            repaint();
            refreshRequested = true;
            lastUpdate = System.currentTimeMillis();
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        Point pos = this.getLocationOnScreen();

        // draw convolved background image
        g2.drawImage(screenSnapshot, -pos.x, -pos.y, null);
        
        // add semi-transparent color
        g2.setColor(BACKGROUND_COLOR);
        g2.fillRect(0, 0, getWidth(), getHeight());
    }

    public void componentHidden(ComponentEvent e) {
        // do nothing
    }

    public void componentMoved(ComponentEvent e) {
        repaint();
    }

    public void componentResized(ComponentEvent e) {
        repaint();
    }

    public void componentShown(ComponentEvent e) {
        repaint();
    }

    public void windowGainedFocus(WindowEvent e) {
        refresh();
    }

    public void windowLostFocus(WindowEvent e) {
        //refresh();
    }

    /**
     * Encapsulate calls on the EDT to setLocation.
     * Used to move the frame associated with this
     * component out of visible desktop area before
     * taking a screenshot.
     */
    class CallSetLocation implements Runnable
    {
        final int X;
        final int Y;

        CallSetLocation(Point p) {
            this(p.x, p.y);
        }

        CallSetLocation(int x, int y) {
            X = x;
            Y = y;
        }

        public void run() {
            frame.setLocation(X, Y);
        }
    }

    // TASK: Improve ScreenshotUpdater
    // Also all frame children of this 'frame' must be considered
    // when moving out of desktop visible area at snapshot-time.

    /**
     * Used to encapsulate the task of taking a screenshot.
     * It should always run out of the EDT, and need to syncrho/wait
     * correctly with CallSetLocation, for taking snapshot correctly.
     */
    class ScreenshotUpdater extends ComponentAdapter implements Runnable
    {
        CallSetLocation moveBack, moveOut;
        boolean movedOutForScreenshot;

        ScreenshotUpdater() {
            frame.addComponentListener(this);
        }

        private void pauseThread(long millis) {
            try {
                Thread.sleep(millis);
            } catch (InterruptedException ignored) {}
        }

        public void run() {
            while (frameIsNotClosing) {
                pauseThread(75);
                long now = System.currentTimeMillis();
                if (refreshRequested && ((now - lastUpdate) > 500)) {
                    if (frame.isVisible()) {
                        moveBack = new CallSetLocation(frame.getLocation());
                        moveOut = new CallSetLocation(-frame.getWidth(),
                                                      -frame.getHeight());
                        movedOutForScreenshot = true;
                        SwingUtilities.invokeLater(moveOut);
                        // from here:
                        // moveBack is then called in componentMoved.
                    }
                    lastUpdate = now;
                    refreshRequested = false;
                }
            }
        }

        @Override 
        public void componentMoved(ComponentEvent e) {
            if (movedOutForScreenshot) {
                movedOutForScreenshot = false;
                takeScreenSnapshot();
                moveBack.run(); // we already are on the EDT here.
            }
        }
    }

    public void windowOpened(WindowEvent e) {
        lastUpdate = -10000000;
        refreshRequested = true;
        frameIsNotClosing = true;
        ScreenshotUpdater updater = new ScreenshotUpdater();
        new Thread(updater).start();
    }

    public void windowClosing(WindowEvent e) {
        int closeOperation = 
                frame.getDefaultCloseOperation();

        if (closeOperation == JFrame.DISPOSE_ON_CLOSE) {
            frame.removeWindowListener(this);
            frame.removeWindowFocusListener(this);
            frame.removeComponentListener(this);
            frameIsNotClosing = false;
            frame = null;
        }
    }

    public void windowClosed(WindowEvent e) {
        // do nothing
    }

    public void windowIconified(WindowEvent e) {
        // do nothing
    }

    public void windowDeiconified(WindowEvent e) {
        // do nothing
    }

    public void windowActivated(WindowEvent e) {
        // do nothing
    }

    public void windowDeactivated(WindowEvent e) {
        // do nothing
    }

}
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)

Ultima modifica di banryu79 : 29-09-2010 alle 15:40.
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 11-07-2010, 19:40   #3
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
JGhostFrame.java

Quote:
/**
* A sort of "transparent background" JFrame that:
* <p>
* - supports a "fake" transparent title bar<br>
* - give limited support for transparency to menu bar and buttons<br>
* - supports a "fake" transparent content pane (JTransparentComponent).<br>
* - can contain only lightweight components (no heavyweight).
* <p>
* It make this setting as non-opaque all added components to it's special content
* pane (a JTransparentComponent).
* <p>
* The frame itself is an undecorated JFrame: this turn of the visible title bar and
* the insets border commonly used to resize a frame. To overcome this limitation a
* FakeTitleArea container is added on the "north" portion of the JTransparentComponent
* installed as the content pane (it provide common functionality for the title bar and
* manages another small area below the title bar used for supporting a JMenuBar).
* A FakeClientArea is added to the "central" portion of the content pane, and all calls
* for adding components to the frame content pane are redirected to target it as the
* container.<br>
*
* @author francesco
*/
Codice:
package transparentbackground;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
/**
 * A sort of "transparent background" JFrame that:
 * <p>
 * - supports a "fake" transparent title bar<br>
 * - give limited support for transparency to menu bar and buttons<br>
 * - supports a "fake" transparent content pane (JTransparentComponent).<br>
 * - can contain only lightweight components (no heavyweight).
 * <p>
 * It make this setting as non-opaque all added components to it's special content
 * pane (a JTransparentComponent).
 * <p>
 * The frame itself is an undecorated JFrame: this turn of the visible title bar and
 * the insets border commonly used to resize a frame. To overcome this limitation a
 * FakeTitleArea container is added on the "north" portion of the JTransparentComponent
 * installed as the content pane (it provide common functionality for the title bar and
 * manages another small area below the title bar used for supporting a JMenuBar).
 * A FakeClientArea is added to the "central" portion of the content pane, and all calls
 * for adding components to the frame content pane are redirected to target it as the
 * container.<br>
 *
 * @author francesco
 */
public class JGhostFrame extends JFrame
{
    // TASK: Usage Examples
    // 1- usage of JGhostFrame as "decorated" frame (DONE)
    // 2- usage of JGhostFrame as "undecorated", with image that support alpha channels
    // 3- try fancy use of JTransparentComponent as one the subcomponents used in an ordinary JFrame.

    /**
     * Set the global background transparency value for all frames created.
     * @param transparency must be in the range 0-255 inclusive.
     */
    public static void setTransparency(int transparency) {
        if (transparency >= 0  &&  transparency <= 255)
            JTransparentComponent.backgroundTransparency = transparency;
    }
            
    private static final Border STD_BORDER =
            BorderFactory.createLineBorder(Color.black, 1);


    private final JTransparentComponent BACKGROUND;
    private final FakeTitleArea TITLE_AREA;
    private final FakeClientArea CLIENT_AREA;
    private final OpacityManager OPACITY_MANAGER;

    // Overrided properties
    boolean undecorated;


    public JGhostFrame() {
        super();
        super.setUndecorated(true);

        // Change our content pane to JTransparentComponent
        BACKGROUND = new JTransparentComponent(this);
        BACKGROUND.setBorder(STD_BORDER);
        this.setContentPane(BACKGROUND);

        // Build fake title bar
        TITLE_AREA = new FakeTitleArea(this);
        BACKGROUND.add("North", TITLE_AREA);
        
        // Build fake client area
        CLIENT_AREA = new FakeClientArea(this);
        BACKGROUND.add("Center", CLIENT_AREA);

        // initialize the Opacity Manager
        OPACITY_MANAGER =
                new OpacityManager(JTransparentComponent.backgroundTransparency);
    }

    /**
     * Wrapped: the menubar is managed by the FakeTitleArea instead of
     * the standard JFrame's RootPane.
     */
    @Override
    public void setJMenuBar(JMenuBar menubar) {
        TITLE_AREA.setJMenuBar(menubar);
    }

    /**
     * Wrapped: the menubar is managed by the FakeTitleArea instead of
     * the standard JFrame's RootPane.
     */
    @Override
    public JMenuBar getJMenuBar() {
        return TITLE_AREA.getJMenuBar();
    }

    /**
     * Wrapped: each JComponent added must be setted non-opaque, and
     * all children it contains. Only lightweight components.
     */
    @Override
    public Component add(Component comp) {
        OPACITY_MANAGER.makeNonOpaque(comp);
        CLIENT_AREA.add(comp);
        return comp;
    }

    /**
     * Wrapped: each JComponent added must be setted non-opaque, and
     * all children it contains. Only lightweight components.
     */
    @Override
    public Component add(String name, Component comp) {
        OPACITY_MANAGER.makeNonOpaque(comp);
        CLIENT_AREA.add(name, comp);
        return comp;
    }

    /**
     * Wrapped: each JComponent added must be setted non-opaque, and
     * all children it contains. Only lightweight components.
     */
    @Override
    public Component add(Component comp, int index) {
        OPACITY_MANAGER.makeNonOpaque(comp);
        CLIENT_AREA.add(comp, index);
        return comp;
    }

    /**
     * Wrapped: each JComponent added must be setted non-opaque, and
     * all children it contains. Only lightweight components.
     */
    @Override
    public void add(Component comp, Object constraints) {
        if (CLIENT_AREA != null) {
            OPACITY_MANAGER.makeNonOpaque(comp);
            CLIENT_AREA.add(comp, constraints);
        }
        else
            super.add(comp, constraints);
    }

    /**
     * Wrapped: each JComponent added must be setted non-opaque, and
     * all children it contains. Only lightweight components.
     */
    @Override
    public void add(Component comp, Object constraints, int index) {
        if (CLIENT_AREA != null) {
            OPACITY_MANAGER.makeNonOpaque(comp);
            CLIENT_AREA.add(comp, constraints, index);
        }
        else
            super.add(comp, constraints, index);
    }
    
    /**
     * Wrapped: the menubar is managed by the FakeTitleArea instead of
     * the standard JFrame's RootPane.
     */
    @Override
    public void setUndecorated(boolean undecorate) {
        if (undecorate) {
            BACKGROUND.remove(TITLE_AREA);
            this.validate();
        }
        else if (isUndecorated()) {
            BACKGROUND.add("North", TITLE_AREA);
            this.validate();
        }

        this.undecorated = undecorate;
    }

    /**
     * Wrapped: the menubar is managed by the FakeTitleArea instead of
     * the standard JFrame's RootPane.
     */
    @Override
    public boolean isUndecorated() {
        return this.undecorated;
    }

    /**
     * Wrapped: title bar is "faked", so JGhostFrame must explicitly
     * manage title updates.
     */
    @Override
    public void setTitle(String title) {
        super.setTitle(title);
        TITLE_AREA.updateTitle(title);
    }

    
    class FakeTitleArea extends JPanel
    {
        private final JGhostFrame T_FRAME;

        // North area is for title box; South area is for menubar panel.
        private final Box TITLE_BOX;
        private final JLabel LB_TITLE;

        private JMenuBar menubar;

        FakeTitleArea(JGhostFrame f) {
            super();
            setOpaque(false);
            setLayout(new BorderLayout());

            T_FRAME = f;

            TITLE_BOX = Box.createHorizontalBox();
            TITLE_BOX.setOpaque(false);
            TITLE_BOX.setBorder(JGhostFrame.STD_BORDER);
            MouseAdapter moveHandler = new MouseAdapter()
            {
                Point last = null;
                Point offset = new Point();
                @Override public void mouseDragged(MouseEvent e) {
                    if (SwingUtilities.isLeftMouseButton(e)) {
                        Point p = e.getLocationOnScreen();
                        if (last != null) {
                            offset.x = p.x - last.x;
                            offset.y = p.y - last.y;
                            Point loc = T_FRAME.getLocationOnScreen();
                            T_FRAME.setLocation(loc.x + offset.x, loc.y + offset.y);
                        }
                        last = p;
                    }
                }
                @Override public void mouseReleased(MouseEvent e) {
                    if (SwingUtilities.isLeftMouseButton(e))
                        last = null;
                }
            };
            TITLE_BOX.addMouseMotionListener(moveHandler);
            TITLE_BOX.addMouseListener(moveHandler);

            JLabel resizer = new JLabel("[o]");
            resizer.setToolTipText("resize");
            MouseAdapter resizeHandler = new MouseAdapter()
            {
                Point last = null;
                Point offset = new Point();
                @Override public void mouseDragged(MouseEvent e) {
                    if (SwingUtilities.isLeftMouseButton(e)) {
                        Point p = e.getPoint();
                            if (last != null && T_FRAME.isVisible()) {
                            offset.x = p.x - last.x;
                            offset.y = p.y - last.y;
                            Dimension size = T_FRAME.getSize();
                            int newX = size.width + offset.x;
                            int newY = size.height + offset.y;
                            T_FRAME.setSize(newX, newY);
                        }
                        last = p;
                    }
                }
                @Override public void mouseReleased(MouseEvent e) {
                    if (SwingUtilities.isLeftMouseButton(e))
                        last = null;
                }
            };
            resizer.addMouseMotionListener(resizeHandler);
            resizer.addMouseListener(resizeHandler);

            JLabel iconizer = new JLabel("[-]");
            iconizer.setToolTipText("iconize");
            iconizer.addMouseListener(new MouseAdapter() {
                @Override public void mouseReleased(MouseEvent e) {
                    if (SwingUtilities.isLeftMouseButton(e))
                        T_FRAME.setExtendedState(JFrame.ICONIFIED);
                }
            });

            JLabel maximizer = new JLabel("[#]");
            maximizer.setToolTipText("maximize");
            maximizer.addMouseListener(new MouseAdapter() {
                Rectangle bounds = null;
                @Override public void mouseReleased(MouseEvent e) {
                    if (SwingUtilities.isLeftMouseButton(e)) {
                        int state = T_FRAME.getExtendedState();
                        if ((state & JFrame.MAXIMIZED_BOTH) != JFrame.MAXIMIZED_BOTH) {
                            bounds = T_FRAME.getBounds(bounds);
                            T_FRAME.setExtendedState(JFrame.MAXIMIZED_BOTH);
                        }
                        else
                            T_FRAME.setBounds(bounds);
                    }
                }
            });

            JLabel quitter = new JLabel("[x]");
            quitter.setToolTipText("close");
            quitter.addMouseListener(new MouseAdapter() {
                @Override public void mouseReleased(MouseEvent e) {
                    if (SwingUtilities.isLeftMouseButton(e)) {
                        WindowEvent close = new WindowEvent(T_FRAME, WindowEvent.WINDOW_CLOSING);
                        T_FRAME.dispatchEvent(close);
                    }
                }
            });

            LB_TITLE = new JLabel();
            LB_TITLE.setOpaque(false);

            TITLE_BOX.add(Box.createHorizontalStrut(1));
            TITLE_BOX.add(resizer);
            TITLE_BOX.add(Box.createHorizontalGlue());
            TITLE_BOX.add(LB_TITLE);
            TITLE_BOX.add(Box.createHorizontalGlue());
            TITLE_BOX.add(iconizer);
            TITLE_BOX.add(Box.createHorizontalStrut(3));
            TITLE_BOX.add(maximizer);
            TITLE_BOX.add(Box.createHorizontalStrut(3));
            TITLE_BOX.add(quitter);
            TITLE_BOX.add(Box.createHorizontalStrut(1));

            this.add(TITLE_BOX, BorderLayout.NORTH);
        }

        private void updateTitle(String title) {
            LB_TITLE.setText(title);
        }

        /**
         * Wrapped: any Component added must be setted non-opaque, and
         * all children it contains, so only JComponent and its subclasses
         * are allowed.
         */
        public void setJMenuBar(JMenuBar menubar) {
            if (menubar != null) {
                OPACITY_MANAGER.makeNonOpaque(menubar);
                menubar.setBorder(JGhostFrame.STD_BORDER);
                this.menubar = menubar;
                this.add(menubar, BorderLayout.SOUTH);
            }
        }

        public JMenuBar getJMenuBar() {
            return this.menubar;
        }
    }

    
    class FakeClientArea extends JPanel
    {
        private final JGhostFrame T_FRAME;

        FakeClientArea(JGhostFrame f) {
            T_FRAME = f;
            setOpaque(false);
            setBorder(JGhostFrame.STD_BORDER);
            // mimic a frame content pane
            setLayout(new BorderLayout());
        }
    }

}
Ora JGhostFrame fa uso di OpacityManager per gestire le questioni relative alla trasparenza quando gli viene aggiunto (metodi add) un child component:
Codice:
package transparentbackground;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.util.Stack;
import javax.swing.JComponent;

/**
 * This class is an helper used during add() operation on a "ghost frame", for validation
 * and opacity setting.
 * <p>
 * It performs validation on the component to be added because only Swing "lightweight"
 * components have the setOpacity() method that enables translucency for their background.
 *
 * @author francesco
 */
public class OpacityManager
{
     private static final String MSG_INVALID_COMPONENT =
            "Only \"lightweight\" components could be added.";

     
    /**
     * utility stack of components that allow easy insertion (pushes)
     * of all the children of a container
     */
    private class ComponentStack
    {
        private Stack<Component> stack =
                new Stack<Component>();

        public void push(Component comp) {
            stack.push(comp);
        }

        public Component pop() {
            return stack.pop();
        }

        public Component peek() {
            return stack.peek();
        }

        public boolean notEmpty() {
            return !stack.empty();
        }

        public void pushChildren(Container container) {
            for (Component c : container.getComponents())
                stack.push(c);
        }

        public void clear() {
            stack.clear();
        }
    }
    
    private final ComponentStack STACK;
    private final int OPACITY;

    /**
     * Construct an OpacityManager for a given transparency
     * @param alpha  the alpha value for transparency (0-255)
     */
    public OpacityManager(int alpha) {
        STACK = new ComponentStack();
        OPACITY = alpha;
    }

    /**
     * Validate and set the opacity for a given Component and all
     * its children that have to be added to a "ghost frame"
     * @param comp the candidate component
     */
    public void makeNonOpaque(Component comp) {
        STACK.clear();
        STACK.push(comp);

        while (STACK.notEmpty()) {
            Component popped = STACK.pop();
            //System.out.println(popped.getClass().getName());

            if (popped instanceof JComponent) {
                JComponent jComp = (JComponent) popped;
                STACK.pushChildren(jComp);

                // make non-opaque:
                jComp.setOpaque(false);
                // set background color alpha channel transparency
                // to the same value used in the color painted above
                // the screenshot. This is useful for make some
                // components, like buttons, truly transparent
                // (in some LnF, for example: MetalLookAndFeel)
                changeBackgroundOpacity(jComp, OPACITY);
            }
            else if (popped instanceof Container) {
                Container cont = (Container) popped;
                STACK.pushChildren(cont);

                String className = cont.getClass().getName();
                if (! className.startsWith("javax.swing."))
                    throw new IllegalArgumentException(MSG_INVALID_COMPONENT);
            }
            else
                throw new IllegalArgumentException(MSG_INVALID_COMPONENT);
        }
    }

    private void changeBackgroundOpacity(Component comp, int alpha) {
        Color col = comp.getBackground();
        if (col != null)
            comp.setBackground(
                    new Color(col.getRed(), col.getGreen(), col.getBlue(), alpha));
    }
}
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)

Ultima modifica di banryu79 : 29-09-2010 alle 15:49.
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 11-07-2010, 19:45   #4
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Esempio d'uso

E qui sotto tre classi che ne mostrano l'uso (l'esempio + due utility).

DecoratedGhostFrameExample:
Codice:
package transparentbackground.example;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import temp.JTextForm;
import temp.LookNFeelSetter;
import transparentbackground.JGhostFrame;

/**
 * Show a 'decoreted' JGhostFrame
 *
 * @author francesco
 */
public class DecoratedGhostFrameExample
{
    public static void main(String[] args) throws Exception {

        LookNFeelSetter.chooseByIndex(args);

        // create our JGhostFrame, that internally use
        // JTransparentComponent as its content pane:
        JGhostFrame.setTransparency(192);
        final JGhostFrame FRAME = new JGhostFrame();
        FRAME.setTitle("GhostFrame Demo");
        FRAME.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        // add a menu bar:
        JMenuBar menuBar = new JMenuBar();
            JMenu fileMenu = new JMenu("File");
            fileMenu.add(new JMenuItem("New..."));
            fileMenu.addSeparator();
            fileMenu.add(new JMenuItem("Open"));
            fileMenu.addSeparator();
            fileMenu.add(new JMenuItem("Save"));
            fileMenu.add(new JMenuItem("Save as..."));
        menuBar.add(fileMenu);
            JMenu editMenu = new JMenu("Edit");
            editMenu.add(new JMenuItem("Copy"));
            editMenu.add(new JMenuItem("Cut"));
            editMenu.add(new JMenuItem("Paste"));
            editMenu.addSeparator();
            editMenu.add(new JMenuItem("Find"));
        menuBar.add(editMenu);
            JMenu viewMenu = new JMenu("View");
            viewMenu.add(new JMenuItem("Full screen"));
        menuBar.add(viewMenu);
            JMenu helpMenu = new JMenu("Help");
            helpMenu.add(new JMenuItem("Help Contents"));
            helpMenu.add(new JMenuItem("About"));
        menuBar.add(Box.createHorizontalGlue());
        menuBar.add(helpMenu);
        //menuBar.add(new JSeparator(SwingConstants.VERTICAL));
        FRAME.setJMenuBar(menuBar);

        // add a form in the center:
        Box title = Box.createHorizontalBox();
        title.add(Box.createHorizontalStrut(3));
        title.add(new JLabel("Please, fill in this form:"), JLabel.CENTER);
        title.add(Box.createHorizontalGlue());
        FRAME.add(title, BorderLayout.NORTH);

        JTextForm.Builder builder = new JTextForm.Builder();
        builder.setLabels("First Name", "Middle Initial", "Last Name", "Age")
               .setTips("insert your name", "insert your middle name initial",
                        "insert your last name", "insert your age")
               .setMemonics('F', 'M', 'L', 'A')
               .setWidths(15, 1, 15, 3);
        final JTextForm FORM = builder.create();
        FRAME.add(FORM, BorderLayout.CENTER);

        // abb buttons in the south:
        JPanel buttonPan = new JPanel(new FlowLayout(FlowLayout.RIGHT));

        String[] values = {"Example", "of", "a", "checkbox"};
        JComboBox combo = new JComboBox(values);
        buttonPan.add(combo);

        final JButton bMenuR = new JButton("Show/hide Menubar");
        bMenuR.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JMenuBar bar = FRAME.getJMenuBar();
                bar.setVisible(!bar.isVisible());
            }
        });
        buttonPan.add(bMenuR);

        final JButton bUndecor = new JButton("Undecorate");
        JButton bDecor = new JButton("Decorate");
        ActionListener decorators = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JButton but = (JButton) e.getSource();
                FRAME.setUndecorated(but.equals(bUndecor));
            }
        };
        bUndecor.addActionListener(decorators);
        bDecor.addActionListener(decorators);
        buttonPan.add(bUndecor);
        buttonPan.add(bDecor);

        FRAME.add(buttonPan, BorderLayout.SOUTH);


        // show it:
        SwingUtilities.invokeLater(new Runnable() {
            @Override public void run() {
                FRAME.pack();
                FRAME.setVisible(true);
            }
        });
    }
}
LookNFeelSetter:
Codice:
package temp;

import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

/**
 * Utility to set up the LnF for the application from first argument passed on the command line.
 * The argument must be an integer value that represent the index value of the platform's currently
 * installed Look'n'Feels.
 *
 * @author francesco
 */
public class LookNFeelSetter
{
    public static void chooseByIndex(String[] args) {

        String msgError =
                "Usage:\njava JGhostFrame [integer]\nYou must pass a valid integer argument";

        if (args.length < 1) {
            throw new RuntimeException(msgError);
        }

        int argValue;
        try {
            argValue = Integer.parseInt(args[0]);
        } catch (NumberFormatException ex) {
            throw new RuntimeException(msgError, ex);
        }

        String lnfClassName = null;
        LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels();
        try {
            lnfClassName = infos[argValue].getClassName();
            System.out.println("Using "+lnfClassName);
        } catch (ArrayIndexOutOfBoundsException ex) {
            System.err.println("Argument value too big ("+argValue+").\nMax allowed is "+infos.length);
            throw new RuntimeException(msgError, ex);
        }

        try {
            UIManager.setLookAndFeel(lnfClassName);
        } catch (Exception ex) {
            System.err.println("Look'n'Feel installation failed.");
            System.exit(1);
        }
    }
}
JTextForm:
Codice:
package temp;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * A simple label/field form panel
 *
 * @author francesco
 */
public class JTextForm extends JPanel
{
    static String[] labels = {"Label"};
    static char[] mnemonics = {'L'};
    static int[] widths = {15};
    static String[] tips = {"this is a tip"};

    public static class Builder
    {
        public JTextForm.Builder setLabels(String... ls) {
            labels = ls;  return this;
        }
        
        public JTextForm.Builder setMemonics(char... ms) {
            mnemonics = ms;  return this;
        }

        public JTextForm.Builder setWidths(int... ws) {
            widths = ws;  return this;
        }
        
        public JTextForm.Builder setTips(String... ts) {
            tips = ts;  return this;
        }

        public JTextForm create() {
            return new JTextForm();
        }
    }

    private JTextField[] fields;

    public JTextForm() {
        super(new BorderLayout());

        JPanel labelPan = new JPanel(new GridLayout(labels.length, 1));
        JPanel fieldPan = new JPanel(new GridLayout(labels.length, 1));
        this.add(labelPan, BorderLayout.WEST);
        this.add(fieldPan, BorderLayout.CENTER);

        fields = new JTextField[labels.length];
        for (int i=0; i<labels.length; i++) {
            fields[i] = new JTextField();
            if (i < tips.length)   fields[i].setToolTipText(tips[i]);
            if (i < widths.length) fields[i].setColumns(widths[i]);

            JLabel l = new JLabel(labels[i], JLabel.RIGHT);
            l.setLabelFor(fields[i]);
            if (i < mnemonics.length) l.setDisplayedMnemonic(mnemonics[i]);
            labelPan.add(l);

            JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT));
            p.add(fields[i]);
            fieldPan.add(p);
        }
    }

    public String getText(int i) {
        return fields[i].getText();
    }
}
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)

Ultima modifica di banryu79 : 29-09-2010 alle 15:52.
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 11-07-2010, 23:41   #5
Ryuzaki_Eru
Senior Member
 
L'Avatar di Ryuzaki_Eru
 
Iscritto dal: Sep 2009
Città: Nel mondo dei sogni
Messaggi: 4131
Complimenti
Ryuzaki_Eru è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2010, 11:17   #6
*andre*
Senior Member
 
Iscritto dal: Sep 2007
Messaggi: 1071
ottimo davvero complimenti
__________________
Affari: ariakasneverborne, PanCar, Luk@°°°, Fabio310, kintaro oe, krike, fabry180384, dariox am2, chiadoz, windsofchange, dado1979, Rudyduca, aleforumista, Sheva77
*andre* è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2010, 15:19   #7
ally
Bannato
 
L'Avatar di ally
 
Iscritto dal: Jan 2003
Città:
Messaggi: 4423
...decisamente interessante...

...ciao Andrea...
ally è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2010, 20:43   #8
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Ciao, interessante, io avevo adottato la stessa tecnica con Labview quando ero piccino

Ti volevo chiedere, col trascinamento come si comporta, è veloce?
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2010, 23:55   #9
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Bel lavoro!
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 13-07-2010, 08:34   #10
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Quote:
Originariamente inviato da MEMon Guarda i messaggi
Ti volevo chiedere, col trascinamento come si comporta, è veloce?
Sì, trascinamento/resize della window non è affatto un problema, la "fregatura" con questo sistema è dovuta alla necessità di far momentaneamente sparire la finestra stessa dall'area visibile del desktop, ogni volta che si deve aggiornare lo snapshot dello screen.

E' questione di un attimo, ma quell'attimo l'utente lo percepisce come una rapida successione scomparsa-ricomparsa della finestra.
(Gli approcci sono due: usare setVisible oppure traslare la location della finestra in una posizione logica non compresa nell'area visibile del desktop, io ho scelto la seconda).
Questo aspetto sarebbe la parte "da limare" e ho intenzione di investigare un po' per vedere se trovo un 'escamotage'...

L'approccio comunque era interessante prima che Swing introducesse il supporto alle Translucent & Shaped Windows; e in particolare era interessante nella sua versione più semplice quando uno vuole usare come finestra d'interfaccia un'immagine particolare che non è rettangolare (ad esempio, nell'immagine del mio desktop postata, la finestra d'interfaccia del mio cellulare).

Io ho solo voluto provare a vedere se riuscivo a estenderlo in modo tale da realizzare una classe che dal punto di vista del codice client fosse in tutto e per tutto paragonabile a JFrame.

P.S.:
Comunque puoi povarlo di persona: devi solo crearti un nuovo progetto nella tua IDE preferita che supporti Java, crearti un package di nome 'transparentbackground' e copia-incollare le prime due classi postate.
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)

Ultima modifica di banryu79 : 13-07-2010 alle 08:40.
banryu79 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


AMD Advancing AI 2026: l'hardware AMD per le elaborazioni IA del futuro, tra GPU, CPU e robot AMD Advancing AI 2026: l'hardware AMD per le ela...
Tascabile e con Android: BOOX Go 6 Gen II è diverso da tutti gli altri e-reader Tascabile e con Android: BOOX Go 6 Gen II &egrav...
Recensione Lenovo Idea Tab Plus: il tablet da 12 pollici che costa meno di 300 euro Recensione Lenovo Idea Tab Plus: il tablet da 12...
Oltre il contante e le crypto: tutto sull'Euro Digitale e la nuova sovranità monetaria europea Oltre il contante e le crypto: tutto sull'Euro D...
Recensione HONOR Magic V6: spessore record e super batteria. È lui il fold da battere? Recensione HONOR Magic V6: spessore record e sup...
Google introduce l'accesso all'account c...
Basta una cartella e l'agente di Claude ...
OpenAI: i modelli "ragionano meglio...
Dieci morti o 100 milioni di danni: le s...
La modalità vocale di Claude lasc...
Marvel's Wolverine torna a mostrarsi con...
Aruba AI Site Manager, l'IA per gestire ...
Servono 4 chip Huawei per pareggiare una...
Crollo di benzina e diesel in Europa: le...
Il nuovo trailer del film di Resident Ev...
Star Wars Zero Company svela il cast e p...
Da 0,7 a 20 FPS: Doom domato su una CPU ...
Amazon col caldo fa pazzie: TOP 15 con p...
Lego ricrea Donkey Kong da sala giochi e...
ChatGPT ignora l'embolia polmonare: uten...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 12:46.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v