1, User defined interface introduction
UI design refers to the overall design of human-computer interaction, operation logic and beautiful interface of software. Excellent UI design not only makes the software personalized and tasteful, but also makes the operation of the software comfortable, simple and free, which fully reflects the positioning and characteristics of the software.
The standard for testing an interface is not the opinion of the leader of a project development team or the result of the vote of project members, but the feeling of end users. Therefore, for most commercial software or professional products, the localized style of Qt obviously can not meet expectations. A lot of style beautification is needed to make it more personalized and tasteful.
2, Borderless design
1. Borderless design
Set window ID as borderless
setWindowFlags(Qt::FramelessWindowHint | windowFlags());
There are many enumeration values about WindowFlags. One of them is WindowStaysOnTopHint, which allows the form to be located on all interfaces.
After no border is set, the form cannot be moved. There are two ways to move it.
2. Movable
A. QT event
//Position of the mouse relative to the form # event - > globalpos() - this - > pos() void Widget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_bPressed = true; m_point = event->pos(); } } //If the left mouse button is pressed, move the window position void Widget::mouseMoveEvent(QMouseEvent *event) { if (m_bPressed) move(event->pos() - m_point + pos()); } //Set mouse not pressed void Widget::mouseReleaseEvent(QMouseEvent *event) { Q_UNUSED(event); m_bPressed = false; }
B,Win API
//Contains header files and libraries that need to be used #ifdef Q_OS_WIN #pragma comment(lib, "user32.lib") #include <qt_windows.h> #endif //Send system messages to move void Widget::mousePressEvent(QMouseEvent *event) { #ifdef Q_OS_WIN if (ReleaseCapture()) SendMessage(HWND(winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); event->ignore(); #else #endif }
3, Custom title block
After customizing the title bar, all controls can be customized, such as adding skin change, setting button and other controls in the title bar.
1. Custom title block
TitleBar.h documents:
#ifndef TITLEBAR_H #define TITLEBAR_H #include <QWidget> class QLabel; class QPushButton; class TitleBar : public QWidget { Q_OBJECT public: explicit TitleBar(QWidget* parent = 0); ~TitleBar(); protected: //Double click the title bar to maximize / restore the interface virtual void mouseDoubleClickEvent(QMouseEvent *event); //Drag the mouse interface virtual void mousePressEvent(QMouseEvent *event); //Set interface title and Icon virtual bool eventFilter(QObject *obj, QEvent *event); private slots: //Minimize, maximize / restore, close void onClicked(); private: //Maximize / restore void updateMaximize(); private: QLabel *m_pIconLabel; QLabel *m_pTitleLabel; QPushButton *m_pMinimizeButton; QPushButton *m_pMaximizeButton; QPushButton *m_pCloseButton; }; #endif // TITLEBAR_H
TitleBar.cpp file:
#include <QLabel> #include <QPushButton> #include <QHBoxLayout> #include <QEvent> #include <QMouseEvent> #include <QApplication> #include "TitleBar.h" #ifdef Q_OS_WIN #pragma comment(lib, "user32.lib") #include <qt_windows.h> #endif TitleBar::TitleBar(QWidget* parent):QWidget(parent) { setFixedHeight(30); m_pIconLabel = new QLabel(this); m_pTitleLabel = new QLabel(this); m_pMinimizeButton = new QPushButton(this); m_pMaximizeButton = new QPushButton(this); m_pCloseButton = new QPushButton(this); m_pIconLabel->setFixedSize(20, 20); m_pIconLabel->setScaledContents(true); m_pTitleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_pMinimizeButton->setFixedSize(27, 22); m_pMaximizeButton->setFixedSize(27, 22); m_pCloseButton->setFixedSize(27, 22); m_pTitleLabel->setObjectName("whiteLabel"); m_pMinimizeButton->setObjectName("minimizeButton"); m_pMaximizeButton->setObjectName("maximizeButton"); m_pCloseButton->setObjectName("closeButton"); m_pMinimizeButton->setToolTip("Minimize"); m_pMaximizeButton->setToolTip("Maximize"); m_pCloseButton->setToolTip("Close"); QHBoxLayout *pLayout = new QHBoxLayout(this); pLayout->addWidget(m_pIconLabel); pLayout->addSpacing(5); pLayout->addWidget(m_pTitleLabel); pLayout->addWidget(m_pMinimizeButton); pLayout->addWidget(m_pMaximizeButton); pLayout->addWidget(m_pCloseButton); pLayout->setSpacing(0); pLayout->setContentsMargins(5, 0, 5, 0); setLayout(pLayout); connect(m_pMinimizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked())); connect(m_pMaximizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked())); connect(m_pCloseButton, SIGNAL(clicked(bool)), this, SLOT(onClicked())); } TitleBar::~TitleBar() { } void TitleBar::mouseDoubleClickEvent(QMouseEvent *event) { Q_UNUSED(event); emit m_pMaximizeButton->clicked(); } void TitleBar::mousePressEvent(QMouseEvent *event) { #ifdef Q_OS_WIN if (ReleaseCapture()) { QWidget *pWindow = this->window(); if (pWindow->isTopLevel()) { SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); } } event->ignore(); #else #endif } bool TitleBar::eventFilter(QObject *obj, QEvent *event) { switch (event->type()) { case QEvent::WindowTitleChange: { QWidget *pWidget = qobject_cast<QWidget *>(obj); if (pWidget) { m_pTitleLabel->setText(pWidget->windowTitle()); return true; } } case QEvent::WindowIconChange: { QWidget *pWidget = qobject_cast<QWidget *>(obj); if (pWidget) { QIcon icon = pWidget->windowIcon(); m_pIconLabel->setPixmap(icon.pixmap(m_pIconLabel->size())); return true; } } case QEvent::WindowStateChange: case QEvent::Resize: updateMaximize(); return true; } return QWidget::eventFilter(obj, event); } void TitleBar::onClicked() { QPushButton *pButton = qobject_cast<QPushButton *>(sender()); QWidget *pWindow = this->window(); if (pWindow->isTopLevel()) { if (pButton == m_pMinimizeButton) { pWindow->showMinimized(); } else if (pButton == m_pMaximizeButton) { pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized(); } else if (pButton == m_pCloseButton) { pWindow->close(); } } } void TitleBar::updateMaximize() { QWidget *pWindow = this->window(); if (pWindow->isTopLevel()) { bool bMaximize = pWindow->isMaximized(); if (bMaximize) { m_pMaximizeButton->setToolTip(tr("Restore")); m_pMaximizeButton->setProperty("maximizeProperty", "restore"); } else { m_pMaximizeButton->setProperty("maximizeProperty", "maximize"); m_pMaximizeButton->setToolTip(tr("Maximize")); } m_pMaximizeButton->setStyle(QApplication::style()); } }
mouseDoubleClickEvent
Double clicking the title bar will maximize / restore the form, so you need to override this event to control it.
mousePressEvent
Generally, the interface moves with the movement of the title bar, but not all positions in the interface can be dragged, so it is reasonable to write events in the title bar.
eventFilter
Event filter: the monitored form here is the form where the title bar is located, so when the form title, icon and other information change, the title bar should also change.
It is better not to directly call the interface to operate the corresponding behavior. For example, a public function is defined in TitleBar to specially modify the title and icon, which will cause unnecessary trouble. Because Qt itself is based on events, the filter method is adopted here.
2. Custom title block usage
Widget.h documents:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); }; #endif // WIDGET_H
Widget.cpp file:
#include "Widget.h" #include "TitleBar.h" #include <QIcon> #include <QVBoxLayout> Widget::Widget(QWidget *parent):QWidget(parent) { setWindowFlags(Qt::FramelessWindowHint | windowFlags()); TitleBar *pTitleBar = new TitleBar(this); installEventFilter(pTitleBar); resize(400, 300); setWindowTitle("Custom Window"); setWindowIcon(QIcon(":/Images/logo")); QPalette pal(palette()); pal.setColor(QPalette::Background, QColor(50, 50, 50)); setAutoFillBackground(true); setPalette(pal); QVBoxLayout *pLayout = new QVBoxLayout(); pLayout->addWidget(pTitleBar); pLayout->addStretch(); pLayout->setSpacing(0); pLayout->setContentsMargins(0, 0, 0, 0); setLayout(pLayout); } Widget::~Widget() { }
installEventFilter must be invoked before setWindowTitle and setWindowIcon, because the event filter must be installed before the corresponding event is triggered, then it will enter the eventFilter event in the title bar.