Как прикрепить QDialog к границам экрана, как это делает Skype? - PullRequest
3 голосов
/ 26 апреля 2010

Давным-давно я пытался найти способ, как прикрепить окно QDialog к границам экрана для моих небольших проектов, таких как Skype Windows, но это не удалось. Может быть, я искал этот код не в нужном месте, так что теперь я ищу решение здесь, в стеке! :)

Итак, кто-нибудь имеет дело с каким-то кодом, ссылками, примерами?

По моему мнению, нам нужно переопределить функцию moveDvent QDialog, как показано ниже, но этот код не работает:

void    CDialog::moveEvent(QMoveEvent * event) {

    QRect wndRect;
    int leftTaskbar = 0, rightTaskbar = 0, topTaskbar = 0, bottomTaskbar = 0;
//  int top = 0, left = 0, right = 0, bottom = 0;

    wndRect = this->frameGeometry();

    // Screen resolution
    int screenWidth =   QApplication::desktop()->width();
    int screenHeight =  QApplication::desktop()->height();

    int wndWidth = wndRect.right() - wndRect.left();
    int wndHeight = wndRect.bottom() - wndRect.top();

    int posX = event->pos().x();
    int posY = event->pos().y();

    // Snap to screen border
    // Left border
    if (posX >= -m_nXOffset + leftTaskbar &&
        posX <= leftTaskbar + m_nXOffset) {
        //left = leftTaskbar;
        this->move(leftTaskbar, posY);
        return;
    }

    // Top border
    if (posY >= -m_nYOffset &&
        posY <= topTaskbar + m_nYOffset) {
        //top = topTaskbar;
        this->move(posX, topTaskbar);
        return;
    }

    // Right border
    if (posX + wndWidth <= screenWidth - rightTaskbar + m_nXOffset &&
        posX + wndWidth >= screenWidth - rightTaskbar - m_nXOffset) {
        //right = screenWidth - rightTaskbar - wndWidth;
        this->move(screenWidth - rightTaskbar - wndWidth, posY);
        return;
    }

    // Bottom border
    if (posY + wndHeight <= screenHeight - bottomTaskbar + m_nYOffset &&
        posY + wndHeight >= screenHeight - bottomTaskbar - m_nYOffset) {
        //bottom = screenHeight - bottomTaskbar - wndHeight;
        this->move(posX, screenHeight - bottomTaskbar - wndHeight);
        return;
    }

    QDialog::moveEvent(event);
}

Спасибо.

Ответы [ 2 ]

1 голос
/ 11 мая 2010

В описании свойства pos из документации QWidget имеется следующее предупреждение о перемещении окна внутри метода обработки события перемещения.

Предупреждение: Вызов move() или setGeometry() внутри moveEvent() может привести к бесконечной рекурсии.

Тем не менее, нет правильного способа прикрепить диалоговое окно внутри границы экрана.

Примечание. Поведение, которое вы наблюдали в KDE, происходит из оконного менеджера.На самом деле диспетчер окон - это тот, который организует окна приложений (например, диалоговые окна), чтобы они отображались на экране.В KDE Window Manager есть возможность заставить все окна приложений (называемые клиентскими) придерживаться границы.

1 голос
/ 26 апреля 2010

Как вы и думали, вы можете достичь этого с помощью функции moveEvent. Я предполагаю, что следующий код справится с задачей, но так как мне нечего здесь тестировать, я напишу некоторый псевдокод:

Сначала получите доступную область экрана:

const QRect screen = QApplication::availableGeometry(this);
// This get the screen rect where you can drag a dialog

Затем получите позицию вашего диалога относительно рабочего стола (если ваш диалог является дочерним элементом другого виджета, вам нужно преобразовать координаты из виджета относительно рабочего стола относительно):

const QRect dialog = geometry();
// Do here transformation

Теперь проверьте, находится ли диалоговое окно рядом с границей экрана

if( abs(dialog.left()-screen.left() < OFFSET )
    move(screen.left(), dialog.top();
else if( abs(dialog.top()-screen.top() < OFFSET )
    move(dialog.left(), screen.top() )
// etc. for the 2 other cases

Дайте мне знать, если это работает

...