Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Qt 4.3.1 [Прилипание окна как у Winamp]


Автор: SABROG 18.8.2007, 18:29
Думал все будет легко, алгоритм ясен. Но не получается, Trolltech предупредили, что вызывать setGeometry внутри moveEvent, resizeEvent нельзя, т.к. будет бесконечная рекурсия. Ну конец то у нее есть - краш, это я уже выяснил.

Но дело в том, что я поставил специальные проверки, чтобы избежать подобной рекурсии. По логике, если граница правой рамки окна входит в 5 пиксельную зону (у меня 20 для удобства) перед правой границей робочего стола, то мы просто из ширины экрана вычитаем размер нашего окна и это и будет новая позиция X. Поэтому, если координата X границы правого окна программы равна ширине экрана, то значит программа уже на своей месте и setGeometry не требуется. Интересность еще в том, что для нижней границы окна, когда идет рассчет по Y - все работает. Ну за исключением бага с возможностью изменить ширину окна потащив за верхнюю границу заголовка окна. Тут тогда и координаты окна меняются и высота его меняется, в итоге это приводит к тому, что увеличить высоту окна можно, а вот уменьшить уже нет. Ну думаю ладно, если вычисления по Y работают, то почему по X не пашут. Вот код для приклеивания окна к правому краю:

Код

void TForm::moveEvent(QMoveEvent *event)
{
    int _x = event->pos().x(), _y = event->pos().y();
    if ((_x+width()) >= (QApplication::desktop()->width()-20) && (_x+width()) !=  QApplication::desktop()->width())
    {
       _x = QApplication::desktop()->width() - width();
         qDebug() << "x():" << event->pos().x() << " y():" << event->pos().y() << " _x: " << _x << " _y:" << _y << " width():" << width() << " height():" << height() << " Dwidth():" << QApplication::desktop()->width() << " Dheight():" << QApplication::desktop()->height();
         setGeometry(_x, _y, width(), height());
    }    
}


А это то, что я вижу в логе:

Код

[18.08.07 19:12:02] [D] x(): 300  y(): 157  _x:  316  _y: 157  width(): 960  height(): 768  Dwidth(): 1280  Dheight(): 1024 
[18.08.07 19:12:02] [D] x(): 312  y(): 134  _x:  316  _y: 134  width(): 960  height(): 768  Dwidth(): 1280  Dheight(): 1024 
[18.08.07 19:12:02] [D] x(): 312  y(): 111  _x:  316  _y: 111  width(): 960  height(): 768  Dwidth(): 1280  Dheight(): 1024 
[18.08.07 19:12:02] [D] x(): 312  y(): 88  _x:  316  _y: 88  width(): 960  height(): 768  Dwidth(): 1280  Dheight(): 1024 
[18.08.07 19:12:02] [D] x(): 312  y(): 65  _x:  316  _y: 65  width(): 960  height(): 768  Dwidth(): 1280  Dheight(): 1024 
[18.08.07 19:12:02] [D] x(): 312  y(): 42  _x:  316  _y: 42  width(): 960  height(): 768  Dwidth(): 1280  Dheight(): 1024 
[18.08.07 19:12:02] [D] x(): 312  y(): 19  _x:  316  _y: 19  width(): 960  height(): 768  Dwidth(): 1280  Dheight(): 1024 
[18.08.07 19:12:02] [D] x(): 312  y(): -4  _x:  316  _y: -4  width(): 960  height(): 768  Dwidth(): 1280  Dheight(): 1024 
... и т.д. до краша


Отсюда видно, что изначально в setGeometry передается правильно. Но при следующем входе в moveEvent видно, что координаты искажены, хрен бы с иксом, так вот как меняется Y я ума не приложу. Сам я его нигде не вычитаю и шаг какой-то странный - 23. Dwidth и Dheith - ширина/высота рабочего стола.

Автор: nickless 18.8.2007, 22:39
SABROG,
Попробуй вместо setGeometry(...) вызвать move(_x, _y), у меня так работает, правда в KDE smile 

А вообще можно реимплементировать QWidget::event() и делать там всё как QWidget, но позицию изменять заранее как надо, тогда оно будет лучше работать, потому что окно сразу передвинется куда нужно, а не будет прыгать как сейчас.

Автор: SABROG 19.8.2007, 10:12
Спасибо, действительно move() отрабатывает нормально. Вопрос решен.

Реализовал так, учитывая все известные баги это оптимальный вариант:

Код

void TForm::moveEvent(QMoveEvent *event)
{
    int _x = x(), _y = y(), newPosX = -1, newPosY = -1, snapFactorX = QApplication::desktop()->width()/30, snapFactorY = QApplication::desktop()->height()/30;
    if (_x > event->oldPos().x() && (_x+width()) >= (QApplication::desktop()->width()-snapFactorX) && (_x+width()) <  QApplication::desktop()->width())
    {
     newPosX = QApplication::desktop()->width() - width();
    }
    else if (_x < event->oldPos().x() && _x <= snapFactorX && _x > 0)
    {
     newPosX = 0;
    }
    if (_y > event->oldPos().y() && (_y+height()) >= (QApplication::desktop()->height()-snapFactorY) && (_y+height()) <  QApplication::desktop()->height())
    {
     newPosY = QApplication::desktop()->height() - height();
    }
    else if (_y < event->oldPos().y() && _y <= snapFactorY && _y > 0)
    {
     newPosY = 0;
    }
    if (newPosX != -1 || newPosY != -1)
    {   
         if (newPosX != -1)
         {
             _x = newPosX;
             newPosX = -1;
         }
         if (newPosY != -1)
         {
             _y = newPosY;
             newPosY = -1;
         }
         move(_x, _y);
    }   
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)