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

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

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Прикрепление окна к краю рабочего стола  (Прочитано 11349 раз)
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #15 : Январь 14, 2014, 12:38 »

Не понравилась мне реализация с наследованием, поэтому переписал Улыбающийся
Название класса кажется не удачным В замешательстве

Код
C++ (Qt)
class AddAttachable: public QObject
{
   Q_OBJECT
 
public:
   AddAttachable( QObject * parent = 0 )
       : QObject( parent ),
         window( 0 ),
         timerId( -1 ),
         d_distance( 10 ),
         activate( true )
   {
 
   }
   void setDistance( int d )
   {
       d_distance = d;
   }
   int distance()
   {
       return d_distance;
   }
   void installTo( QWidget * widget )
   {
       if ( window )
           remove();
 
       window = widget;
       window->installEventFilter( this );
   }
   void remove()
   {
       window->removeEventFilter( this );
       window = 0;
   }
 
private:
   QWidget * window;
   int timerId;
   int d_distance;
   bool activate;
 
public slots:
   void setActivate( bool act )
   {
       activate = act;
   }
   bool isActivate()
   {
       return activate;
   }
 
protected:
   void timerEvent( QTimerEvent * event )
   {
       if ( !window || !activate ) // паранойя
           return;
 
       const QRect & availableGeometry = QDesktopWidget().availableGeometry();
       int d_x = availableGeometry.x();
       int d_y = availableGeometry.y();
       int d_width = availableGeometry.width();
       int d_height = availableGeometry.height();
 
       int x = window->x();
       int y = window->y();
       int width = window->width();
       int height = window->height();
 
       if ( x >= d_x && x <= d_distance )
           window->move( d_x, y );
 
       if ( y >= d_y && y <= d_distance )
           window->move( x, d_y );
 
       if ( x + width >= d_width - d_distance && x + width <= d_width )
           window->move( d_width - width, y );
 
       if ( y + height >= d_height - d_distance && y + height <= d_height )
           window->move( x, d_height - height );
   }
 
   bool eventFilter( QObject * object, QEvent * event )
   {
       if ( object == window && activate )
       {
           if ( event->type() == QEvent::MouseButtonPress )
               timerId = startTimer( 333 );
 
           else if ( event->type() == QEvent::MouseButtonRelease )
               killTimer( timerId );
       }
 
       return QObject::eventFilter( object, event );
   }
};
 
class MovableWindow: public QWidget
{
public:
   MovableWindow( QWidget * parent = 0 )
       : QWidget( parent )
   {
       setWindowFlags( Qt::Window | Qt::FramelessWindowHint );
 
       QHBoxLayout * layout = new QHBoxLayout();
       layout->setContentsMargins( 0, 0, 0, 0 );
       layout->addWidget( new QSizeGrip( this ), 0, Qt::AlignLeft | Qt::AlignTop );
       layout->addWidget( new QSizeGrip( this ), 0, Qt::AlignRight | Qt::AlignBottom );
       setLayout( layout );
 
       setMinimumSize( 50, 50 );
       resize( 150, 150 );
 
       AddAttachable * addAttachable = new AddAttachable( this );
       addAttachable->installTo( this );
   }
 
private:
   bool isMousePress;
   QPoint oldPosition;
 
protected:
   void mousePressEvent( QMouseEvent * event )
   {
       if ( event->button() == Qt::LeftButton )
       {
           oldPosition = event->pos();
           isMousePress = true;
       }
 
       QWidget::mousePressEvent( event );
   }
   void mouseReleaseEvent( QMouseEvent * event )
   {
       isMousePress = false;
 
       QWidget::mouseReleaseEvent( event );
   }
   void mouseMoveEvent( QMouseEvent * event )
   {
       if ( isMousePress )
       {
           QPoint delta = event->pos() - oldPosition;
           move( pos() + delta );
       }
 
       QWidget::mouseMoveEvent( event );
   }
   void paintEvent( QPaintEvent * )
   {
       QPainter painter( this );
       painter.setPen( QPen( Qt::black, 2.0 ) );
       painter.drawRect( rect() );
   }
};
 
« Последнее редактирование: Январь 14, 2014, 23:53 от gil9red » Записан

GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #16 : Январь 14, 2014, 12:39 »

А смысл прибивать таймер, если его и так прибьет после того как будет отпущена мышь? Улыбающийся
Таймер ведь работает пока зажата кнопка мыши Улыбающийся
Согласен)
Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #17 : Январь 14, 2014, 13:06 »

А если по-народному?
Код
C++ (Qt)
bool MyWidget::event( QEvent * e )
{
static bool inDrag = false;
 
qDebug() << e->type();
switch ((int) e->type()) {
case QEvent::NonClientAreaMouseButtonPress:
inDrag = true;
break;
 
case QEvent::NonClientAreaMouseButtonRelease:
if (inDrag)
qApp->postEvent(this, new QEvent(QEvent::User));
inDrag = false;
break;
 
case QEvent::Move:
if (!inDrag)
qApp->postEvent(this, new QEvent(QEvent::User));
break;
 
case QEvent::User:
if (pos().x() < 50)
move(QPoint(50, pos().y()));
break;
}
 
return false;
}
 
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #18 : Январь 14, 2014, 13:15 »

Igors, интересное решение Улыбающийся
Записан

Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #19 : Январь 14, 2014, 13:22 »

На нормальном ОС даже не нужно отслеживать драг - окно как бы "упирается", сдвинуть дальше его пользователь не может. Но на чмошном Вындоуз возникает неприятный эффект "мельтешения"  Плачущий  
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #20 : Январь 14, 2014, 14:01 »

На нормальном ОС даже не нужно отслеживать драг - окно как бы "упирается", сдвинуть дальше его пользователь не может. Но на чмошном Вындоуз возникает неприятный эффект "мельтешения"  Плачущий  
Наверное нужно всё-таки говорить не про ОС, а оконный менеджер.
В случае ТС оный не используется вовсе, так что только ручками)
Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #21 : Январь 14, 2014, 17:36 »

Наверное нужно всё-таки говорить не про ОС, а оконный менеджер.
В случае ТС оный не используется вовсе, так что только ручками)
Хмм... я полагал что FrameLess вообще не заслуживает обсуждения - ведь там никакого реентера нет, зачем совать таймер? Ну ладно, примерчик в аттаче (была заготовка для драга, добавил отсечки)

Вспоминая недавнюю тему - не лучше ли было иметь этот сервис "внешним", не загружая код рабочих окон ?  Улыбающийся
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #22 : Январь 14, 2014, 17:41 »

Хмм... я полагал что FrameLess вообще не заслуживает обсуждения - ведь там никакого реентера нет, зачем совать таймер?
Согласен, через postEvent() красивее)

Цитировать
Вспоминая недавнюю тему - не лучше ли было иметь этот сервис "внешним", не загружая код рабочих окон ?  Улыбающийся
Хм... чего-то не понял про что речь?
Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #23 : Январь 14, 2014, 18:08 »

Хм... чего-то не понял про что речь?
Ну вот написан какой-то код (любой из вариантов выше, здесь не суть). Как его использовать? Когда "все с нуля" эта проблема не чувствуется - захотел создал новый класс, почему нет. А вот когда уже что-то наработано - ой как не хочется это ворошить, а если еще хоть часть кода не своя... Вот если  gil9red призадумается как сделать это "easy to use"  Улыбающийся
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #24 : Январь 14, 2014, 23:09 »

Хм... чего-то не понял про что речь?
Ну вот написан какой-то код (любой из вариантов выше, здесь не суть). Как его использовать? Когда "все с нуля" эта проблема не чувствуется - захотел создал новый класс, почему нет. А вот когда уже что-то наработано - ой как не хочется это ворошить, а если еще хоть часть кода не своя... Вот если  gil9red призадумается как сделать это "easy to use"  Улыбающийся

Подумаю, но не обещаю, что сделаю Веселый
Записан

Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #25 : Январь 14, 2014, 23:24 »

Подумаю, но не обещаю, что сделаю Веселый
Ну так вы уже придумали AddAttachable. Объект этого класса можно использовать вне перемещаемого объекта: есть готовый виджет, стало нужно что бы он начал прилипать - добавили объект класса AddAttachable и привязали к нему виджет.

Внимательно посмотрите на условие, паранойя ли? Подмигивающий  [window = 0; activate = true] -> какой результат?

Код
C++ (Qt)
   void timerEvent( QTimerEvent * event )
   {
       if ( !window && !activate ) // паранойя
           return;
 
« Последнее редактирование: Январь 14, 2014, 23:29 от Old » Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #26 : Январь 14, 2014, 23:53 »

Подумаю, но не обещаю, что сделаю Веселый
Ну так вы уже придумали AddAttachable. Объект этого класса можно использовать вне перемещаемого объекта: есть готовый виджет, стало нужно что бы он начал прилипать - добавили объект класса AddAttachable и привязали к нему виджет.
Просто я не уверен, что не захочу допилить класс, также как не уверен, что захочу Веселый

Внимательно посмотрите на условие, паранойя ли? Подмигивающий  [window = 0; activate = true] -> какой результат?
Код
C++ (Qt)
   void timerEvent( QTimerEvent * event )
   {
       if ( !window && !activate ) // паранойя
           return;
 
Результат будет true, только тогда, когда обе переменные имеют значение false (или 0) - не заметил - косяк Улыбающийся
Надо бы условие поменять на логическое "или" (||) Улыбающийся
А паранойя, потому что, в eventFilter прописано условие создания таймера и timerEvent не должен случиться, только если его не вызовут другие таймера Улыбающийся
« Последнее редактирование: Январь 14, 2014, 23:56 от gil9red » Записан

Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #27 : Январь 15, 2014, 00:00 »

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


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