Results 1 to 20 of 28
- 01-14-2013, 01:34 AM #1
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
alphacomposite for multiple shapes (cut a hole through them)
Hi,
Making a Java Clock. I just need a little help with getting the final fillOval method.
Ideally id like the fillOval method to reveal the JPanel background. So if I used a background color, or image it would be visible.
Its basically cutting a hole in several shapes stacked ontop of each other.
Heres the code
Java Code:/* * Rings - A Java RingClock Implementation */ package rings; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.text.SimpleDateFormat; import java.util.Calendar; import javax.swing.JFrame; import javax.swing.JPanel; /** * * @author aubrey */ public class Rings extends JPanel { //degree parameters for hours, minutes, and start. int ito, to, from; //current time int hours, mins; public Rings() { update(); initialize(); } public void initialize() { setSize(200, 200); //set fillArc to 12 O Clock //ie from = 90; from = 90; } public void update(){ //DateTime Example //String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime()); //Time Example String timeStamp = new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime()); System.out.println(timeStamp); String tempMins = timeStamp.substring(3,5); System.out.println("Minutes: "+tempMins); mins= Integer.parseInt(tempMins); to = mins*6; String tempHours = timeStamp.substring(0,2); hours= Integer.parseInt(tempHours); switch(hours) { case 13: hours=1; break; case 14: hours=2; break; case 15: hours=3; break; case 16: hours=4; break; case 17: hours=5; break; case 18: hours=6; break; case 19: hours=7; break; case 20: hours=8; break; case 21: hours=9; break; case 22: hours=10; break; case 23: hours=11; break; case 00: hours=12; break; default: break; } System.out.println("Hours: "+hours); int degree = 360/12; ito = hours*degree; } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D)g; //background fill g2d.setColor(Color.lightGray); g2d.fillOval(25, 25, 100, 100); //outer - current minutes g2d.setColor(Color.GRAY); g2d.fillArc(25, 25, 100, 100, from, -to); //second background fill g2d.setColor(Color.lightGray); g2d.fillOval(35, 35, 80, 80); //inner - current hours g2d.setColor(Color.darkGray); g2d.fillArc(35, 35, 80, 80, from, -ito); //third fill - need to cut a hole here! //AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OUT); //g2d.setComposite(ac); g2d.setColor(Color.lightGray.brighter()); g2d.fillOval(45, 45, 60, 60); } public static void main(String[] args) { Rings ringClockPanel = new Rings(); JFrame f = new JFrame(); f.setSize(200, 200); f.getContentPane().add(ringClockPanel); f.setVisible(true); } }Last edited by aubreybourke; 01-14-2013 at 01:18 PM.
- 01-14-2013, 04:17 AM #2
Re: alphacomposite for multiple shapes (cut a hole through them)
Do you have a specific question? 'I just need help' isn't one.
dbWhy do they call it rush hour when nothing moves? - Robin Williams
- 01-14-2013, 01:09 PM #3
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
Re: alphacomposite for multiple shapes (cut a hole through them)
Hi Daryl,
Yes, I basically need to know how to properly use alphacomposite on the final filloval method in my paint method on lines 118-123. I have commented out my attempt, but I'm probably close.
I need the effect that there is a transparent hole through all the previous fillOvals and fillArc's. Which will reveal the JPanel underneath.
I think the correct rule is DST_OUT. The parameters for the correct size and location of this final filled oval are on line 123.
Nice to see you again Daryl.
Aubrey.
- 01-14-2013, 01:11 PM #4
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
Re: alphacomposite for multiple shapes (cut a hole through them)
BTW the code compiles and runs. So it will be obvious what is happening here. Instead of the final fill oval making a small white oval in the center, I would like that piece to be transparent.
- 01-14-2013, 01:54 PM #5
Re: alphacomposite for multiple shapes (cut a hole through them)
I think your problem lies here:
Any application of AlphaComposite will have the same effect on the panel's background painting as it has on any Shapes already drawn.
Why not just g.setColor(getBackground()); and fillOval(...)?I need the effect that there is a transparent hole through all the previous fillOvals and fillArc's.
Also, have you seen this page which illustrates the use of AlphaComposite? Compositing Graphics (The Java™ Tutorials > 2D Graphics > Advanced Topics in Java2D)
dbWhy do they call it rush hour when nothing moves? - Robin Williams
- 01-14-2013, 02:27 PM #6
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
Re: alphacomposite for multiple shapes (cut a hole through them)
Yes, it should. But, when I use the DST_OUT rule the oval somehow is black. So, maybe its close. I think we can exlude these two possiblilities.
1. the composite rule (looks right, but there is another parameter that accepts value between 0 and 1 representing tranparency)
2. the previous fills (maybe the composite rule only applies to the current obstructing layer. There are other layers under this one, and the rule may not take this into account - I dont know)
But, more likely, I think the problem is somewhere here:
3. the Jpanel background
4. the JFrame container
5. the JFrame background
because we're getting a hole, its just either not going deep enough or too deep.
Yes I have seen the 2D Graphics tutorial. Its a very good page, with the applet.
Why not just g.setColor(getBackground()); and fillOval(...)?
Also, have you seen this page which illustrates the use of AlphaComposite? Compositing Graphics (The Java™ Tutorials > 2D Graphics > Advanced Topics in Java2D)
Using the same color as the background is possible. But, I would like to make this clock a component, a JPanel, then call setOpaque(false) on it. So when I add it to some other container (which may have a wallpaper) the center reveals the underlying wallpaper.
Regards
Aubrey.
- 01-14-2013, 03:48 PM #7
Re: alphacomposite for multiple shapes (cut a hole through them)
There are no 'layers' -- there's just the source, which is what you draw/fill after setting the composite, and the destination, which is what's already there.
You're going to need to draw to a BufferedImage of a type that supports transparency and drawImage(...) in the paintComponent(...) override. Take a stab at it and post back if you have any trouble getting there.
dbWhy do they call it rush hour when nothing moves? - Robin Williams
- 01-14-2013, 03:58 PM #8
Re: alphacomposite for multiple shapes (cut a hole through them)
Aw, what the heck. you can use either SrcOut or Clear.
dbJava Code:import java.awt.*; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.image.BufferedImage; import javax.swing.*; public class Hole { static final int SIDE = 400; public static void main(String[] args) throws Exception { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new Hole().makeUI(); } }); } public void makeUI() { final JPanel back = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.blue); for (int i = 0; i < getWidth(); i += 10) { for (int j = 0; j < getHeight(); j += 10) { if ((i + j) % 20 == 0) { g.fillRect(i, j, 10, 10); } } } } @Override public Dimension getPreferredSize() { return new Dimension(SIDE, SIDE); } }; final BufferedImage image = new BufferedImage(SIDE, SIDE, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = image.createGraphics(); g2.setColor(Color.red); g2.fillRect(30, 30, SIDE - 60, SIDE - 60); g2.setColor(Color.yellow); g2.fillOval(0, 0, SIDE / 2 + 60, SIDE / 2 + 60); g2.setColor(Color.cyan); g2.fillOval(SIDE / 2 - 60, SIDE / 2 - 60, SIDE / 2 + 60, SIDE / 2 + 60); g2.setComposite(AlphaComposite.SrcOut); g2.fillOval(SIDE / 4, SIDE / 4, SIDE / 2, SIDE / 2); final JPanel front = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(image, 0, 0, this); } }; front.setOpaque(false); JFrame frame = new JFrame(); final Component contentPane = frame.getContentPane(); contentPane.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { front.setSize(contentPane.getSize()); } }); frame.add(front); frame.add(back); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); frame.setVisible(true); } }Why do they call it rush hour when nothing moves? - Robin Williams
- 01-14-2013, 04:04 PM #9
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
Re: alphacomposite for multiple shapes (cut a hole through them)
Ahh yeah! Deadly! Thanks Dayrl, works now...
- 01-14-2013, 04:07 PM #10
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
Re: alphacomposite for multiple shapes (cut a hole through them)
Here's the working code:
Java Code:/* * Rings - A Java RingClock Implementation */ package rings; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Composite; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.text.SimpleDateFormat; import java.util.Calendar; import javax.swing.JFrame; import javax.swing.JPanel; /** * * @author aubrey */ public class Rings extends JPanel { int ito, to, from; int hours, mins; BufferedImage image; public Rings() { setBackground(Color.GRAY); image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB); update(); initialize(); } public void initialize() { setSize(200, 200); //set fillArc to 12 O Clock //ie from = 90; from = 90; } public void update(){ //DateTime Example //String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime()); //Time Example String timeStamp = new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime()); System.out.println(timeStamp); String tempMins = timeStamp.substring(3,5); System.out.println("Minutes: "+tempMins); mins= Integer.parseInt(tempMins); to = mins*6; String tempHours = timeStamp.substring(0,2); hours= Integer.parseInt(tempHours); switch(hours) { case 13: hours=1; break; case 14: hours=2; break; case 15: hours=3; break; case 16: hours=4; break; case 17: hours=5; break; case 18: hours=6; break; case 19: hours=7; break; case 20: hours=8; break; case 21: hours=9; break; case 22: hours=10; break; case 23: hours=11; break; case 00: hours=12; break; default: break; } System.out.println("Hours: "+hours); int degree = 360/12; ito = hours*degree; } public void paintComponent(Graphics g) { super.paintComponent(g); //Graphics2D gc = (Graphics2D) g; //Graphics2D g2d = (Graphics2D)g; //Composite originalComposite = g2d.getComposite(); Graphics2D gc = image.createGraphics(); RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); renderHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); gc.setRenderingHints(renderHints); gc.setColor(Color.lightGray); gc.fillOval(25, 25, 100, 100); // AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.DST_IN); //g2d.setComposite(ac); //gc.setComposite(originalComposite); gc.setColor(Color.GRAY); gc.fillArc(25, 25, 100, 100, from, -to); gc.setColor(Color.WHITE); gc.fillOval(35, 35, 80, 80); gc.setColor(Color.darkGray); gc.fillArc(35, 35, 80, 80, from, -ito); // AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.DST_OUT); AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.DST_OUT); gc.setComposite(ac); //g2d.setColor(Color.GREEN); gc.setColor(Color.lightGray.brighter()); gc.fillOval(45, 45, 60, 60); g.drawImage(image, 0, 0, null); } public static void main(String[] args) { Rings ringClockPanel = new Rings(); JFrame f = new JFrame(); f.setSize(200, 200); f.getContentPane().add(ringClockPanel); f.setVisible(true); } }
- 01-14-2013, 04:12 PM #11
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
Re: alphacomposite for multiple shapes (cut a hole through them)
Yours looks like a rubber duck! :)
- 01-14-2013, 04:19 PM #12
Re: alphacomposite for multiple shapes (cut a hole through them)
My suggestions:
1. Don't create a new BufferedImage every time through the paintComponent(...) method.
2. Don't draw to the BufferedImage in the paintComponent(...) method.
If the panel may be resized, create a new BufferedImage in a ComponentListener#componentResized(...), and draw to it. If that results in the old image still appearing after the resize, add a call to repaint() wrapped in a SwingUtilities#invokeLater(...).
dbWhy do they call it rush hour when nothing moves? - Robin Williams
- 01-14-2013, 06:40 PM #13
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
- 01-14-2013, 06:46 PM #14
Re: alphacomposite for multiple shapes (cut a hole through them)
Moved from New to Java
dbWhy do they call it rush hour when nothing moves? - Robin Williams
- 01-19-2013, 11:50 AM #15
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
Re: alphacomposite for multiple shapes (cut a hole through them)
Having trouble with transparency painting. The clock flickers on repaint, because I have to clear the rectangle first and paint the updated image. It doesnt seem to do this in one step. Also Im not sure what I should do to stop the flickering. What does an Image observer do?
Updated code, compile and runs:
Java Code:/* * Rings - A Java RingClock Implementation (like conky lotus rings) */ package rings; import com.sun.awt.AWTUtilities; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Composite; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.text.SimpleDateFormat; import java.util.Calendar; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JWindow; import javax.swing.Timer; /** * * @author aubrey */ public class AlphaRings extends JPanel { int ito, to, from; int hours, mins; BufferedImage image; static JWindow f; static AlphaRings ringClockPanel; Graphics g; Graphics2D g2d, gc; public AlphaRings() { //setBackground(Color.GRAY); setOpaque(false); update(); initialize(); timer.start(); } public void initialize() { setSize(200, 200); //set fillArc to 12 O Clock //ie from = 90; from = 90; } public void update(){ //DateTime Example //String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime()); //Time Example String timeStamp = new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime()); System.out.println(timeStamp); String tempMins = timeStamp.substring(3,5); System.out.println("Minutes: "+tempMins); mins= Integer.parseInt(tempMins); to = mins*6; String tempHours = timeStamp.substring(0,2); hours= Integer.parseInt(tempHours); switch(hours) { case 13: hours=1; break; case 14: hours=2; break; case 15: hours=3; break; case 16: hours=4; break; case 17: hours=5; break; case 18: hours=6; break; case 19: hours=7; break; case 20: hours=8; break; case 21: hours=9; break; case 22: hours=10; break; case 23: hours=11; break; case 00: hours=12; break; default: break; } System.out.println("Hours: "+hours); int degree = 360/12; ito = hours*degree; } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D)g; image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB); Graphics2D gc = image.createGraphics(); Composite originalComposite = gc.getComposite(); RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); renderHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); gc.setRenderingHints(renderHints); AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f); gc.setComposite(ac); gc.setColor(Color.WHITE); gc.fillOval(25, 25, 100, 100); gc.setComposite(originalComposite); ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f); gc.setComposite(ac); gc.setColor(Color.WHITE); gc.fillArc(25, 25, 100, 100, from, -to); ac = AlphaComposite.getInstance(AlphaComposite.DST_OUT); gc.setComposite(ac); gc.fillOval(35,35, 80,80); gc.setComposite(originalComposite); ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f); gc.setComposite(ac); gc.setColor(Color.WHITE); gc.fillOval(35, 35, 80, 80); gc.setComposite(originalComposite); gc.setColor(Color.lightGray); gc.fillArc(35, 35, 80, 80, from, -ito); ac = AlphaComposite.getInstance(AlphaComposite.DST_OUT); gc.setComposite(ac); //gc.setColor(Color.lightGray.brighter()); gc.fillOval(45, 45, 60, 60); gc.setComposite(originalComposite); Composite originalComposite1 = g2d.getComposite(); ac = AlphaComposite.getInstance(AlphaComposite.DST_OUT); g2d.setComposite(ac); //gc.setComposite(originalComposite); g2d.clearRect(0, 0, 200, 200); g2d.setComposite(originalComposite1); g2d.drawImage(image, 0, 0, null); } private final Timer timer = new Timer(1000*60, new ActionListener() { public void actionPerformed(ActionEvent e) { update(); repaint(); } }); public static void main(String[] args) { ringClockPanel = new AlphaRings(); f = new JWindow(); //f.setUndecorated(true); f.setSize(200, 200); //AWTUtilities.setWindowOpacity(f, .1f); AWTUtilities.setWindowOpaque(f, false); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); double width = screenSize.getWidth(); double height = screenSize.getHeight(); int w = (int)width; System.out.println(w); int halfed = (w/2)-(f.getWidth()/2); f.setLocation(1700, 20); f.getContentPane().add(ringClockPanel); f.setVisible(true); } }
- 01-19-2013, 05:56 PM #16
Re: alphacomposite for multiple shapes (cut a hole through them)
Notes after a (very) quick glance:
Unused variables w and halfed. Did you mean to use them to set the frame's location on screen?
Rather than set the size of a JWindow, I would override getPreferredSize() in AlphaRings and pack() the window.
Al Swing constructors and methods should be invoked on the EDT. Lesson: Concurrency in Swing (The Java™ Tutorials > Creating a GUI With JFC/Swing)
dbWhy do they call it rush hour when nothing moves? - Robin Williams
- 01-19-2013, 07:20 PM #17
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
Re: alphacomposite for multiple shapes (cut a hole through them)
yes variables w and halfed I need for centering the frame.
I'm not exactly sure what you mean about overiding getPreferredSize() in AlphaRings. Whats wrong with the default implementation?
So, I tried frame.setSize(ringClockPanel.getPreferredSize()) and them frame.pack() but no joy, must have got something wrong.
I read the swing concurrency lesson. That clears up allot. But after reading I Also I think the problem I'm having is related to my windowmanager. I'm running a lightweight linux os called "Lubuntu" and it doesnt support transparency at all. I managed to get transparency to work by replacing the LXDE wm with compiz. The problem is animation. However, I'm fairly sure the same code runs perfectly on windows.
I did a check to see if the timer is calling repaint on the EDT and it is. Furthermore, I also put what was in the timer scheduled to run SwingUtilities.invokeLater - same storey with the flicker here.
Aubrey.Last edited by aubreybourke; 01-19-2013 at 08:42 PM.
- 01-19-2013, 08:36 PM #18
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
Re: alphacomposite for multiple shapes (cut a hole through them)
I'm fairly sure my linux configuration isn't designed to work the way it does with transparency.
Its not related to just the alphaRings either, I tested it with another opaque app (which runs fine in windows) but also flickers on each call to repaint in compiz.
Its Because Lubuntu uses the LXDE window manager. So looks like the problem is somewhere between LXDE and Compiz (which are kind of opposites, one is minimalistic and the other is more intensive. So they probably aren't supposed to work together).
There's really two problems I can reproduce with this LXDE/Compiz configuration if anyone is interested:
one is the flicker on each repaint.
And the other is painting ontop of the previous paint (which normally doesnt happen. I shouldnt have to call clearRectangle at all).
Sorry Daryl, you can go ahead and close this thread.Last edited by aubreybourke; 01-19-2013 at 08:40 PM.
- 01-20-2013, 02:44 AM #19
Re: alphacomposite for multiple shapes (cut a hole through them)
And what about the Swing methods and constructors in the main(...) method?I also put what was in the timer scheduled to run SwingUtilities.invokeLater
I'm guessing you ended up with a tiny little frame. I recommended overriding getPreferrredSize() to return a Dimension appropriate to the content, which looks to me like being [200, 200]:I tried frame.setSize(ringClockPanel.getPreferredSize()) and them frame.pack() but no joy, must have got something wrong.Also, after a closer look at your present code, I think this can be done without AlphaComposite, using drawArc(...) to draw to the BufferedImage, and omitting the call to super.paintComponent(g); I'll maybe try that after my second cup of coffee :yawn:Java Code:#Override public Dimension getPreferredSize() { return new Dimension(200, 200); }
dbWhy do they call it rush hour when nothing moves? - Robin Williams
- 01-20-2013, 06:50 PM #20
Member
- Join Date
- Feb 2012
- Location
- Dublin
- Posts
- 29
- Rep Power
- 0
Re: alphacomposite for multiple shapes (cut a hole through them)
Is there any need to put the methods inside the constructor into the invokeLater, because I create the object from invokeLater anyhow?
will do the getPrefferedSize now.
You tired of coffee? That's not good, you should buy some redbull for a change.
Best
Aubrey.
Similar Threads
-
Need help on Multiple Moving Shapes
By Majeh in forum New To JavaReplies: 1Last Post: 03-19-2011, 08:54 PM -
Security hole by Race condition
By simorgh in forum Threads and SynchronizationReplies: 0Last Post: 03-24-2010, 04:10 AM -
Struggling with AlphaComposite .. please help me
By jeshmal4u in forum Java 2DReplies: 3Last Post: 03-08-2010, 05:11 AM -
Inserting multiple shapes using mouseListener
By thayalan in forum Java 2DReplies: 1Last Post: 03-14-2009, 02:43 PM


1Likes
LinkBack URL
About LinkBacks
Reply With Quote


Bookmarks