Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.54/121: Рейтинг темы: голосов - 121, средняя оценка - 4.54
2 / 2 / 0
Регистрация: 20.04.2011
Сообщений: 6
1

Аналоговые часы

06.05.2011, 21:43. Показов 25289. Ответов 12
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Что было сделано:
-нарисованы все стрелки, сам круг.
-Все стрелки двигаются.

Что хочу спросить:
-можно ли как-то нанести на круг циферблата "деления-штрихи", дабы хоть как-нибудь обозначить время.

Читаем системное время, получаем который час.
C#
1
int.Parse(System.DateTime.Now.ToString("HH:mm:ss").Split(':')[0]);
Теперь главный вопрос: КАК присобачить полученный час, так же минуту (текущего настоящего времени) к начальным координатам стрелок при запуске программы. другими словами, сейчас минутная и часовая стрелка стоят на 3ке. а хочу, чтоб становились соответсвенно времени.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace WindowsFormsApplication4
{
    public partial class Form1 : Form
    {
        const float x0 = 200;
        const float y0 = 200;
        int ticks = 0;
 
        float alfa =(float)Math.PI*3/2; //начально положение секундной стрелки будет на 0
        float beta;//относится к минутам
        float delta = 0; //к часам. 
///вот нули дельты и беты соответствуют нулям на координатном круге. вот и стоят мои стрелки на 3х часах.
        public Form1()
        {
            InitializeComponent();
        }
///попробовал сделать метод, который возвращал бы бету хотя бы для 9 вечера. не работает.
        public static float betachka(int hour)
        {
 
            if (hour == 21)
            {
                float beta = (float)Math.PI*3/2;
                return (float)beta;
            }
            else return 0;
        }
        private void panel1_Paint(object sender, PaintEventArgs e)
        {
///длины стрелок
            float rs = 80;
            float rm = 60;
            float rh = 45;
 
            float xs; float xm; float xh;
            float ys; float ym; float yh;
 
            xs = x0 + rs * (float)Math.Cos(alfa);
            ys = y0 + rs * (float)Math.Sin(alfa);
 
            xm = (x0) + rm * (float)Math.Cos(beta);
            ym = y0 + rm * (float)Math.Sin(beta);
            
            xh = x0 + rh * (float)Math.Cos(delta);
            yh = y0 + rh * (float)Math.Sin(delta);
 
            Graphics gr01 = e.Graphics;
 
            Pen p01 = new Pen(Color.Black, 4);
 
            Pen p02 = new Pen(Color.Red, 2);
            Pen p03 = new Pen(Color.Blue, 3);
            Pen p04 = new Pen(Color.Purple, 4);
///рисуем
            gr01.DrawEllipse(p01, x0 - 100, x0 - 100, 200, 200);
            gr01.DrawLine(p02, (x0), y0, xs, ys);
            gr01.DrawLine(p03, (x0), y0, xm, ym);
            gr01.DrawLine(p04, x0, y0, xh, yh);
        }
 
        private void timer1_Tick(object sender, EventArgs e)
        {
            ticks += 1;
            if (ticks == 60)
            {
                alfa = (float)Math.PI*3/2;
            }
            alfa += (float)0.104719;//угол 6 градусов в радианах
            
           
            if (ticks == 3600)
            {
                beta = betachka(21);
            }
            beta += (float)0.00174527; //угол 0,1 градус в радианах. столько проходит минутная стрелка за 1 сек
 
            if (ticks == 216000)
            {
                delta = int.Parse(System.DateTime.Now.ToString("HH:mm:ss").Split(':')[0]); ;
            }
            delta += (float)0.0000290886; //соответственно такой угол в радианах проходит часовая стрелка за 1 сек
            panel1.Invalidate();
        }
 
      
 
        }
   
    }
2
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.05.2011, 21:43
Ответы с готовыми решениями:

Аналоговые часы
Дорогие друзья! Большая просьба, пожалуйста помогите сделать аналоговые часы в приложении....

Аналоговые часы (24-часовой циферблат)
Ребят,здравствуйте. У меня тут небольшая проблема с программированием на с# Как сделать...

Таймер или аналоговые часы
Есть ли у кого нибудь исходники таймер или аналоговых часов(со стрелками)

