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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Перемещение QFrame  (Прочитано 10814 раз)
AD
Гость
« : Июль 24, 2009, 10:40 »

Не удается заставить правильно перемещаться визир. Визир (QFrame) находится в виджете GraphicDisplay, точнее список визиров.
Код
C++ (Qt)
/// Класс для переопределения виджета каждого визира
class VFFrame: public QFrame
{
Q_OBJECT
 
private:
QPoint _move_point; ///< точка целеуказания, куда необходимо двигать
 
signals:
void moveVF();
 
public:
void setMovePoint(const QPoint& pnt) { _move_point = pnt; }
};
 
/// Передвижение визира вслед за мышью
void VFFrame::mouseMoveEvent(QMouseEvent* events)
{
QFrame::mouseMoveEvent(events);
 
emit moveVF();
 
if(!_is_left_pressed) return;
if(_vf_shape == QFrame::VLine)
setGeometry(_move_point.x(), y(), width(), height());
else if(_vf_shape == QFrame::HLine)
setGeometry(x(), _move_point.y(), width(), height());
}
 
/// Отпускание кнопки мыши
void VFFrame::mouseReleaseEvent(QMouseEvent* events)
{
QFrame::mouseReleaseEvent(events);
 
emit moveVF();
 
if(!_is_left_pressed) return;
_is_left_pressed = false;
if(_vf_shape == QFrame::VLine)
setGeometry(_move_point.x(), y(), width(), height());
else if(_vf_shape == QFrame::HLine)
setGeometry(x(), _move_point.y(), width(), height());
_is_viewfinder = false;
}
 
/// Изменение размеров окна
void VFFrame::resizeEvent(QResizeEvent* events)
{
if(_vf_shape == QFrame::VLine)
setGeometry(x(), 0, 16, parentWidget() -> height());
else if(_vf_shape == QFrame::HLine)
setGeometry(0, y(), parentWidget() -> width(), 16);
}
 
/// Класс для отображения параметров по времени или по расстоянию
class GraphicDisplay : public QDialog, public Ui::GraphicDisplayClass
{
Q_OBJECT
 
private:
QList<VFFrame*> viewfinderList; ///< список всех визиров
QPoint _move_pointVF; ///< точка, куда следует перемещаться визир
void connectViewfinder();
void disconnectViewfinder();
 
private slots:
void setMovePoint();
};
 
/// Проверка на попадание фокуса на визир
bool GraphicDisplay::isViewfinder(const QPoint& pos)
{
foreach(VFFrame* pf, viewfinderList)
if(pf -> isViewfinder())
{
_move_pointVF = pos;
return true;
}
return false;
}
 
/// Подсоединение сигнала
void GraphicDisplay::connectViewfinder()
{
foreach(VFFrame* pf, viewfinderList)
if(pf -> isViewfinder())
{
connect(pf, SIGNAL(moveVF()), this, SLOT(setMovePoint()));
break;
}
}
 
/// Разъединение сигнала
void GraphicDisplay::disconnectViewfinder()
{
foreach(VFFrame* pf, viewfinderList)
if(pf -> isViewfinder())
{
disconnect(pf, SIGNAL(moveVF()), this, SLOT(setMovePoint()));
break;
}
}
 
/// Нажатие на кнопку - рисование "резиновой ленты"
void GraphicDisplay::mousePressEvent(QMouseEvent* events)
{
QWidget::mousePressEvent(events);
 
if(isViewfinder(events -> pos())) { connectViewfinder(); return; }
// ....................................
}
 
/// Переопределение функции передвижения мыши
void GraphicDisplay::mouseMoveEvent(QMouseEvent* events)
{
if(isViewfinder(events -> pos())) return;
 
// .............................................
}
 
/// Возвращение прежнего вида курсору и изменение масштаба
void GraphicDisplay::mouseReleaseEvent(QMouseEvent* events)
{
if(isViewfinder(events -> pos()))
{ disconnectViewfinder(); return; }
 
// ....................................................................
}

Смысл в том, что во время движения в координату _move_point записывается предыдущее значение, т.к. движение мыша функций GraphicDisplay попадает позже, чем в движение мыша функций VFFrame. Как все-таки добиться эффекта, чтобы в функцию setMovePoint класса VFFrame передавалось значение events -> pos() класса GraphicDisplay?
Записан
AD
Гость
« Ответ #1 : Июль 24, 2009, 13:02 »

Есть хоть какие-нибудь идеи, как можно откорректировать код? Ну хоть подтолкните, пожалуйста, на мысль, как выправить код. Как сделать перемещение визира плавным, а не скачкообразным?
Записан
spectre71
Гость
« Ответ #2 : Июль 24, 2009, 13:15 »

