الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

رسم ساعة باستعمال Java2D

بدأه herch في 22 فبراير 2010 · 6 رد · 1,426 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

هذا مثال على ما يمكن القيام به باستعمال Java2D، وهو ساعة بسيطة، النتيجة هي على هذا الشكل

post-181903-12668012675133_thumb.png

هذه هي الفئة الرئيسية التي يتم فيها الرسم

package clock;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.Calendar;
import javax.swing.JPanel;
import javax.swing.Timer;

public class ClockPanel extends JPanel implements ActionListener {

	private final int WIDTH = 200, HEIGHT = 200, ANGLE_INCREMENT_HOUR = 30,
			ANGLE_INCREMENT_MINUTE = 6, ANGLE_INCREMENT_SECOND = 6, 
			RADIUS = 80, X_CENTER = WIDTH/2, Y_CENTER = HEIGHT/2,
			RADIUS_HOUR = 40, RADIUS_MINUTE = 60, RADIUS_SECOND = 60;
	private Timer timer;
	private Line2D hourLine, minuteLine, secondLine;
	private BufferedImage bgImage;

	public ClockPanel() {
		timer = new Timer(1000, this);
		hourLine = new Line2D.Float(X_CENTER, Y_CENTER, 0, 0);
		minuteLine = new Line2D.Float(X_CENTER, Y_CENTER, 0, 0);
		secondLine = new Line2D.Float(X_CENTER, Y_CENTER, 0, 0);
		setPreferredSize(new Dimension(WIDTH, HEIGHT));
		timer.start();
	}

	public void actionPerformed(ActionEvent e) {
		repaint();
	}

	@Override
	protected void paintComponent(Graphics g) {
		Graphics2D g2 = (Graphics2D)g;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		if (bgImage == null) {
			bgImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
			Graphics2D gImage = bgImage.createGraphics();
			gImage.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			paintClockBackground(gImage);
			paintClockBorder(gImage);
			paintClockMarks(gImage);
		}
		g.drawImage(bgImage, 0, 0, this);
		paintClockPointers(g);
		paintDigitalClock(g);
	}

	private void paintClockMarks(Graphics g) {
		g.setColor(Color.RED);
		for (int i = 0; i < 60; i++) {
			double angle = Math.toRadians(i * ANGLE_INCREMENT_SECOND);
			int x = (int)(X_CENTER + (RADIUS - 3) * Math.cos(angle));
			int y = (int)(Y_CENTER + (RADIUS - 3) * Math.sin(angle));
			if (i % 5 == 0){
				g.fillOval(x, y, 2, 2);
			} else {
				g.fillOval(x, y, 1, 1);
			}
		}
	}

	private void paintClockPointers(Graphics g) {
		Graphics2D g2 = (Graphics2D)g;
		g2.setColor(Color.RED);
		Calendar now = Calendar.getInstance();
		//paint hour pointer
		int hour = now.get(Calendar.HOUR);
		double angleHour = Math.toRadians(hour * ANGLE_INCREMENT_HOUR);
		int xHour = (int)(X_CENTER + RADIUS_HOUR * Math.cos(angleHour - 1.5708));	//1.5708 radian = 90 degree
		int yHour = (int)(Y_CENTER + RADIUS_HOUR * Math.sin(angleHour - 1.5708));
		hourLine.setLine(X_CENTER, Y_CENTER, xHour, yHour);
		g2.setStroke(new BasicStroke(6f, BasicStroke.JOIN_MITER, BasicStroke.CAP_ROUND));
		g2.draw(hourLine);
		//paint minute pointer
		int minute = now.get(Calendar.MINUTE);
		double angleMinute = Math.toRadians(minute * ANGLE_INCREMENT_MINUTE);
		int xMinute = (int)(X_CENTER + RADIUS_MINUTE * Math.cos(angleMinute - 1.5708));
		int yMinute = (int)(Y_CENTER + RADIUS_MINUTE * Math.sin(angleMinute - 1.5708));
		minuteLine.setLine(X_CENTER, Y_CENTER, xMinute, yMinute);
		g2.setStroke(new BasicStroke(3f, BasicStroke.JOIN_MITER, BasicStroke.CAP_ROUND));
		g2.draw(minuteLine);
		//paint second pointer
		int second = now.get(Calendar.SECOND);
		double angleSecond = Math.toRadians(second * ANGLE_INCREMENT_SECOND);
		int xSecond = (int)(X_CENTER + RADIUS_SECOND * Math.cos(angleSecond - 1.5708));
		int ySecond = (int)(Y_CENTER + RADIUS_SECOND * Math.sin(angleSecond - 1.5708));
		secondLine.setLine(X_CENTER, Y_CENTER, xSecond, ySecond);
		g2.setStroke(new BasicStroke());
		g2.draw(secondLine);
	}