Аналоговые часы
читаю вот эти статьи, хочу попробовать написать аналоговые часы, не знаю как описать с помощью XAML...

12
мастер топоров
916 / 741 / 101
Регистрация: 16.08.2009
Сообщений: 1,476
06.05.2011, 22:53 2
в обработчик события первой загрузки формочки прописать метод, который рисует стрелки с аргументом текущего времени
1
2 / 2 / 0
Регистрация: 20.04.2011
Сообщений: 6
06.05.2011, 23:03  [ТС] 3
Простите, но я не совсем понял, что Вы имели ввиду.
Точнее, понять то я понял. а вот как сделать...)
0
мастер топоров
916 / 741 / 101
Регистрация: 16.08.2009
Сообщений: 1,476
07.05.2011, 01:59 4
Лучший ответ Сообщение было отмечено как решение

Решение

может не особо красиво, но работает
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
using System;
using System.Windows.Forms;
using System.Drawing;
 
namespace TempWinFormProject {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
            timerTime = new Timer();
            timerTime.Tick += new EventHandler(timerTime_Tick);
            timerTime.Interval = 1000;
            timerTime.Enabled = true;
            g = this.CreateGraphics();
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        }
 
        //величина, изменение которой масштабирует размер самих часов
        double Lenght = 120;
        Graphics g;
        Timer timerTime;
        //цвет фона часов
        Color bkColor = Control.DefaultBackColor;
        //обновление-рисовка фона за часам
        private void PaintBackGround() {
            g.FillRectangle(
                new SolidBrush(bkColor),
                new Rectangle(
                    new Point(
                        (int)(this.ClientRectangle.Width / 2 - Lenght),
                        (int)(this.ClientRectangle.Height / 2 - Lenght)),
                        new Size((int)Lenght * 2, (int)Lenght * 2)));
        }
        //просовка циферблата
        private void PaintCircle() {
            //прорисовка внешней окружности
            g.DrawEllipse(
                new Pen(
                    new SolidBrush(Color.Black),
                    2),
                new Rectangle(
                    new Point(
                        (int)(this.ClientRectangle.Width / 2 - Lenght),
                        (int)(this.ClientRectangle.Height / 2 - Lenght)),
                        new Size((int)Lenght * 2, (int)Lenght * 2)));
            //прорисовка линий, который указывают на деления часов
            for (int i = 0; i < 12; i++) {
                g.DrawLine(new Pen(new SolidBrush(Color.Black), 1),
                    new Point((int)(ClientRectangle.Width / 2), (int)(ClientRectangle.Height / 2)),
                    new Point((int)(ClientRectangle.Width / 2 + Lenght * Math.Cos(Math.PI / 6 * i)), (int)(ClientRectangle.Height / 2 + Lenght * Math.Sin(Math.PI / 6 * i))));
            }
            //прорисовка круга, который закрывает внутреннюю часть линий чтобы остались только черточки
            //этот круг меньше диаметром внешней окружности
            g.FillEllipse(
                new SolidBrush(bkColor),
                new Rectangle(
                    new Point(
                        (int)(this.ClientRectangle.Width / 2 - Lenght + 10),
                        (int)(this.ClientRectangle.Height / 2 - Lenght + 10)),
                        new Size((int)(Lenght - 10) * 2, (int)(Lenght - 10) * 2)));
 
        }
        //прорисовка стрелок часов
        private void PaintArrows(DateTime dt) {
            //прорисовка секундной стрелки
            g.DrawLine(
                new Pen(new SolidBrush(Color.Black), 1),
                new Point((int)(ClientRectangle.Width / 2), (int)(ClientRectangle.Height / 2)),
                new Point((int)(ClientRectangle.Width / 2 + (Lenght - 4) * Math.Sin(2 * Math.PI / 60 * dt.Second)), (int)(ClientRectangle.Height / 2 - (Lenght - 4) * Math.Cos(2 * Math.PI / 60 * dt.Second))));
            //прорисовка минутной стрелки
            g.DrawLine(
                new Pen(new SolidBrush(Color.Black), 2),
                new Point((int)(ClientRectangle.Width / 2), (int)(ClientRectangle.Height / 2)),
                new Point((int)(ClientRectangle.Width / 2 + (Lenght - 4) * Math.Sin(2 * Math.PI / 60 * dt.Minute)), (int)(ClientRectangle.Height / 2 - (Lenght - 4) * Math.Cos(2 * Math.PI / 60 * dt.Minute))));
            //определения количества часов, прошедших после полудня или после полуночи
            //фактически перевод 23=>11 и так далее
            int hour;
            if (dt.Hour <= 12) {
                hour = dt.Hour;
            } else {
                hour = dt.Hour - 12;
            }
            //прорисовка часовой стрелки
            g.DrawLine(
                new Pen(new SolidBrush(Color.Black), 2),
                new Point((int)(ClientRectangle.Width / 2), (int)(ClientRectangle.Height / 2)),
                new Point((int)(ClientRectangle.Width / 2 + (Lenght - 10) * Math.Sin(2 * Math.PI / 12 * hour + 2 * Math.PI / (12 * 60) * dt.Minute)), (int)(ClientRectangle.Height / 2 - (Lenght - 10) * Math.Cos(2 * Math.PI / 12 * hour + 2 * Math.PI / (12 * 60) * dt.Minute))));
        }
        //общая прорисовка часов
        private void PaintClock(DateTime dtArg) {
            //фон
            PaintBackGround();
            //циферблат
            PaintCircle();
            //стрелки
            PaintArrows(dtArg);
        }
        //"тик" таймера
        private void timerTime_Tick(object sender, EventArgs e) {
            PaintClock(DateTime.Now);
        }
        //первая загрузка формы
        private void Form1_Shown(object sender, EventArgs e) {
            PaintClock(DateTime.Now);
        }
    }
}

