JComponent not displaying text - Swing is pwning me!
I'm a High School AP Computer Science student doing an independent study project in Java. I have chosen to write an application for beginning piano students in which the computer displays a picture of the keyboard with a note highlighted. The user then selects the name of the note that correspond开发者_开发问答s to the highlighted key, with a timer that counts to zero and then reports the user's score.
My view is almost finished, but I am having trouble displaying my timer on the screen.
The timer is created by the model and runs in a separate thread, every second instructing the controller to update the timer, which calls a method in view, which in turn sets a value in the object TimerUpdateComponent and then validates to display the new text.
At least, that's the theory. The timer works perfectly - prints to the console every second, just like I asked - but when I run the view, nothing appears. So, thinking I would do what the master does and figure out the difference, I copied this code directly from Horstmann and Cornell's [I]Core Java - Volume I[/I], which should display the string "Hello, World!" in the center of the panel:
public void paintComponent(Graphics g){<br>
Graphics2D g2 = (Graphics2D) g;<br>
String message = "Hello, World!";<br>
Font f = new Font("Serif",Font.BOLD,36);<br>
g2.setFont(f);
//measure the size of the message
FontRenderContext context = g2.getFontRenderContext();
Rectangle2D bounds = f.getStringBounds(message, context);
//set (x,y) to top-left corner of text
double x = (getWidth() - bounds.getWidth())/2;
double y = (getHeight() - bounds.getHeight())/2;
//add ascent to y to reach the baseline
double ascent = -bounds.getY();
double baseY = y + ascent;
//draw the message
g2.drawString(message, (int)x, (int)y);
g2.setPaint(Color.LIGHT_GRAY);
//draw the baseline
g2.draw(new Line2D.Double(x, baseY,x - bounds.getWidth(), baseY));
//draw the enclosing rectangle
Rectangle2D rect = new Rectangle2D.Double(x,y,bounds.getWidth(), bounds.getHeight());
g2.draw(rect);
}
}
To my astonishment, this code didn't display the string either! I thought the string might have been too big for the rather small panel, so it was only showing the white space, but I tried changing the type size to 10, and that didn't work either.
So now I'm really :chomp: ing. The only thing I can think of is that the book is out of date (Did Sun change the way Swing works since 2008? I doubt it.) or made an egregious coding error (in its eighth edition?) So I created a separate file and copied the entire .java file from the book, and it worked just fine.
Please help me!
Also, here's my original method body in case you want to look at that:
String message = time/60+":"+time%60;<br>
Graphics2D g2 = (Graphics2D) g;<br>
FontRenderContext context = g2.getFontRenderContext();<br>
Rectangle2D bounds = g2.getFont().getStringBounds(message, context);<br>
double x = (getWidth() - bounds.getWidth()) / 2;<br>
double y = (getHeight() - bounds.getHeight() / 2);<br>
g2.drawString(message,(int)x,(int)y);<br>
After the first repaint you're painting gray text on a gray background.
But why not just use a JLabel and call setText every time the timer fires, rather doing all this yourself?
The key phrase is
the timer runs on a separate thread.
You can only update a Swing GUI from the Event Dispatch Thread, the one that works the GUI.
The solution is to run your update code using SwingUtilities.invokeLater()
.
You should probably set the paint of the text before drawing the text. Also make sure to call repaint on the component on each update using SwingUtilities.invokeLater()
精彩评论