Есть хоть какие-нибудь идеи, как можно откорректировать код? Ну хоть подтолкните, пожалуйста, на мысль, как выправить код. Как сделать перемещение визира плавным, а не скачкообразным?
Из твоего описания и кода непонятно что ты хочешь сделать!
Например говоришь о "_move_point", а в твоем коде она нигде не изменяется.
Записан
AD
Гость
« Ответ #3 : Июль 24, 2009, 13:50 »

setMovePoint() ее меняет.
Мне необходимо, чтобы движение визира шло плавно, а не скачками назад-вперед.

Вот так изменяет setMovePoint:
Код
C++ (Qt)
// in header
private slots:
void setMovePoint();
 
/// Слот установки экранных координат во фрейм визира
void GraphicDisplay::setMovePoint()
{
foreach(VFFrame* pf, viewfinderList)
if(pf -> isViewfinder())
{
pf -> setMovePoint(_move_pointVF);
break;
}
}
 
Записан
ufna
Гость
« Ответ #4 : Июль 24, 2009, 13:54 »

а в целом код данного куска можешь выложить? или это комм. тайна?

скачки взад-вперед происходят видимо по причинетого, что функция, идущей второй, кидает виджет на бывшее значение. Вывод - нужно из первого эвента менять некий флаг во втором или еще что, запрещающий "кидать назад".
Записан
AD
Гость
« Ответ #5 : Июль 24, 2009, 14:12 »

Так я все, что относится к этому коду и выложил. Все, что идет далее в функция QGraphicDisplay::mouse....Event - Это масштабирование самого графика.
Записан
AD
Гость
« Ответ #6 : Июль 24, 2009, 14:16 »

Вот еще раз код:
Код
C++ (Qt)
/// Класс для переопределения виджета каждого визира
class VFFrame: public QFrame
{
Q_OBJECT
 
private:
Shape _vf_shape; ///< форма визира (вертикальный или горизонтальный)
bool _is_left_pressed; ///< флаг указания нажатия на левую кнопку мыши
bool _is_viewfinder; ///< флаг сигнализации о наведении курсора мыши на визир
QPoint _move_point; ///< точка целеуказания, куда необходимо двигать
 
signals:
void moveVF();
 
protected:
virtual void mousePressEvent(QMouseEvent* events);
virtual void mouseMoveEvent(QMouseEvent* events);
virtual void mouseReleaseEvent(QMouseEvent* events);
virtual void resizeEvent(QResizeEvent* events);
virtual void enterEvent(QEvent* events) { _is_viewfinder = true; }
virtual void leaveEvent(QEvent* events) { _is_viewfinder = false; }
 
public:
VFFrame(QWidget *parent, const Shape shape = QFrame::VLine);
virtual ~VFFrame() {}
void setShape(const Shape shape) { setFrameShape(shape); _vf_shape = shape; }
bool isViewfinder() const { return _is_viewfinder; }
void setMovePoint(const QPoint& pnt) { _move_point = pnt; }
};
 
/// Переопределение нажатия на лекую кнопку мыши
void VFFrame::mousePressEvent(QMouseEvent* events)
{
QFrame::mousePressEvent(events);
 
emit moveVF();
 
switch(events -> button())
{
case Qt::LeftButton: ///< если нажата левая кнопка мыши
_is_left_pressed = true;
break;
}
}
 
/// Передвижение визира вслед за мышью
void VFFrame::mouseMoveEvent(QMouseEvent* events)
{
QFrame::mouseMoveEvent(events);
 
emit moveVF();
 
if(!_is_left_pressed) return;
if(_vf_shape == QFrame::VLine)
setGeometry(_move_point.x(), y(), width(), height());
else if(_vf_shape == QFrame::HLine)
setGeometry(x(), _move_point.y(), width(), height());
}
 
/// Отпускание кнопки мыши
void VFFrame::mouseReleaseEvent(QMouseEvent* events)
{
QFrame::mouseReleaseEvent(events);
 
emit moveVF();
 
if(!_is_left_pressed) return;
_is_left_pressed = false;
if(_vf_shape == QFrame::VLine)
setGeometry(_move_point.x(), y(), width(), height());
else if(_vf_shape == QFrame::HLine)
setGeometry(x(), _move_point.y(), width(), height());
_is_viewfinder = false;
}
 
 
/// Слот установки экранных координат во фрейм визира
void GraphicDisplay::setMovePoint()
{
foreach(VFFrame* pf, viewfinderList)
if(pf -> isViewfinder())
{
pf -> setMovePoint(_move_pointVF);
break;
}
}
 
/// Проверка на попадание фокуса на визир
bool GraphicDisplay::isViewfinder(const QPoint& pos)
{
foreach(VFFrame* pf, viewfinderList)
if(pf -> isViewfinder())
{
_move_pointVF = pos;
return true;
}
return false;
}
 