	private void paintClockBackground(Graphics g) {
		Graphics2D g2 = (Graphics2D)g;
		RadialGradientPaint gradient = new RadialGradientPaint(X_CENTER - 30, Y_CENTER - 30, RADIUS,
				new float[]{0.0f, 1.0f}, new Color[]{Color.decode("0x4E65AF"), Color.decode("0x0000")});
		g2.setPaint(gradient);
		g2.setStroke(new BasicStroke(10.0f));
		g2.fillOval(20, 20, RADIUS*2, RADIUS*2);
	}

	private void paintClockBorder(Graphics g) {
		GradientPaint gradient = new GradientPaint(0, 0, Color.decode("0x4E65AF"), WIDTH, HEIGHT, Color.decode("0x1D316A"));
		Graphics2D g2 = (Graphics2D)g;
		g2.setPaint(gradient);
		g2.setStroke(new BasicStroke(5.0f));
		g2.drawOval(18, 18, RADIUS*2 + 2, RADIUS*2 + 2);
	}

	private void paintDigitalClock(Graphics g) {
		Graphics2D g2 = (Graphics2D)g;
		g2.setColor(Color.WHITE);
		Calendar now = Calendar.getInstance();
		int hour = now.get(Calendar.HOUR);
		int minute = now.get(Calendar.MINUTE);
		int second = now.get(Calendar.SECOND);
		String strTime = (hour<10 ? "0"+ hour : hour) + ":" + (minute<10 ? "0"+ minute : minute) + ":" + (second<10 ? "0"+ second : second);
		int widthString = g.getFontMetrics().stringWidth(strTime);
		g.drawString(strTime, X_CENTER - widthString/2, Y_CENTER + RADIUS/2);
	}
}

المشروع في المرفقات

Clock.zip

1
#2

عصام

لاحظت وجود RenderingHints أكثر من مرة

ما فائدته؟

ولاحظت أنك استخدمت ألوان مخصصة عن طريق Color.decode

عن نفسي فأنا سيء في اختيار الألوان

