Results 1 to 20 of 21
- 03-16-2012, 09:45 PM #1
Member
- Join Date
- Mar 2012
- Posts
- 21
- Rep Power
- 0
Java imagemap class gives incosistent instances
I'm trying to implement a sort of imagemap in java over a piano keyboard pic. As the mouse moves the keys hilite when the mouse enters and unhilite as they leave. Can you please help me find why different instances of the same class behave differently in this code? The first button created draws itself and paints itself properly. The second and third button draw and behave correctly behind the scenes according to the debugger, but the painting never happens. Do I need to put these buttons on a different component? I've tried a JPanel instead of a label and no difference. Thanks for your time.
Java Code:package com.mst.buttons; import java.awt.BorderLayout; public class buttonFrame extends JFrame { private JPanel contentPane; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { buttonFrame frame = new buttonFrame(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the frame. */ public buttonFrame() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 578, 373); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); GridBagLayout gbl_contentPane = new GridBagLayout(); gbl_contentPane.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0, 0}; gbl_contentPane.rowHeights = new int[]{0, 0, 0, 0, 0}; gbl_contentPane.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, Double.MIN_VALUE}; gbl_contentPane.rowWeights = new double[]{0.0, 0.0, 0.0, 1.0, Double.MIN_VALUE}; contentPane.setLayout(gbl_contentPane); JLabel piano = new JLabel(""); piano.setLabelFor(piano); piano.setIcon(new ImageIcon("C:\\Users\\Donald\\workspace2\\pianoKeyboard\\src\\com\\musicstandtechnologies\\pianokeyboard\\Keyboard450x220.png")); GridBagConstraints gbc_piano = new GridBagConstraints(); gbc_piano.insets = new Insets(0, 0, 5, 5); gbc_piano.fill = GridBagConstraints.BOTH; gbc_piano.gridx = 2; gbc_piano.gridy = 1; contentPane.add(piano, gbc_piano); //////////////////////////////////////////////// int[] xs1 = new int[] { 0,45,45,0,0 }; int[] ys1 = new int[] { 0,0,220,220,0 }; Polygon p1 = new Polygon(xs1, ys1, xs1.length); String n1 = "C3"; int[] xs2 = new int[] { 45,90,90,45,45 }; int[] ys2 = new int[] { 0,0,220,220,0 }; Polygon p2 = new Polygon(xs2, ys2, xs2.length); String n2 = "D3"; int[] xs3 = new int[] { 90,135,135,90,90 }; int[] ys3 = new int[] { 0,0,220,220,0 }; Polygon p3 = new Polygon(xs3, ys3, xs3.length); String n3 = "D3"; PianoButton pb1 = new PianoButton(p1, n1); piano.add(pb1); PianoButton pb2 = new PianoButton(p2, n2); piano.add(pb2); PianoButton pb3 = new PianoButton(p3, n3); piano.add(pb3); } } class PianoButton extends JComponent implements MouseListener { Polygon key; String noteName; Color color; public PianoButton(Polygon p, String nn) { key = p; noteName = nn; color = Color.white; setBounds(key.getBounds()); addMouseListener(this); } @Override public void mouseClicked(MouseEvent arg0) {} @Override public void mouseEntered(MouseEvent arg0) { hilite(); } @Override public void mouseExited(MouseEvent arg0) { unhilite(); } @Override public void mousePressed(MouseEvent arg0) {} @Override public void mouseReleased(MouseEvent arg0) { turnRed(); repaint(); } void hilite() { System.out.println("Turned yellow"); color = Color.yellow; repaint(); } void turnRed() { System.out.println("Turned Red"); color = Color.red; } void unhilite() { System.out.println("Turned white"); color = Color.white; } public void paintComponent(Graphics g){ Graphics2D g2 = (Graphics2D) g; super.paintComponent(g2); g2.setColor(color); g2.fillPolygon(key); g2.drawPolygon(key); } }
- 03-16-2012, 10:48 PM #2
Re: Java imagemap class gives incosistent instances
The code is missing many import statements that are need to compile it.
- 03-16-2012, 10:56 PM #3
Member
- Join Date
- Mar 2012
- Posts
- 21
- Rep Power
- 0
Button to ClipRect mismatch
In putting a class of subclassed jcomponents onto a jpanel to act as buttons, the proper calls work behind the scenes (the buttons are supposed to hilite as the mouse passes over them and these calls work) but only one button actually paints itself properly on screen.
Now I've found that the clip rect of the other buttons matches the first button and doesn't match their own bounds. How can this be, and how can I fix it? There doesn't seem to be a call to setClipBounds() and this seems like I'm headed down the wrong pathway anyway. Your help is appreciated.
Java Code://////////////////////////////////////////////// int[] xs1 = new int[] { 0,45,45,0,0 }; int[] ys1 = new int[] { 0,0,220,220,0 }; Polygon p1 = new Polygon(xs1, ys1, xs1.length); String n1 = "C3"; int[] xs2 = new int[] { 45,90,90,45,45 }; int[] ys2 = new int[] { 0,0,220,220,0 }; Polygon p2 = new Polygon(xs2, ys2, xs2.length); String n2 = "D3"; int[] xs3 = new int[] { 90,135,135,90,90 }; int[] ys3 = new int[] { 0,0,220,220,0 }; Polygon p3 = new Polygon(xs3, ys3, xs3.length); String n3 = "D3"; PianoButton pb1 = new PianoButton(p1, n1); piano.add(pb1); PianoButton pb2 = new PianoButton(p2, n2); piano.add(pb2); PianoButton pb3 = new PianoButton(p3, n3); piano.add(pb3); } } class PianoButton extends JComponent implements MouseListener { Polygon key; String noteName; Color color; public PianoButton(Polygon p, String nn) { key = p; noteName = nn; color = Color.white; setBounds(key.getBounds()); addMouseListener(this); } @Override public void mouseClicked(MouseEvent arg0) {} @Override public void mouseEntered(MouseEvent arg0) { hilite(); } @Override public void mouseExited(MouseEvent arg0) { unhilite(); } @Override public void mousePressed(MouseEvent arg0) {} @Override public void mouseReleased(MouseEvent arg0) { turnRed(); repaint(); } void hilite() { System.out.println("Turned yellow"); color = Color.yellow; repaint(); } void turnRed() { System.out.println("Turned Red"); color = Color.red; } void unhilite() { System.out.println("Turned white"); color = Color.white; } public void paintComponent(Graphics g){ Graphics2D g2 = (Graphics2D) g; super.paintComponent(g2); g2.setColor(color); g2.fillPolygon(key); g2.drawPolygon(key); } }
- 03-16-2012, 10:58 PM #4
Member
- Join Date
- Mar 2012
- Posts
- 21
- Rep Power
- 0
Re: Java imagemap class gives incosistent instances
Oh. OK. I'll work up a compilable example. I'm new to the forum today.
- 03-16-2012, 11:01 PM #5
Member
- Join Date
- Mar 2012
- Posts
- 21
- Rep Power
- 0
Re: Java imagemap class gives incosistent instances
Wait... the only thing missing from this code is the GUI and the pic. I can't provide those. What you see is the entire test. The code is simple, that's one of the reasons I don't understand why it doesn't work. I'm used to C++ and java is new to me, not programming in general. This is weird. It has something to do with the clipRect I believe but I thought someone more familiar with Java might know something obvious I'm doing wrong and could point it out.
But that's all the code there is... it compiles for me.
- 03-16-2012, 11:02 PM #6
Re: Java imagemap class gives incosistent instances
Post #3 above was merged from the double post. devdon, in future please stick to one thread per topic.
I'm moving this to AWT/Swing. It neither belongs in New to Java nor Advanced Java.
dbWhy do they call it rush hour when nothing moves? - Robin Williams
- 03-16-2012, 11:06 PM #7
Re: Java imagemap class gives incosistent instances
The code you posted will not compile. For example where is the import for the JFrame class?it compiles for me.
I get 36 errors.
- 03-16-2012, 11:14 PM #8
Member
- Join Date
- Mar 2012
- Posts
- 21
- Rep Power
- 0
Re: Java imagemap class gives incosistent instances
Look, I sure don't want to get off on the wrong foot here. This is a one-file program meant to test one thing. It has one JFrame, one contentPane, oneJPanel with an image and the buttons are created by the code. That's it. This is the latest code copy/pasted from eclipse. The file is called "ButtonFrame.java"
Java Code:package com.mst.buttons; import java.awt.BorderLayout; import java.awt.Color; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.Rectangle; import javax.imageio.ImageIO; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import java.awt.GridBagLayout; import javax.swing.JLabel; import java.awt.GridBagConstraints; import javax.swing.ImageIcon; import java.awt.Insets; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; public class buttonFrame extends JFrame { private JPanel contentPane; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { buttonFrame frame = new buttonFrame(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the frame. */ public buttonFrame() { setTitle("Piano"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 578, 373); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); GridBagLayout gbl_contentPane = new GridBagLayout(); gbl_contentPane.columnWidths = new int[]{0, 0}; gbl_contentPane.rowHeights = new int[]{0, 0}; gbl_contentPane.columnWeights = new double[]{1.0, Double.MIN_VALUE}; gbl_contentPane.rowWeights = new double[]{1.0, Double.MIN_VALUE}; contentPane.setLayout(gbl_contentPane); ImagePanel piano = new ImagePanel(); GridBagConstraints gbc_piano = new GridBagConstraints(); gbc_piano.gridy = 0; gbc_piano.gridx = 0; gbc_piano.fill = GridBagConstraints.BOTH; contentPane.add(piano, gbc_piano); piano.setLayout(new BorderLayout(0, 0)); //////////////////////////////////////////////// int[] xs1 = new int[] { 0,45,45,0,0 }; int[] ys1 = new int[] { 0,0,220,220,0 }; Polygon p1 = new Polygon(xs1, ys1, xs1.length); String n1 = "C3"; int[] xs2 = new int[] { 50,90,90,50,50 }; int[] ys2 = new int[] { 0,0,220,220,0 }; Polygon p2 = new Polygon(xs2, ys2, xs2.length); String n2 = "D3"; int[] xs3 = new int[] { 95,135,135,95,95 }; int[] ys3 = new int[] { 0,0,220,220,0 }; Polygon p3 = new Polygon(xs3, ys3, xs3.length); String n3 = "E3"; PianoButton pb1 = new PianoButton(p1, n1); piano.setLayout(null); piano.add(pb1); PianoButton pb2 = new PianoButton(p2, n2); piano.setLayout(null); piano.add(pb2); PianoButton pb3 = new PianoButton(p3, n3); piano.setLayout(null); piano.add(pb3); } } @SuppressWarnings("serial") class PianoButton extends JComponent implements MouseListener { Polygon key; String noteName; Color color; public PianoButton(Polygon p, String nn) { key = p; noteName = nn; color = Color.white; addMouseListener(this); setBounds(key.getBounds()); } @Override public void mouseClicked(MouseEvent arg0) {} @Override public void mouseEntered(MouseEvent arg0) { hilite(); } @Override public void mouseExited(MouseEvent arg0) { unhilite(); } @Override public void mousePressed(MouseEvent arg0) {} @Override public void mouseReleased(MouseEvent arg0) { turnRed(); repaint(); } void hilite() { System.out.println("Turned yellow" + noteName); color = Color.yellow; repaint(); } void turnRed() { System.out.println("Turned Red" + noteName); color = Color.red; repaint(); } void unhilite() { System.out.println("Turned white" + noteName); color = Color.white; repaint(); } public void paintComponent(Graphics g){ Graphics2D g2 = (Graphics2D) g; super.paintComponent(g2); g2.setColor(color); g2.fillPolygon(key); g2.drawPolygon(key); System.out.println(getBounds()); System.out.println(g2.getClipBounds()); } } class ImagePanel extends JPanel{ private BufferedImage image; public ImagePanel() { try { image = ImageIO.read(new File("C:\\Users\\Donald\\workspace2\\pianoKeyboard\\src\\com\\musicstandtechnologies\\pianokeyboard\\Keyboard450x220.png")); } catch (IOException ex) { // handle exception... } } @Override public void paintComponent(Graphics g) { g.drawImage(image, 0, 0, null); // see javadoc for more info on the parameters } }
- 03-16-2012, 11:18 PM #9
- 03-16-2012, 11:24 PM #10
Member
- Join Date
- Mar 2012
- Posts
- 21
- Rep Power
- 0
Re: Java imagemap class gives incosistent instances
Touche.
- 03-16-2012, 11:45 PM #11
Re: Java imagemap class gives incosistent instances
Can you explain what is supposed to happen when the code is executed?
I get a gray window with a white rectangle on the left. When I mouse over the white, it turns yellow.
- 03-17-2012, 12:01 AM #12
Member
- Join Date
- Mar 2012
- Posts
- 21
- Rep Power
- 0
Re: Java imagemap class gives incosistent instances
Yes... The white rectangle is where a picture of a piano keyboard goes. The one yellow rect that shows up (I assume only one showed up) is where the first key is. This is like an imagemap written in java rather than html over a pic of a piano keyboard. So the keys should hilight when the mouse goes over them, as the ONE key does. That part works. The problem is that there are THREE keys there and even though the debugger shows that the graphics paintComponent() routine is being called for the other keys, the actual painting is not being done for them. That's what I can't figure out. They are all instances of the same class.
The difference I've found, and if you run the debugger and click on the button you see, then click directly to the right of that button, too, 45 pixels wide x 2 buttons, you will see in the console a Rectangle output that gives the getBounds() of the key and the getClipBounds() of the graphics object. You will see that they all are set to the clipBounds of the first button. (I just discovered this after posting my question.)
Now the question is whether that is the problem and if so how did it get that way and how to fix it? This seems to be too complicated for a simple mouselistener setup so I must be doing something basically incorrect but I don't know what.
- 03-17-2012, 12:05 AM #13
Re: Java imagemap class gives incosistent instances
What is supposed to show initially?
What is supposed to show as the mouse is moved over the keys? The gray should go to yellow and back to gray as the mouse exits a key.
- 03-17-2012, 12:09 AM #14
Member
- Join Date
- Mar 2012
- Posts
- 21
- Rep Power
- 0
Re: Java imagemap class gives incosistent instances
As the mouse enters it turns yellow. If you click on it, it turns red. As you leave it turns white. I don't know where gray is coming from, maybe your background. In my version this is taking place over white piano keys (ignoring the black ones for the time being.) If you can picture a C, D and E key on a piano keyboard, then those are the three keys that are being represented by the buttons. Yellow hilight, red click, white no activity.
Last edited by devdon; 03-17-2012 at 12:14 AM.
- 03-17-2012, 02:15 AM #15
Re: Java imagemap class gives incosistent instances
There is something very wrong with your layout of the components and usage of the JComponent class. Try changing to extend JPanel and see what happens.
- 03-17-2012, 11:09 AM #16
Re: Java imagemap class gives incosistent instances
Do you think you could get rid of redundant garbage that makes the code difficult to follow?Java Code:piano.setLayout(new BorderLayout(0, 0)); : : piano.setLayout(null); : : piano.setLayout(null); : : piano.setLayout(null); : : piano.setLayout(null);
@Norm: nothing wrong with extending JComponent here.
@devdon: JComponent#paintComponent does nothing, so calling the super implementation doesn't do anything.
I'm late for lunch. I'll take another look after I eat.
dbWhy do they call it rush hour when nothing moves? - Robin Williams
- 03-17-2012, 12:50 PM #17
Re: Java imagemap class gives incosistent instances
I was making a lot of changes got it to work better and thought that the classname was key.
Put these lines at the end of the paintComponent() method for the PianoButton class and look at what is drawn. The light bulb should come shortly
Java Code:g.setColor(Color.BLACK); g.drawLine(0, 20, 40, 20); // This draws as expected <<<<<<<<<,
- 03-17-2012, 01:07 PM #18
Re: Java imagemap class gives incosistent instances
I see what's wrong. This line
in the paintComponent(...) override in PianoButton fills the Polygon in the coordinate space of the PianoButton. That's naturally outside the area of the component, so nothing shows.Java Code:g2.fillPolygon(key);
I understand that in the long run, your Polygons won't be simple rectangles, so it's convenient to stagger them and use their Bounds to determine the Bounds of the PianoButton. One way you can get the desired result with a minimum change in code is by translating the Graphics before filling/drawing the Polygon.If you're sure that getBounds().y will always be zero, you can make that a mite more efficient.Java Code:g2.translate(-key.getBounds().x, -key.getBounds().y);
dbWhy do they call it rush hour when nothing moves? - Robin Williams
- 03-17-2012, 01:18 PM #19
Member
- Join Date
- Mar 2012
- Posts
- 21
- Rep Power
- 0
Re: Java imagemap class gives incosistent instances
That fixed it perfectly! Thank you! I learned a great deal about swing working on this last night but never solved the problem. You've done it in one line of code.
Do you have perhaps a better way of going about this? I'm open to changing my approach. I'm looking for the best way, not simply this way above others. But you've certainly made this way work for me.
- 03-17-2012, 01:49 PM #20
Re: Java imagemap class gives incosistent instances
As in so many programming situations, there's no single 'best' way. For large commercial projects, the 'best' way is usually the most readable, as that leads to maintainability -- and over the lifetime of a software product, maintenance costs are usually much more than initial development and operating costs. For small personal projects (the kind I do), brevity of code fosters a sense of elegance of solution and is satisfying (I love ternaries and regex).
For any performance/processing intensive program, efficiency can become a concern, but only after profiling shows up the bottlenecks. There's no point in shaving nanoseconds off a program that need to run minutes faster.
In your program, one thing I would definitely do differently is using an anonymous inner class extending MouseAdapter for the MouseListener in PianoButton, obviating the need to write all the empty method bodies. The class uses a MouseListener -- it isn't a MouseListener that other classes should use. Favor composition over inheritance.
Then, coming to ImagePanel: empty catch blocks are evil, and drawImage(...) should be called only after checking that the Image is non-null. You could just as easily use a JLabel with an ImageIcon instead, reducing one custom class. JLabel, like all JComponents, inherits from Container so you can add the PianoButtons to it. It has a null layout to begin with, so there you get one more line of code reduced.
Understanding coordinate space is important for aspects other than custom painting, such as computing mouse coordinates from MouseEvents. What you've learned today will help you code up other stuff without making the same mistake.
dbWhy do they call it rush hour when nothing moves? - Robin Williams
Similar Threads
-
Error initializing class instances
By fr0s1yjack in forum New To JavaReplies: 1Last Post: 06-22-2011, 03:58 PM -
Drawing multiple instances of one class with an array
By Grimmjow in forum New To JavaReplies: 16Last Post: 05-22-2010, 03:51 AM -
approx. 1000 instances of class?
By artemff in forum CLDC and MIDPReplies: 0Last Post: 01-01-2010, 07:57 PM -
Class Instances stored in an ArrayList
By Ersk in forum New To JavaReplies: 4Last Post: 12-12-2009, 04:13 PM -
Problem with class instances
By sdwinder in forum New To JavaReplies: 7Last Post: 10-21-2009, 01:25 AM


1Likes
LinkBack URL
About LinkBacks
Reply With Quote

Bookmarks