/// Подсоединение сигнала
void GraphicDisplay::connectViewfinder()
{
foreach(VFFrame* pf, viewfinderList)
if(pf -> isViewfinder())
{
connect(pf, SIGNAL(moveVF()), this, SLOT(setMovePoint()));
break;
}
}
 
/// Разъединение сигнала
void GraphicDisplay::disconnectViewfinder()
{
foreach(VFFrame* pf, viewfinderList)
if(pf -> isViewfinder())
{
disconnect(pf, SIGNAL(moveVF()), this, SLOT(setMovePoint()));
break;
}
}
 
/// Копирование визиров
void GraphicDisplay::copyingViewfinder(QMouseEvent* events)
{
if(events -> button() != Qt::LeftButton || events -> modifiers() != Qt::ControlModifier)
return;
foreach(VFFrame* pf, viewfinderList)
if(pf -> isViewfinder())
{
appendViewfinder(pf -> frameShape());
break;
}
}
 
/// Нажатие на кнопку - рисование "резиновой ленты"
void GraphicDisplay::mousePressEvent(QMouseEvent* events)
{
QWidget::mousePressEvent(events);
 
if(isViewfinder(events -> pos()))
{
copyingViewfinder(events);
connectViewfinder();
return;
}
// ...................
}
 
/// Переопределение функции передвижения мыши
void GraphicDisplay::mouseMoveEvent(QMouseEvent* events)
{
if(isViewfinder(events -> pos())) return;
// ......................
}
 
/// Возвращение прежнего вида курсору и изменение масштаба
void GraphicDisplay::mouseReleaseEvent(QMouseEvent* events)
{
if(isViewfinder(events -> pos()))
{ disconnectViewfinder(); return; }
}
 
Записан
spectre71
Гость
« Ответ #7 : Июль 24, 2009, 14:45 »

Не стал особо разбираться, но если правильно понял, то установка новых координат происходит по сигналу moveVF.
Так почему бы не передавать через него необходимую координату?
Записан
AD
Гость
« Ответ #8 : Июль 24, 2009, 15:17 »

Понял правильно. Беда в том, что правильные координаты в функция mouse....Event класса GraphicDisplay!
Записан
ufna
Гость
« Ответ #9 : Июль 24, 2009, 15:38 »

а почему нельзя сделать VFFrame доступ к GraphicDisplay? А в нем функцию, которая из отданных в него координат мыши вернет правильные координаты. Или наоборот, я не вникал кто чем двигает.
Записан
AD
Гость
« Ответ #10 : Июль 24, 2009, 15:49 »

Корректные координаты доступны в защищенных функциях mouse....Event класса GraphicDisplay. Каким образом организовать доступ? Если бы знал, сам бы сделал, не спрашивая! Улыбающийся
Записан
ufna
Гость
« Ответ #11 : Июль 24, 2009, 15:55 »

имхо, можно так:
визир (это такая линия типа?) при нажатии на него делает grabMouse();
после этого, перемещение его идет только в его собственном мув эвенте. Подстройка идет под координаты мыши однозначно.

зачем в принципе в этом должен учавствовать GraphicDisplay?

и еще - можешь скомпилированный вариант выложить, чтобы увидеть как оно в деле? Еще есть идея, но вначале хочется убедиться.

либо так - в сиих функциях у визира не делается ничего, кроме установки внутрь себя флажка нажат/не нажат. А график дисплей в своем мув эвенте обращается к объекту визира (пусть заимеет на него указатель, если нету), смотрит на этот флажок, и если он "тру", то переносит визир куда нужно.
« Последнее редактирование: Июль 24, 2009, 15:58 от ufna » Записан
spectre71
Гость
« Ответ #12 : Июль 24, 2009, 16:04 »

Понял правильно. Беда в том, что правильные координаты в функция mouse....Event класса GraphicDisplay!
Если сделаешь GraphicDisplay доступным для VFFrame:
1) получашь mouse координаты mouseEvent у VFFrame - gpos= e->globalPos ().
2) pos = GraphicDisplay->mapFromGlobal(gpos)
Записан
AD
Гость
« Ответ #13 : Июль 24, 2009, 16:17 »

Рисунок того, как это выглядит, можно посмотреть здесь:
http://www.forum.crossplatform.ru/index.php?showtopic=3093&st=0&gopid=22586&#entry22586

ufna, ты ведь там зарегистрирован. Мог бы посмотреть тему! Улыбающийся
« Последнее редактирование: Июль 24, 2009, 16:19 от AD » Записан
AD
Гость
« Ответ #14 : Июль 24, 2009, 16:21 »

Если сделаешь GraphicDisplay доступным для VFFrame:
1) получашь mouse координаты mouseEvent у VFFrame - gpos= e->globalPos ().
2) pos = GraphicDisplay->mapFromGlobal(gpos)
А можно поподробнее пункты? Прости. пока не врубился как сделать!
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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