فهل هناك من يساعد في اختيار الألوان :(

أخيراً هذا المقطع من الشيفرة يمثل عملية رسم العقارب

هلا شرحته بالتفصيل :lol:

                double angleHour = Math.toRadians(hour * ANGLE_INCREMENT_HOUR);
                int xHour = (int)(X_CENTER + RADIUS_HOUR * Math.cos(angleHour - 1.5708));       //1.5708 radian = 90 degree
                int yHour = (int)(Y_CENTER + RADIUS_HOUR * Math.sin(angleHour - 1.5708));
                hourLine.setLine(X_CENTER, Y_CENTER, xHour, yHour);

تحياتي

1
حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#3

RenderingHints تسمح بتحديد قيم بعض خصائص الرسم. استعملت في المثال الخاصية KEY_ANTIALIASING وأعطيتها القيمة VALUE_ANTIALIAS_ON، والخاصية KEY_TEXT_ANTIALIASING اعطيتها القيمة VALUE_TEXT_ANTIALIAS_ON. الهدف هو تفعيل ال Antialiasing بالنسبة للأشكال والحروف، وهو يسمح بإزالة التكسرات التي تظهر

لاحظ الرسم التالي بدون تفعيل ال ANTIALIASING. لاحظ التكسرات.

post-181903-1266836185243_thumb.png

عند تفعيل ال ANTIALIASING. تختفي التكسرات

post-181903-12668362252784_thumb.png

-------------------------------------

استعملت Color.decode لأنني كنت أختار الألوان من بريمج يمكنني من اختيار الألوان ويعطيني قيمتها بال hexadecimal، والطريقة decode تقبل أن تمرر لها قيمة اللون بال hexadeciamle.

لا توجد ألوان كثيرة، فقط لونين استعملتهما في ال gradient

--------------------------------------------

double angleHour = Math.toRadians(hour * ANGLE_INCREMENT_HOUR);

المتغير angleHour يمثل الزاوية التي سيدور بها عقرب الساعة انطلاقا من الساعة 12.

ANGLE_INCREMENT_HOUR يساوي 30، وهي الزاوية التي تفصل بين كل ساعة. الساعة اليدوية يكون مرسوما فيها 12 ساعة، والدائرة فيها 360 درجة، والساعة اليدوية هي عبارة عن دائرة --> 360 ÷ 12 = 30.

hour هي الساعة، وهي تبتدأ من 0 إلى 11، حيث 0 تمثل الساعة الثانية عشر. إذن عندما تكون الساعة الثانية عشر، أي 0، فإن زاوية الدوران هي 0 * 30 = 0، في الساعة الواحدة، زاوية الدوران هي 1 * 30 = 30، في الساعة الثانية، زاوية الدوران هي 2 * 30 = 60 وهكذا...

 	int xHour = (int)(X_CENTER + RADIUS_HOUR * Math.cos(angleHour - 1.5708)); 	//1.5708 radian = 90 degree
 	int yHour = (int)(Y_CENTER + RADIUS_HOUR * Math.sin(angleHour - 1.5708));

عقرب الساعة ما هو إلا خط، أي أننا يجب أن نعرف إحداثيات نقطة البداية ونقطة النهاية حتى نتمكن من رسمه. نقطة البداية معروفة، وهي مركز الدائرة (X_CENTER, Y_CENTER)، بالنسبة لنقطة النهاية، فهي توجد في الدائرة التي يرسمها العقرب عند دورانه، وبالتالي نستعمل معادلة الدائرة لإيجاد نقطة ما

معادلة الدائرة، حيث a,b تمثل مركز الدائرة، r الشعاع، و t الزاوية، أي angleHour

post-181903-12668375719806_thumb.png

post-181903-12668375818584_thumb.png

post-181903-12668373607819_thumb.png

لم أكن أبدا جيدا في الرياضيات، لذلك لا تنتظر مني شرحا جيدا :D. إذا فهم أحد ماذا أعني فليشرحه بطريقة أفضل.

تم تعديل هذه المشاركة بواسطة herch في 22 فبراير 2010 في 14:29

1
#4

قمت بإضافة بعض التعديلات. الآن الساعة تظهر بهذا الشكل

post-181903-12668520646366_thumb.png

Clock.jar

Clock_project.zip

#5

جميل جداً أخ عصام !

هذه معلومة أبحث عنها منذ زمن :

        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
#6

من الجيد أن الموضوع كان ذا فائدة :)

#7

هل تصدق أني استخدمتها من قبل

أظن في حزمة Achart على ما أذكر

كان لدي الرسم البياني الدائري وكانت هذه التكسرات تجعل المنظر سيئ جداً

بالمناسبة هذا ما يعرف بالإحداثيات القطبية على ما أذكر

لو أن الأخ الشمري هنا لكان أفادنا كنت قرأت له موضوعاً أكثر من رائع

بالمناسبة أنا أيضاً لا أجد في الرياضيات هواي

مع أني كنت في الماضي أعشقها

على كل تسلم يا عم عصام ونزورك في الأفراح يا باشا

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

مواضيع مشابهة