то есть вам нужно не приплюсовывать единичку при каждом тике таймера и от этого числа отталкиваться чтобы рисовать положение стрелок, а отталкиваться нужно от текущего времени
я в метод, который отрисовывает стрелки передаю значение текущего времени и от него отталкиваюсь при прорисовке
я не говорю что ваш метод нерабочий, он рабочий, но немного неудачный подход к задаче
3
10 / 10 / 1
Регистрация: 02.04.2011
Сообщений: 95
07.05.2011, 13:59 5
Если не критично - используй wpf , там можно вообще без кода подобное приложение сделать.
0
2 / 2 / 0
Регистрация: 20.04.2011
Сообщений: 6
07.05.2011, 18:14  [ТС] 6
Большое спасибо, разобрался
0
4 / 4 / 0
Регистрация: 08.03.2011
Сообщений: 42
01.08.2013, 07:13 7
Пишу похожую программу велосипед.
Рисую в pictureBox, стрелка рисуется по таймеру. Проблема в мерцании картинки при обновлении рисуемой области - pictureBox1.Invalidate(). Можно ли это исправить ? Может лучше перемещать стрелку (вот только как) ?

Добавлено через 17 минут
хм...сделал два таймера, один для отрисовки, второй для обновления - почти идеально)
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Init();
        }
 
        int i;
        Pen gPen = new Pen(Color.Black, 1);
        Graphics gPanel;
        Timer timer = new Timer();
        Timer timer2 = new Timer();
        double radian;
        double gradus;
        float radian2, x1,y1;
        double x, y;
 
        void Init()
        {
            gPanel = pictureBox1.CreateGraphics();
            timer.Interval = 1;
            timer2.Interval = 10;
            timer.Tick += new EventHandler(timer_Tick);
            timer2.Tick += new EventHandler(timer2_Tick);
            i = 0;;
        }
 
        private void timer_Tick(object sender, EventArgs e)
        {
            Run();
        }
 
        private void timer2_Tick(object sender, EventArgs e)
        {
            pictureBox1.Refresh();
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
            timer.Start();
            timer2.Start();
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
        }
 
        void Run()
        {
            i++;
            gradus = i;
            radian = gradus * Math.PI / 180;
            radian2 = (float)radian;
            x = 300 - (150 * (1 - Math.Sin(radian)));
            y = (150 * (1 - Math.Cos(radian)));
            x1 = (float)x;
            y1 = (float)y;
            listBox1.Items.Add("x1 " + x1);
            listBox2.Items.Add("y1 " + y1);
            gPanel.DrawEllipse(gPen, 0, 0, 300, 300);
            gPanel.DrawLine(gPen, 150, 150, x1, y1);
        }
    }
0
86 / 86 / 6
Регистрация: 14.01.2011
Сообщений: 265
01.08.2013, 07:21 8
Цитата Сообщение от MadMarik Посмотреть сообщение
Проблема в мерцании картинки при обновлении рисуемой области
Можно попробовать включить двойную буферизацию чтоб не было мерцания:
C++
1
Form1->DoubleBuffered = true;
1
4 / 4 / 0
Регистрация: 08.03.2011
Сообщений: 42
01.08.2013, 07:36 9
Включил в свойствах формы. Не помогло.
0
4 / 4 / 0
Регистрация: 08.03.2011
Сообщений: 42
06.08.2013, 09:00 10
И такс, стрелка двигается. Теперь вопрос как ускорить движение ?
Есть два таймера, один выполняет метод Draw
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
        
void Draw()
        {
            gradus ++;
            radian = gradus * Math.PI / 180;
            x = 300 - (150 * (1 - Math.Sin(radian)));
            y = (150 * (1 - Math.Cos(radian)));
            x1 = (float)x;
            y1 = (float)y;
            gPanel.DrawLine(gPen, 150, 150, x1, y1);
            gPanel.DrawEllipse(gPen2, 0, 0, 300, 300);
        }

второй выполняет обновление рисуемой области
C#
1
pictureBox1.Refresh();
Если использовать один таймер, то стрелка мерцает. Пробовал рассчитать координаты при запуске формы(записать в листбокс, а потом с него считывать), чтобы при рисовании их не рассчитывать, не помогло. DrawLine медленный ? Как ускорить движение стрелки ?
0
86 / 86 / 6
Регистрация: 14.01.2011
Сообщений: 265
08.08.2013, 11:23 11
Цитата Сообщение от MadMarik Посмотреть сообщение
Если использовать один таймер, то стрелка мерцает.
Поработал с вашим кодом маленько:
Во первых убрал метод Refresh со второго таймера! Не надо перерисовывать весь компонент. Достаточно закрашивать те области, которые проходила стрелка. Таким образом функция Run стала следующей:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        void Run()
        {
            i++;
            gradus = i;
            radian = gradus * Math.PI / 180;
            radian2 = (float)radian;
            gPen = new Pen(SystemColors.Control, 1);//настраиваем цвет заливки под цвет компонента
            gPanel.DrawLine(gPen, 150, 150, x1, y1);//закрашиваем предыдущую отрисовку стрелки цветом компонента
            x = 300 - (150 * (1 - Math.Sin(radian)));
            y = (150 * (1 - Math.Cos(radian)));
            x1 = (float)x;
            y1 = (float)y;
            listBox1.Items.Add("x1 " + x1);
            listBox2.Items.Add("y1 " + y1);
            gPen = new Pen(Color.Black, 1);
            gPanel.DrawLine(gPen, 150, 150, x1, y1);
        }
Ну и рисовать окружность нужно только один раз соответственно. Добавил ее рисование на кнопку:
C#
1
2
3
4
5
6
7
8
        private void button1_Click_1(object sender, EventArgs e)
        {
            gPen = new Pen(Color.Black, 1);
            gPanel.DrawEllipse(gPen, 0, 0, 300, 300);
 
            timer.Start();
            timer2.Start();
        }
После этих изменений осталось только мерцание стрелки! Сам круг больше не мерцает!
1
4 / 4 / 0
Регистрация: 08.03.2011
Сообщений: 42
08.08.2013, 11:41 12
Спасибо за помощь. Сейчас проблема не в мерцании, а в скорости стрелки.
0
0 / 0 / 0
Регистрация: 18.04.2016
Сообщений: 9
18.04.2016, 11:51 13
Моя версия аналоговых часов
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
 
namespace MyClock
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void timer1_Tick(object sender, EventArgs e)
        {
            Text = DateTime.Now.ToLongTimeString();
            Invalidate();
 
        }
 
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics G = e.Graphics;
            G.SmoothingMode = SmoothingMode.HighQuality;
            G.Clear(Color.White);
            int Mx = ClientRectangle.Width;
            int My = ClientRectangle.Height;
            Point ptCenter = new Point(Mx / 2, My / 2);
            int R = Math.Min(Mx, My) / 2 - 1;
            using (Pen P = new Pen(Color.Black, 2))
                G.DrawEllipse(P, ptCenter.X - R, ptCenter.Y - R, R + R, R + R);
            using (LinearGradientBrush br = new LinearGradientBrush
                (ClientRectangle, Color.White, Color.DarkGray,
                    LinearGradientMode.BackwardDiagonal))
                G.FillEllipse(br, ptCenter.X - R, ptCenter.Y - R, R + R, R + R);
            for (int minute = 0; minute < 60; minute++)
            {
                Point pt = RadiaPoint(ptCenter, R - 20, minute);
                using (SolidBrush BS = new SolidBrush(Color.Black))
                {
                    if ((minute % 5) == 0) G.FillRectangle(BS, pt.X - 3, pt.Y - 3, 7, 7);
                    else G.FillRectangle(BS, pt.X - 1, pt.Y - 1, 2, 2);
                }
            }
            DateTime DT = DateTime.Now;
            using (Pen P = new Pen(Color.FromArgb(80, 20, 70, 30), 4))
            {
                P.CustomEndCap = new AdjustableArrowCap(4, 6, true);
                Point ptN = RadiaPoint(ptCenter, 20, DT.Second + 30);
                Point ptE = RadiaPoint(ptCenter, R - 2, DT.Second);
                G.DrawLine(P, ptN, ptE);
            }
            using (Pen P = new Pen(Color.FromArgb(100, 0, 0, 0), 6))
            {
                P.StartCap = LineCap.RoundAnchor;
                P.EndCap = LineCap.Round;
                G.DrawLine(P, RadiaPoint(ptCenter, 15, 30 + DT.Minute),
                              RadiaPoint(ptCenter, (int)(R * 0.8), DT.Minute));
            }
            using (Pen P = new Pen(Color.Black, 8))
            {
                P.StartCap = LineCap.Flat;
                P.EndCap = LineCap.DiamondAnchor;
                float[] CV = new float[] { 0.0f, 0.2f, 0.5f, 0.7f, 0.9f, 1.0f };
                P.CompoundArray = CV;
                G.DrawLine(P, RadiaPoint(ptCenter, 15, 30 + DT.Hour * 5 + DT.Minute / 12),
                    RadiaPoint(ptCenter, (int)(R * 0.75), DT.Hour * 5 + DT.Minute / 12));
            }
 
 
                           
        }
        private Point RadiaPoint(Point ptCenter, int R, int seconds)
        {
            double angle = -((seconds - 15) % 60) * Math.PI / 30;
            return new Point(ptCenter.X + (int)(R * Math.Cos(angle)),
                ptCenter.Y - (int)(R * Math.Sin(angle)));
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer,true);
            SetStyle(ControlStyles.UserPaint, true);
        }
       
 
    }
}
0
18.04.2016, 11:51
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.04.2016, 11:51
Помогаю со студенческими работами здесь

аналоговые часы на C#
задание по сути таково что надо сделать часы со стрелками: часовой, минутной и секундной. а время...

Даны целые числа m (часы) и n (минуты) .Определить наименьшее время (в минутах) когда совпадут минуты и часы
Даны целые числа m (часы) и n (минуты) .Определить наименьшее время (в минутах) до того момента ...

Даны целые числа m (часы) и n (минуты) .Определить наименьшее время (в минутах) когда совпадут минуты и часы
Даны целые числа m (часы) и n (минуты) .Определить наименьшее время (в минутах) до того момента ...

Из секунд - часы, минуты и секунды. Из минут - часы, минуты
private void button4_Click(object sender, EventArgs e) { if (textBox3.Text ==...

Аналоговые часы
Добрый день! Стоит задача разработать программу для построения часов со стрелочным циферблатом....

Аналоговые часы
Сделал часы, секундная и минутная стрелки отображают корректное время, а вот с часовой беда. Вроде...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru