Java GUI组件练习用Demo,主要是为了学习GUI的设计思路、组件的特性。这里的代码并不是最优雅的解决方案,千万别纠结这个……
要点:
- 绘图的框架应该继承自JFrame,具体组件继承自JPanel。
- 继承自JPanel的类覆写父类(JComponent)的paintComponent()方法,注意不是Container的paintComponents()!
- 这些都是不能重用的组件,所以要刷新则调用repaint(),此处在每次调用setter方法的时候进行调用。
- 通过时分秒计算时针、分针、秒针的位置需要用三角函数的知识。
- 在计算时针和分针角度时,秒数对其影响太小(为second/3600),故此处为方便忽略不算。
效果图:黄线只是为了调整时钟数字摆放的位置,展示的代码中已经删去。
用于显示GUI的类,继承了JFrame,引用了两个继承自JPanel的类(分别用作绘画时钟和显示具体时间)。
package thinkwise.gui.graphics.practice;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;
public class DisplayClock extends JFrame {
private StillClock clock = new StillClock();
public DisplayClock() {
final MessagePanel p = new MessagePanel(clock.getHour() + ":" + clock.getMinute() + ":" + clock.getSecond());
p.setCentered(true);
p.setFont(new Font("Courier", Font.BOLD, 16));
p.setForeground(Color.blue);
add(clock);
add(p, BorderLayout.SOUTH);
Timer timer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
clock.setCurrentTime();
clock.repaint();
p.setMessage(clock.getHour() + ":" + clock.getMinute() + ":" + clock.getSecond());
p.repaint();
}
});
timer.start();
}
public static void main(String[] args) {
DisplayClock c = new DisplayClock();
c.setTitle("Clock");
c.setSize(300, 350);
c.setVisible(true);
c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
c.setLocationRelativeTo(null);
}
}
时钟类
package thinkwise.gui.graphics.practice;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.swing.JPanel;
public class StillClock extends JPanel {
private int hour;
private int minute;
private int second;
public StillClock() {
setCurrentTime();
}
public StillClock(int hour, int minute, int second){
this.hour = hour;
this.minute = minute;
this.second = second;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int xCenter = getWidth()/2;
int yCenter = getHeight()/2;
int clockRadius = (int) (Math.min(getWidth(), getHeight()) * 0.8 * 0.5);
g.setColor(Color.black);
g.drawOval(xCenter - clockRadius, yCenter - clockRadius, 2 * clockRadius, 2 * clockRadius);
g.drawString("12", xCenter - 5, yCenter - clockRadius + 12);
g.drawString("3", xCenter + clockRadius - 10, yCenter + 3);
g.drawString("6", xCenter - 3, yCenter + clockRadius - 3);
g.drawString("9", xCenter - clockRadius + 3, yCenter + 3);
int sLength = (int) (clockRadius * 0.8);
int xSecnd = (int) (xCenter + sLength * Math.sin(2 * Math.PI/60 * second));
int ySecond = (int) (yCenter - sLength * Math.cos(2 * Math.PI/60 * second));
g.setColor(Color.RED);
g.drawLine(xCenter, yCenter, xSecnd, ySecond);
int mLength = (int) (clockRadius * 0.65);
int xMinute = (int) (xCenter + mLength * Math.sin((minute + second/60) * 2 * Math.PI/60));
int yMinute = (int) (yCenter - mLength * Math.cos((minute + second/60) * (2 * Math.PI/60)));
g.setColor(Color.blue);
g.drawLine(xCenter, yCenter, xMinute, yMinute);
int hLength = (int) (clockRadius * 0.5);
int xHour = (int) (xCenter + hLength * Math.sin((hour % 12 + minute/60) * (2 * Math.PI/12)));
int yHour = (int) (yCenter - hLength * Math.cos((hour % 12 + minute/60) * (2 * Math.PI/12)));
g.setColor(Color.green);
g.drawLine(xCenter, yCenter, xHour, yHour);
}
public void setCurrentTime(){
Calendar calendar = new GregorianCalendar();
this.hour = calendar.get(Calendar.HOUR_OF_DAY);
this.minute = calendar.get(Calendar.MINUTE);
this.second = calendar.get(Calendar.SECOND);
}
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = hour;
repaint();
}
public int getMinute() {
return minute;
}
public void setMinute(int minute) {
this.minute = minute;
repaint();
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
repaint();
}
}
时间文本显示:
package thinkwise.gui.graphics.practice;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.swing.JPanel;
public class MessagePanel extends JPanel {
private String message = "Welcome to Java";
private int xCoordinate = 20;
private int yCoordinate = 20;
private boolean centered;
private int interval = 10;
public MessagePanel() {
}
public MessagePanel(String message){
this.message = message;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(centered){
FontMetrics fm = g.getFontMetrics();
int stringWidth = fm.stringWidth(message);
int stringAscent = fm.getAscent();
xCoordinate = getWidth()/2 - stringWidth/2;
yCoordinate = getHeight()/2 + stringAscent/2;
}
g.drawString(message, xCoordinate, yCoordinate);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 30);
}
public void moveLeft(){
xCoordinate -= interval;
repaint();
}
public void moveRight(){
xCoordinate += interval;
repaint();
}
public void moveUp(){
yCoordinate += interval;
repaint();
}
public void moveDown(){
yCoordinate -= interval;
repaint();
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
repaint();
}
public int getxCoordinate() {
return xCoordinate;
}
public void setxCoordinate(int xCoordinate) {
this.xCoordinate = xCoordinate;
repaint();
}
public int getyCoordinate() {
return yCoordinate;
}
public void setyCoordinate(int yCoordinate) {
this.yCoordinate = yCoordinate;
repaint();
}
public boolean isCentered() {
return centered;
}
public void setCentered(boolean centered) {
this.centered = centered;
repaint();
}
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
repaint();
}
}
参考资料: