Russian Qt Forum
Апрель 18, 2024, 19:51 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Отловить клик в нужный сектор  (Прочитано 5718 раз)
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« : Июль 25, 2012, 22:40 »

Вот код класса:

h
Код
C++ (Qt)
#ifndef SHEDULEINDICATOR_H
#define SHEDULEINDICATOR_H
 
#include <QtCore/QMap>
 
#include <QtGui/QWidget>
 
class SheduleIndicator : public QWidget
{
Q_OBJECT
 
public:
explicit SheduleIndicator (QWidget *parent = 0);
 
void setShedule (const QMap <int, bool> &shedule) {
shedule_ = shedule;
drawImage();
}
 
protected:
virtual void showEvent (QShowEvent *);
virtual void paintEvent (QPaintEvent *event);
 
private:
void drawImage ();
 
private:
QMap <int, bool> shedule_;
QPixmap image_;
};
 
#endif //SHEDULEINDICATOR_H
 

cpp
Код
C++ (Qt)
#include <QtCore/QTimer>
#include <QtCore/QTime>
 
#include <QtGui/QPainter>
#include <QRadialGradient>
#include <QLinearGradient>
#include <QConicalGradient>
 
#include "sheduleindicator.h"
 
enum {UpdateInterval = 1000 * 60 * 1};
 
SheduleIndicator::SheduleIndicator (QWidget *parent)
: QWidget (parent)
{
QTimer *timer = new QTimer (this);
connect (timer, SIGNAL (timeout()), SLOT (update()));
timer->start (UpdateInterval);
}
 
void SheduleIndicator::drawImage ()
{
image_ = QPixmap (size ());
image_.fill (Qt::transparent);
 
const int side = qMin (width(), height());
 
QPainter painter;
painter.begin (&image_);
painter.setRenderHint (QPainter::Antialiasing);
painter.translate (width() / 2, height() / 2);
painter.scale (side / 200.0, side / 200.0);
 
const int radius = 65;
const int width = 30;
 
const QRect rectangle (-radius, -radius, radius * 2, radius * 2);
 
static const QColor insideColor (Qt::darkGray);
static const QColor offColor (QColor (195, 195, 195));
static const QColor onColor (QColor (228, 131, 16));
static const QColor foreGroundColor (QColor (95, 95, 105));
static const QColor digitsColor (QColor (195, 195, 195));
static const QColor edgeColor (QColor (26, 26, 26));
 
painter.setPen (QPen (edgeColor, 1));
painter.setBrush (Qt::NoBrush);
painter.drawEllipse (QPoint (0, 0), radius + width / 2, radius + width / 2);
painter.drawEllipse (QPoint (0, 0), radius - width / 2, radius - width / 2);
 
QPen sectionPen;
sectionPen.setWidth (width);
sectionPen.setCapStyle (Qt::FlatCap);
 
for (int i = 0; i < 24; ++i) {
QRadialGradient circle (0, 0, radius + width / 2, 0, 0);
circle.setColorAt (0.0, insideColor);
circle.setColorAt (0.62, insideColor);
circle.setColorAt (0.63, foreGroundColor);
circle.setColorAt (shedule_ [i] ? 0.68 : 0.65,
  shedule_ [i] ? onColor : offColor);
circle.setColorAt (shedule_ [i] ? 0.95 : 0.98,
  shedule_ [i] ? onColor : offColor);
circle.setColorAt (1.0, foreGroundColor);
sectionPen.setBrush (circle);
 
painter.setPen (sectionPen);
painter.drawArc (rectangle, 75 * 16, 15 * 16);
painter.rotate (15);
}
 
painter.setPen (QPen (foreGroundColor, 1));
 
for (int i = 0; i < 24; i++) {
painter.drawLine (0, radius - width / 2, 0, radius + width / 2);
painter.rotate (15);
}
 
painter.setBrush (insideColor);
painter.setPen (insideColor);
 
painter.drawEllipse (QPoint (0, 0), radius - width / 2 - 1, radius - width / 2 - 1);
 
 
// Digits
const QRectF rectangle1 (-100.0, -100.0, 200.0, 200.0);
painter.setPen (digitsColor);
painter.drawText (rectangle1, Qt::AlignTop | Qt::AlignHCenter, "0");
painter.drawText (rectangle1, Qt::AlignBottom | Qt::AlignHCenter, "12");
painter.drawText (rectangle1, Qt::AlignLeft | Qt::AlignVCenter, "18");
painter.drawText (rectangle1, Qt::AlignRight | Qt::AlignVCenter, "6  ");
 
painter.end();
}
 
void SheduleIndicator::showEvent (QShowEvent *e)
{
QWidget::showEvent (e);
 
drawImage();
}
 
 
void SheduleIndicator::paintEvent (QPaintEvent *)
{
const int side = qMin (width(), height());
 
QPainter painter (this);
painter.drawPixmap (QPoint (0, 0), image_);
painter.setRenderHint (QPainter::Antialiasing);
painter.translate (width() / 2, height() / 2);
painter.scale (side / 200.0, side / 200.0);
 
static const QPointF p0 (0, 10);
static const QPointF p1 (5, 5);
static const QPointF p2 (0.5, -70);
static const QPointF p3 (-0.5, -70);
static const QPointF p4 (-5, 5);
static const QPointF hourHand [5] = {p0, p1, p2, p3, p4};
 
painter.setPen (Qt::NoPen);
 
// Hand
painter.save();
const QTime time = QTime::currentTime();
painter.translate (QPoint (-2, 2));;
painter.rotate (15.0 * (time.hour() + time.minute() / 60.0));
painter.setBrush (QColor (0x40, 0x40, 0x40, 100));
painter.drawConvexPolygon (hourHand, 5);
painter.rotate (-15.0 * (time.hour() + time.minute() / 60.0));
painter.translate (QPoint (2, -2));;
painter.rotate (15.0 * (time.hour() + time.minute() / 60.0));
 
QLinearGradient handGradient (p1, p4);
handGradient.setColorAt (0.0, Qt::blue);
handGradient.setColorAt (0.5, Qt::darkBlue);
handGradient.setColorAt (1.0, Qt::blue);
painter.setBrush (handGradient);
 
painter.drawConvexPolygon (hourHand, 5);
painter.restore();
 
// hand pin
QRadialGradient handCircle (0, 0, 4, 0, 0);
handCircle.setColorAt (0.0, Qt::white);
handCircle.setColorAt (1.0, Qt::darkBlue);
painter.setBrush (handCircle);
painter.drawEllipse (QPoint (0, 0), 4, 4);
}
 

На картинке то, что отображается. Возникла необходимость отследить клик мыши и определить сектор, по которому кликнули. С рисованием и геометрией плохо, посему прошу помощи.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #1 : Июль 25, 2012, 22:57 »

Как вариарт можно попробовоть так:
1) От точки клика строим отрезок к центру и определем его длину.
2) Длина отрезка должна быть меньше\равна радиуса внешней окружности и больше\равна внутренней.
3) Определяем угол наклона отрезка, допустим к оси Х.
4) Полученный угол сравниваем с углами наклона радиусов сектора
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
DmitryM
Гость
« Ответ #2 : Июль 26, 2012, 09:48 »

1. переводишь координаты курсора в полярные координаты с центром в окружности.
2. проверяешь длину радиус-вектора
3. делишь угол на 2*pi/N, где N число секторов, получаешь номер нужного сектора.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Июль 27, 2012, 09:43 »

Код
C++ (Qt)
int GetSector( const QPoint & locMouse, const QPoint & center, int num = 12 )
{
QPoint delta = locMouse - center;
qreal angle = atan2(-delta.y(), delta.x());  // в экранных координатах y идет вниз, поэтому y с минусом
static const qreal PI2 = 3.141592 * 2;
if (angle < 0) angle += PI2;
return (int) (angle / PI2 * num);
}
 
atan2 возвращает угол с осью X, отсчитываемый против часовой стрелки. Сектор 0 будет "на 3 часа", сектор 1 на 2 часа и.т.д. Если надо перевести в "обычные часы" можно напр так
Код
C++ (Qt)
sector = ((12 - sector) + 3) % 12;
 
 
« Последнее редактирование: Июль 27, 2012, 10:38 от Igors » Записан
DmitryM
Гость
« Ответ #4 : Июль 27, 2012, 10:00 »

из описание atan2
Цитировать
y
Floating point value representing an y-coordinate.
x
Floating point value representing an x-coordinate.
If both arguments passed are zero, a domain error occurs, which sets the global variable ERRNO to the EDOM value.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #5 : Июль 29, 2012, 15:32 »

Фухх. Сделал. Правда, с точки зрения математики, все плохо (я так думаю), но меня устроило.
Код
C++ (Qt)
void SheduleIndicator::mousePressEvent (QMouseEvent *e)
{
if (mode_ != Edit) {
return;
}
 
const QPoint center (width () / 2, height () / 2);
const QPoint point (e->pos ().x ()- center.x (),
center.y () - e->pos ().y ());
 
const int distance = qSqrt (qPow ((center.x () - e->pos ().x ()), 2)
 + qPow ((center.y () - e->pos ().y ()), 2));
 
if (distance >= RMin && distance <= RMax) {
qreal angle = qAcos (point.y () / qSqrt (qPow (point.x (), 2) + qPow (point.y (), 2)));
if (point.x () < 0) {
angle = 2 * M_PI - angle;
}
 
const int i = angle / (2 * M_PI / 24);
 
shedule_ [i] = !shedule_ [i];
emit sheduleChanged ();
drawImage ();
repaint ();
}
}
 
 
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Июль 29, 2012, 16:23 »

Фухх. Сделал. Правда, с точки зрения математики, все плохо (я так думаю),
Правильно думаете Улыбающийся  А вообще Qt классы очень плохо приспособлены для инженерных расчетов, даже простых
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.159 секунд. Запросов: 23.