swing - Is it possible to make some items in the menu to fade in with 500 ms onset delay in Java? -
i have jmenu of 16 jmenuitems, of want 3 items displayed upfront , rest 13 items fade in 500 ms delay. there way animation in java?
this not easy sounds.
basically thought "i'll attach popup listener popup menu menu items added to"...but apparently doesn't work well. menu popup built dynamically on demand. makes sense, it's still pain.
so instead, i've found if wait addnotify
can start animation engine.
the animation engine simple concept. has javax.swing.timer
ticks @ regular interval. coupled start time , duration, can calculate progress of animation , generate alpha
value required.
the thing left notify interested parties animation has changed , voila...
import java.awt.alphacomposite; import java.awt.borderlayout; import java.awt.container; import java.awt.dimension; import java.awt.eventqueue; import java.awt.graphics; import java.awt.graphics2d; import java.awt.event.actionevent; import java.awt.event.actionlistener; import java.text.numberformat; import java.util.arraylist; import java.util.list; import javax.swing.jframe; import javax.swing.jmenu; import javax.swing.jmenubar; import javax.swing.jmenuitem; import javax.swing.jpanel; import javax.swing.jpopupmenu; import javax.swing.timer; import javax.swing.uimanager; import javax.swing.unsupportedlookandfeelexception; import javax.swing.event.popupmenuevent; import javax.swing.event.popupmenulistener; public class fademenu { private animationengine engine; public static void main(string[] args) { new fademenu(); } public fademenu() { eventqueue.invokelater(new runnable() { @override public void run() { try { uimanager.setlookandfeel(uimanager.getsystemlookandfeelclassname()); } catch (classnotfoundexception | instantiationexception | illegalaccessexception | unsupportedlookandfeelexception ex) { } engine = new animationengine(); jmenubar mb = new jmenubar(); jmenu flip = new jmenu("flip"); flip.add("static 1"); flip.add("static 2"); flip.add("static 3"); flip.add(new fademenuitem("fade 1")); flip.add(new fademenuitem("fade 2")); flip.add(new fademenuitem("fade 3")); flip.add(new fademenuitem("fade 4")); mb.add(flip); jframe frame = new jframe("testing"); frame.setjmenubar(mb); frame.setdefaultcloseoperation(jframe.exit_on_close); frame.setlayout(new borderlayout()); frame.add(new testpane()); frame.pack(); frame.setlocationrelativeto(null); frame.setvisible(true); } }); } public class testpane extends jpanel { public testpane() { } @override public dimension getpreferredsize() { return new dimension(200, 200); } } public class fademenuitem extends jmenuitem { public fademenuitem(string text) { super(text); engine.addtiminglistener(new timinglistener() { @override public void timingevent() { repaint(); } }); } @override protected void paintcomponent(graphics g) { graphics2d g2d = (graphics2d) g.create(); g2d.setcomposite(alphacomposite.srcover.derive(engine.getalpha())); super.paintcomponent(g2d); g2d.dispose(); } @override public void removenotify() { container parent = getparent(); if (parent instanceof jpopupmenu) { jpopupmenu menu = (jpopupmenu) parent; engine.stop(); } super.removenotify(); } @override public void addnotify() { super.addnotify(); container parent = getparent(); if (parent instanceof jpopupmenu) { jpopupmenu menu = (jpopupmenu) parent; engine.restart(); } } } public interface timinglistener { public void timingevent(); } public class animationengine { private timer fade; private float alpha; private long starttime; private long duration = 1000; private list<timinglistener> listeners; public animationengine() { listeners = new arraylist<>(5); fade = new timer(40, new actionlistener() { @override public void actionperformed(actionevent e) { long elapsed = system.currenttimemillis() - starttime; if (elapsed >= duration) { ((timer) e.getsource()).stop(); alpha = 1f; } else { alpha = (float) elapsed / (float) duration; } firetimingevent(); } }); fade.setrepeats(true); fade.setcoalesce(true); fade.setinitialdelay(500); } public void addtiminglistener(timinglistener listener) { listeners.add(listener); } public void removetiminglistener(timinglistener listener) { listeners.add(listener); } protected void firetimingevent() { (timinglistener listener : listeners) { listener.timingevent(); } } public void restart() { fade.stop(); alpha = 0; firetimingevent(); starttime = system.currenttimemillis(); fade.start(); } public float getalpha() { return alpha; } public void stop() { fade.stop(); } } }
while works on windows, i'd concerned might not work on other platforms, means menus generated controlled (in part) ui delegate. become messy, quickly
Comments
Post a Comment