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(); } }
参考资料: