Qt窗口定制

Posted 朝十晚八

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt窗口定制相关的知识,希望对你有一定的参考价值。

qt中的QWidget窗口支持窗体绘制,但是不支持窗口标题栏绘制,想要美观的界面,还需要自己去定制,下面我就介绍一种定制窗体的方法

    一个窗口无非就3部分,标题栏、窗体和状态栏,接下来我定制的窗口没有状态栏,如果自己想加状态栏的话,照着这个模式自己也可以添加,说白了,窗口定制就是把完整的窗口分3部分定制,而每个部分又都是一个qt窗口

    定制窗口效果图如下,根据个人喜好,自己也可以定制不同的效果

图1 定制窗口

    如图1所示,这个窗口包含两部分,标题栏和窗体,这两部分其实分别是一个没有标题栏的QWidget,接下来我分别介绍下这两部分

   标题栏

   构造函数代码如下​

 1 setAutoFillBackground(true);//自动填充背景色,防止继承父窗口背景色
 2 
 3 setStyleSheet(QStringLiteral("background:blue;"));//背景色
 4 
 5 ​setFixedHeight(30);//设置高度 看个人喜好 可以做微调​
 6 
 7 _p->minimize = new QToolButton(this);
 8 
 9 _p->maximize = new QToolButton(this);
10 
11 _p->close = new QToolButton(this);
View Code

/// 设置系统按钮图标.

  1 QPixmap pix = style()->standardPixmap(QStyle::SP_TitleBarCloseButton);
  2 
  3 _p->close->setIcon(pix);
  4 
  5 _p->maxPix = style()->standardPixmap(QStyle::SP_TitleBarMaxButton);
  6 
  7 _p->maximize->setIcon(_p->maxPix);
  8 
  9 pix = style()->standardPixmap(QStyle::SP_TitleBarMinButton);
 10 
 11 _p->minimize->setIcon(pix);
 12 
 13 _p->restorePix = style()->standardPixmap(QStyle::SP_TitleBarNormalButton);
 14 
 15 _p->minimize->setMinimumHeight(20);
 16 
 17 _p->close->setMinimumHeight(20);
 18 
 19 _p->maximize->setMinimumHeight(20);
 20 
 21 _p->label = new QLabel(this);
 22 
 23 _p->label->setAttribute(Qt::WA_TransparentForMouseEvents, true); //鼠标穿透
 24 
 25 _p->label->setStyleSheet(QStringLiteral("  font-size:12px;\\
 26 
 27     font - weight:Bold"));
 28 
 29     _p->label->setMargin(0);
 30 
 31 SetWindowTitle("title");
 32 
 33 QHBoxLayout *hbox = new QHBoxLayout;
 34 
 35 hbox->addWidget(_p->label);
 36 
 37 hbox->addWidget(_p->minimize);
 38 
 39 hbox->addWidget(_p->maximize);
 40 
 41 hbox->addWidget(_p->close);
 42 
 43 //_p->maximize->setVisible(false);
 44 
 45 hbox->insertStretch(1, 500);
 46 
 47 hbox->setSpacing(0);
 48 
 49 connect(_p->minimize, &QToolButton::clicked, this, [this]{
 50 
 51     BaseWidget * widget = qobject_cast(parent());
 52 
 53     if (widget)
 54 
 55     {
 56 
 57         widget->SetWindowMovePos(widget->pos());
 58 
 59         emit WindowDockedSignal();
 60 
 61     }
 62 
 63 });
 64 
 65 connect(_p->maximize, &QToolButton::clicked, this, &TitleBar::showMaxRestore);
 66 
 67 connect(_p->close, &QToolButton::clicked, this, [this]{emit WindowCloseSignal(_p->label->text()); });
 68 
 69 hbox->setMargin(1);
 70 
 71 hbox->setSpacing(2);
 72 
 73 setLayout(hbox);
 74 
 75void TitleBar::showMaxRestore()//最大化或者还原
 76 
 77 {
 78 
 79     if (_p->maxNormal)
 80 
 81     {
 82 
 83         _p->maxNormal = !_p->maxNormal;
 84 
 85         _p->maximize->setIcon(_p->maxPix);
 86 
 87     }
 88 
 89     else
 90 
 91     {
 92 
 93         _p->maxNormal = !_p->maxNormal;
 94 
 95         _p->maximize->setIcon(_p->restorePix);
 96 
 97     }
 98 
 99     emit WindowMaxRestoreSignal(_p->maxNormal);
100 
101 }
102 
103 void TitleBar::SetWindowTitle(const QString & title)//设置窗口标题
104 
105 {
106 
107     if (_p)
108 
109     {
110 
111         _p->label->setText(title);
112 
113     }
114 
115 }
116 
117 void TitleBar::SetWindowMaxable(bool isMax)
118 
119 {
120 
121     if (_p)
122 
123     {
124 
125         _p->maxNormal = isMax;
126 
127         if (_p->maxNormal)
128 
129         {
130 
131             _p->maximize->setIcon(_p->maxPix);
132 
133         }
134 
135         else
136 
137         {
138 
139             _p->maximize->setIcon(_p->restorePix);
140 
141         }
142 
143     }
144 
145 }
146 
147 void TitleBar::mousePressEvent(QMouseEvent * event)//移动窗口
148 
149 {
150 
151     QPoint mousePos = _p->minimize->mapFromParent(event->pos());
152 
153     if (_p->minimize->rect().contains(mousePos))//如果点击了最小化 则不能移动
154 
155     {
156 
157         return;
158 
159     }
160 
161     if (_p->maximize->rect().contains(mousePos))//如果点击了最大化不能移动
162 
163     {
164 
165         return;
166 
167     }
168 
169     _p->leftButtonPressed = true;
170 
171     _p->startPos = event->globalPos();
172 
173     _p->clickPos = mapToParent(event->pos());
174 
175 }
176 
177 void TitleBar::mouseReleaseEvent(QMouseEvent * event)
178 
179 {
180 
181     _p->leftButtonPressed = false;
182 
183 }
184 
185 void TitleBar::mouseMoveEvent(QMouseEvent * event)
186 
187 {
188 
189     if (_p->maxNormal)
190 
191     {
192 
193         return;
194 
195     }
196 
197     if (_p->leftButtonPressed)
198 
199     {
200 
201         parentWidget()->move(event->globalPos() - _p->clickPos);//移动父窗口
202 
203     }
204 
205 }
206 
207 void TitleBar::mouseDoubleClickEvent(QMouseEvent * event)
208 
209 {
210 
211     showMaxRestore();
212 
213 }
View Code

    窗体定制

    直接上代码

​   cpp如下​

  1 setFrameShape(Panel);
  2 
  3 setMouseTracking(true);
  4 
  5 setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Tool);/// 隐藏窗口标题栏.
  6 
  7 setFixedSize(150, 190);
  8 
  9 _p->m_mouse_down = false;
 10 
 11 _p->m_titleBar = new TitleBar(this);
 12 
 13 _p->m_titleBar->installEventFilter(this);
 14 
 15 connect(_p->m_titleBar, &TitleBar::WindowDockedSignal
 16 
 17 , this, [this]{
 18 
 19 setFixedSize(_p->m_content->size());
 20 
 21 setMinimumSize(0, 0);
 22 
 23 setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
 24 
 25 _p->m_titleBar->setVisible(false);
 26 
 27 });
 28 
 29 connect(_p->m_titleBar, &TitleBar::WindowMaxRestoreSignal
 30 
 31 , this, [this](bool isMax){
 32 
 33 if (isMax)
 34 
 35 {
 36 
 37 showMaximized();
 38 
 39 }
 40 
 41 else
 42 
 43 {
 44 
 45 showNormal();
 46 
 47 }
 48 
 49 });
 50 
 51 _p->m_content = new QWidget(this);
 52 
 53 QPalette plt = _p->m_content->palette();
 54 
 55 plt.setColor(QPalette::Window, QColor("#000000"));
 56 
 57 _p->m_content->setPalette(plt);//设置背景色黑色
 58 
 59 _p->m_content->setAutoFillBackground(true);
 60 
 61 _p->m_content->setAttribute(Qt::WA_PaintOnScreen, true);
 62 
 63 QVBoxLayout *vbox = new QVBoxLayout(this);
 64 
 65 vbox->addWidget(_p->m_titleBar);
 66 
 67 vbox->setStretchFactor(_p->m_titleBar, 0);
 68 
 69 vbox->setMargin(0);
 70 
 71 vbox->setSpacing(0);
 72 
 73 QVBoxLayout *layout = new QVBoxLayout(this);
 74 
 75 layout->addWidget(_p->m_content);
 76 
 77 layout->setMargin(0);
 78 
 79 layout->setSpacing(0);
 80 
 81 vbox->addLayout(layout);
 82 
 83 vbox->setStretchFactor(layout, 1);
 84 
 85 TitleBar * BaseWidget::GetTitleBar() const
 86 
 87 {
 88 
 89          if (_p)
 90 
 91          {
 92 
 93               return _p->m_titleBar;
 94 
 95           }
 96 
 97 }
 98 
 99 QWidget * BaseWidget::GetContentWidget() const
100 
101 {
102 
103      if (_p)
104 
105       {
106 
107             return _p->m_content;
108 
109        }
110 
111 }
112 
113 BaseWidget::State BaseWidget::GetWindowState() const
114 
115 {
116 
117     if (_p)
118 
119     {
120 
121           return _p->state;
122 
123      } 
124 
125 }
126 
127 void BaseWidget::SetWindowState(BaseWidget::State state)
128 
129 {
130 
131      if (_p)
132 
133       {
134 
135              _p->state = state;
136 
137              if (_p->state == _floating)
138 
139              {
140 
141                   _p->m_titleBar->setVisible(true);
142 
143                }
144 
145                else
146 
147               {
148 
149                      _p->m_titleBar->setVisible(false);
150 
151                }
152 
153        }
154 
155 }
156 
157 QPoint BaseWidget::GetWindowFloatPos() const
158 
159 {
160 
161     if (_p)
162 
163     {
164 
165           return _p->floatPostion;
166 
167     }  
168 
169 }
170 
171 void BaseWidget::SetWindowFloatPos(const QPoint & point)
172 
173 {
174 
175      if (_p)
176 
177      {
178 
179            _p->floatPostion = point;
180 
181      }
182 
183 }
184 
185 QPoint BaseWidget::GetWindowMovePos() const
186 
187 {
188 
189     if (_p)
190 
191     {
192 
193     return _p->m_restorePos;
194 
195     }
196 
197 }
198 
199 void BaseWidget::SetWindowMovePos(const QPoint & pos)
200 
201 {
202 
203     if (_p)
204 
205     {
206 
207           _p->m_restorePos = pos;
208 
209      }
210 
211 }
212 
213 bool BaseWidget::eventFilter(QObject * object, QEvent * event)
214 
215 {
216 
217 if (object == _p->m_titleBar)
218 
219 {
220 
221      if (event->type() == QEvent::MouseMove)
222 
223      {
224 
225         QMouseEvent * mouseEvent = static_cast(event);
226 
227         if (mouseEvent && mouseEvent->button() & Qt::LeftButton)
228 
229          {
230 
231                 return true;//不做处理
232 
233             }
234 
235         }
236 
237     }
238 
239      return QWidget::eventFilter(object, event);
240 
241 }
242 
243 void BaseWidget::mousePressEvent(QMouseEvent * event)
244 
245 {
246 
247      if (event->button() == Qt::LeftButton)
248 
249      {
250 
251         _p->m_mouse_down = true;
252 
253          _p->dragPostion = event->globalPos() - frameGeometry().topLeft();
254 
255          event->accept();
256 
257      }
258 
259 }
260 
261 void BaseWidget::mouseMoveEvent(QMouseEvent * event)
262 
263 {
264 
265     if (_p->state != _floating || isMaximized())//如果窗口不是悬浮状态 或者最大化 不允许拖动
266 
267     {
268 
269          return;
270 
271     }
272 
273     if (_p->m_mouse_down)
274 
275     {
276 
277         move(event->globalPos() - _p->dragPostion);
278 
279         event->accept();
280 
281     }
282 
283 }
284 
285 void BaseWidget::mouseReleaseEvent(QMouseEvent * event)
286 
287 {
288 
289     _p->m_mouse_down = false; 
290 
291 }
292 
293 void BaseWidget::mouseDoubleClickEvent(QMouseEvent * event)
294 
295 {
296 
297  if (_p->state == _dock)
298 
299  {
300 
301          _p->state = _floating;
302 
303          _p->m_titleBar->setVisible(true);
304 
305          setParent(nullptr);
306 
307          setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint |      Qt::Tool);
308 
309          move(GetWindowMovePos());
310 
311         show();
312 
313     }
314 
315 }
View Code

​    有如上两部分代码,功能基本可以实现

以上是关于Qt窗口定制的主要内容,如果未能解决你的问题,请参考以下文章

qt中如何去掉主窗口标题栏

qt去掉标题栏的窗口,最小化到任务栏后,怎么没有系统菜单?

c++ qt的标题栏可以自定义吗

Qt 4:移动没有标题栏的窗口

Qt - 拖动标题栏时防止窗口调整大小

如何在QT中实现自己的标题栏