IT Notes

QWidget с нестандартной рамкой: Создаем декоративное окно

Разработаем простой Qt-виджет с нестандартной строкой заголовка. Пока что ограничимся лишь функционалом. Украшательства добавляются с помощью стилей (оставим их на другой раз). В итоге у нас выйдет что-то подобное:

draggable-widget-demo

Визуально получить представленный результат очень просто. Достаточно инициализировать наш виджет в конструкторе следующим образом:

DraggableWidget::DraggableWidget( QWidget* parent ) :
    QWidget( parent, Qt::Window | Qt::FramelessWindowHint ),
    ui( new Ui::DraggableWidget ) {
    ui->setupUi( this );

    ui->lbTitle->setText( windowTitle() );
    connect( ui->btnQuit, SIGNAL( clicked( bool ) ), qApp, SLOT( quit() ) );
}

Важный момент здесь заключается в указании флагов окна: Qt::Window | Qt::FramelessWindowHint. Все остальное сводится к правильной компоновке элементов на форме.

Для кнопки в правом верхнем углу я включил flat-режим через Qt Designer, чтобы она лучше вписывалась в интерфейс. При этом сигнал нажатия кнопки clicked() привязывается к слоту quit() для приложения.

поезд фото.

Но это еще не все. Окно теперь нельзя перемещать с помощью мыши. Добавим такую возможность. А чтобы сделать приложение еще более нестандартным, пусть его можно будет перемещать не только за область заголовка, но и за любое другое место.

Добавим обработчики событий мыши:

void DraggableWidget::mouseMoveEvent( QMouseEvent* e ) {
    if( e->buttons() | Qt::LeftButton ) {
        setGeometry(
            pos().x() + ( e->x() - dx ),
            pos().y() + ( e->y() - dy ),
            width(),
            height()
        );
    }
}

void DraggableWidget::mousePressEvent( QMouseEvent* e ) {
    if( e->button() == Qt::LeftButton ) {
        dx = e->x();
        dy = e->y();
        setCursor( Qt::OpenHandCursor );
    }
}

void DraggableWidget::mouseReleaseEvent( QMouseEvent* e ) {
    if( e->button() == Qt::LeftButton ) {
        setCursor( Qt::ArrowCursor );
    }
}

Немного геометрических расчетов и окно можно двигать. В mousePressEvent() фиксируем начальное положение курсора в системе координат виджета. В mouseMoveEvent() меняем глобальные координаты окна так, чтобы курсор мыши всегда оставался на том же расстоянии от левого верхнего угла виджета.

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

Исходники

 Скачать пример создания виджета с нестандартной строкой заголовка в Qt

Похожие публикации

Комментарии

А пример полу прозрачного окна можете показать ?

Anonymous:

А пример полу прозрачного окна можете показать ?

Здравствуйте. Спасибо за комментарий. Подготовлю к следующей статье :)

А когда новая статья будет ?

Anonymous:

А когда новая статья будет ?

Извиняюсь за отсутствие. Был в отпуске. Думаю, что уже на следующей неделе.

Доброго времени суток!

Было бы еще лучше, если бы DraggableWidget как то сделать похожим на оригинальный заголовок обычного приложения ОС. Иначе, такое приложение просто не вписывается в общее оформление.

Если есть идеи - подскажите, пожалуйста.

Anonymous:

Доброго времени суток!

Было бы еще лучше, если бы DraggableWidget как то сделать похожим на оригинальный заголовок обычного приложения ОС. Иначе, такое приложение просто не вписывается в общее оформление.

Если есть идеи - подскажите, пожалуйста.

Здравствуйте. Вы легко можете использовать стандартную рамку окна. Для этого просто уберите флаг Qt::FramelessWindowHint из кода инициализации.

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

Mikhail:

Anonymous:

Доброго времени суток!

Было бы еще лучше, если бы DraggableWidget как то сделать похожим на оригинальный заголовок обычного приложения ОС. Иначе, такое приложение просто не вписывается в общее оформление.

Если есть идеи - подскажите, пожалуйста.

Здравствуйте. Вы легко можете использовать стандартную рамку окна. Для этого просто уберите флаг Qt::FramelessWindowHint из кода инициализации.

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

Доброго времени суток!

Значит я что-то неверно понял. Если надо просто "выделиться на фоне остальных" - тогда да, можно просто загасить заголовок окна (ибо его отрисовывает ОС) и нарисовать все свое.

Но, иногда, нужно что-то просто добавить в заголовок окна (например подобие QToolBar с несколькими кнопками). Ну, хочется так. Тем более, что в windows это как раз делается просто. Хотелось бы что-то подобное изобразить в Qt под Linux, но как? Пока идей нет, думал, что вы сможете подсказать.