Qt漂亮界面

谁践踏了优雅 2022-09-12 05:41 498阅读 0赞

要做一个类似下面的qt界面,顶部是导航栏的样子——包含图标和程序名称,右边是界面切换按钮,然后放大、缩小和关闭按钮也在,还能拖动。这样,就更像一个商用的软件了。

在这里插入图片描述
功能规划:
1.去掉菜单栏、工具栏;
2.顶部导航栏包含程序图标、名称、界面切换按钮、放大缩小关闭按钮;
3.顶部导航栏可以拖动;
4.导航栏按钮可以切换界面。

可以参考的相关博客链接

文章目录

  • 一、去掉菜单栏和工具栏
  • 二、顶部导航栏的设计
  • 三、阵列按钮的点击事件写法
  • 四、重写缩写界面、放大界面和关闭程序事件
  • 五、鼠标事件的处理
  • 六、installEventFilter的使用

一、去掉菜单栏和工具栏

在UI设计界面,在menuBar和mainToolBar上右键,选择移除菜单栏和移除工具栏。
在这里插入图片描述
把顶部的图标和程序名称、放大缩小关闭按钮都去掉,使用如下语句。

  1. this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);

二、顶部导航栏的设计

主要是用installEventFilter来实现的。参考第6章节。
这个顶部导航栏是通过注册监听事件,让app监控所有的程序事件。如果属性是可移动的,然后记录鼠标的坐标等,来控制窗口的位置和大小。

appinit.h头文件

  1. #ifndef APPINIT_H
  2. #define APPINIT_H
  3. #include <QObject>
  4. class AppInit : public QObject
  5. {
  6. Q_OBJECT
  7. public:
  8. static AppInit *Instance();
  9. explicit AppInit(QObject *parent = 0);
  10. void start();
  11. protected:
  12. bool eventFilter(QObject *obj, QEvent *evt);
  13. private:
  14. static AppInit *self;
  15. signals:
  16. public slots:
  17. };
  18. #endif // APPINIT_H

appinit.cpp的文件

  1. #include "appinit.h"
  2. #include "qmutex.h"
  3. #include "qapplication.h"
  4. #include "qevent.h"
  5. #include "qwidget.h"
  6. AppInit *AppInit::self = 0;
  7. AppInit *AppInit::Instance()
  8. {
  9. if (!self) {
  10. QMutex mutex;
  11. QMutexLocker locker(&mutex);
  12. if (!self) {
  13. self = new AppInit;
  14. }
  15. }
  16. return self;
  17. }
  18. AppInit::AppInit(QObject *parent) : QObject(parent)
  19. {
  20. }
  21. bool AppInit::eventFilter(QObject *obj, QEvent *evt)
  22. {
  23. QWidget *w = (QWidget *)obj;
  24. //如果窗口w的属性“canMove"是假的,继续监听
  25. if (!w->property("canMove").toBool()) {
  26. return QObject::eventFilter(obj, evt);
  27. }
  28. //如果属性是可移动
  29. static QPoint mousePoint;
  30. static bool mousePressed = false;
  31. //获取鼠标事件
  32. QMouseEvent *event = static_cast<QMouseEvent *>(evt);
  33. if (event->type() == QEvent::MouseButtonPress) {
  34. //如果鼠标被按下,且是左键按下
  35. if (event->button() == Qt::LeftButton) {
  36. mousePressed = true;
  37. //记下当前坐标:全局坐标-窗口坐标
  38. mousePoint = event->globalPos() - w->pos();
  39. return true;
  40. }
  41. //如果鼠标松开
  42. } else if (event->type() == QEvent::MouseButtonRelease) {
  43. mousePressed = false;
  44. return true;
  45. //如果鼠标在移动
  46. } else if (event->type() == QEvent::MouseMove) {
  47. if (mousePressed && (event->buttons() && Qt::LeftButton)) {
  48. //移动当前窗口到某个位置
  49. w->move(event->globalPos() - mousePoint);
  50. return true;
  51. }
  52. }
  53. return QObject::eventFilter(obj, evt);
  54. }
  55. void AppInit::start()
  56. {
  57. qApp->installEventFilter(this);
  58. }

使用方式:

  1. //函数功能:让自定义的顶部导航栏可以拖动
  2. AppInit::Instance()->start();

三、阵列按钮的点击事件写法

当我们有一排按钮需要程序来添加点击事件时,如果一个个connect那么代码就太长了,connect需要写,它们的槽函数又要单独写,而这些按钮响应的事件处理又差不多。那么可以用如下的写法,立马让你成为QT中级程序员的感觉。
在这里插入图片描述
使用findChildren函数找到某个widget下所有的按钮,如下面代码所示。

  1. //设置顶部导航按钮
  2. QList<QToolButton *> tbtns = ui->widgetTop->findChildren<QToolButton *>();
  3. foreach (QToolButton *btn, tbtns) {
  4. btn->setIconSize(icoSize);
  5. btn->setMinimumWidth(icoWidth);
  6. btn->setCheckable(true);
  7. connect(btn, SIGNAL(clicked()), this, SLOT(buttonClick()));
  8. }

首先,findChildren函数找到了widgetTop下的所有QToolButton类型按钮。
然后,给每一个按钮设置图标尺寸,宽度和可选择属性,然后连接connect到buttonClick()槽函数。
槽函数代码如下:

  1. void UIDemo01::buttonClick()
  2. {
  3. QToolButton *b = (QToolButton *)sender();
  4. //获取当前点击事件按钮的名称
  5. QString name = b->text();
  6. QList<QToolButton *> tbtns = ui->widgetTop->findChildren<QToolButton *>();
  7. foreach (QToolButton *btn, tbtns) {
  8. if (btn == b) {
  9. //如果是当前点击事件的按钮,将其设为选中状态
  10. btn->setChecked(true);
  11. } else {
  12. //如果不是当前点击事件的按钮,将其设为未选中状态
  13. btn->setChecked(false);
  14. }
  15. }
  16. if (name == "主界面") {
  17. ui->stackedWidget->setCurrentIndex(0);
  18. } else if (name == "系统设置") {
  19. ui->stackedWidget->setCurrentIndex(1);
  20. } else if (name == "警情查询") {
  21. ui->stackedWidget->setCurrentIndex(2);
  22. } else if (name == "调试帮助") {
  23. ui->stackedWidget->setCurrentIndex(3);
  24. } else if (name == "用户退出") {
  25. //退出程序
  26. exit(0);
  27. }
  28. }

这个槽函数,首先使用sender()函数获得了发生点击事件的那个QToolButton类型按钮的句柄。
然后,将其设为选中状态,将其他的按钮设为未选中状态;
最后,根据按钮的名称来选择跳转到的主界面。

四、重写缩写界面、放大界面和关闭程序事件

首先,在.h文件中注册这些函数

  1. private slots:
  2. void on_btnMenu_Min_clicked();
  3. void on_btnMenu_Max_clicked();
  4. void on_btnMenu_Close_clicked();

然后,直接重写这些函数即可。

  1. void UIDemo01::on_btnMenu_Min_clicked()
  2. {
  3. //qt自带函数
  4. showMinimized();
  5. }
  6. void UIDemo01::on_btnMenu_Max_clicked()
  7. {
  8. //静态定义变量,只在第一次使用
  9. static bool max = false;
  10. //静态定义变量获得尺寸
  11. static QRect location = this->geometry();
  12. //记忆放大前的窗口尺寸,方便取消最大化时返回原位置和大小
  13. if (max) {
  14. this->setGeometry(location);
  15. } else {
  16. //保存当前的窗口尺寸
  17. location = this->geometry();
  18. //设置界面可达的最大尺寸
  19. this->setGeometry(qApp->desktop()->availableGeometry());
  20. }
  21. //最大化就不能移动了
  22. this->setProperty("canMove", max);
  23. max = !max;
  24. }
  25. void UIDemo01::on_btnMenu_Close_clicked()
  26. {
  27. //qt自带函数
  28. close();
  29. }

五、鼠标事件的处理

有时我们需要捕获某个控件上的鼠标事件,比如这个界面在导航栏双击可以最大化和取消最大化。
首先,在.h文件中注册bool eventFilter(QObject *watched, QEvent *event);函数

  1. protected:
  2. bool eventFilter(QObject *watched, QEvent *event);

然后,给需要捕获鼠标事件的控件添加鼠标事件注册

  1. ui->widgetTitle->installEventFilter(this);//顶部导航栏注册鼠标事件

最后,在鼠标事件中编写处理程序

  1. bool UIDemo01::eventFilter(QObject *watched, QEvent *event)
  2. {
  3. //如果是鼠标双击事件
  4. if (event->type() == QEvent::MouseButtonDblClick) {
  5. //如果发生的控件是 ui->widgetTitle
  6. if (watched == ui->widgetTitle) {
  7. //调用发生最大化的函数
  8. on_btnMenu_Max_clicked();
  9. return true;
  10. }
  11. }
  12. //我们处理了点击事件,把事件返回到上层,让它们继续处理其他事件
  13. return QWidget::eventFilter(watched, event);
  14. }

六、installEventFilter的使用

installEventFilter的使用参考
简述:
事件过滤器,可以实现一个QObject监视另一个QObject的所有事件,但是两个QObject必须在同一个线程内

使用:
被监视者(ui->widge)安装事件过滤器

  1. ui->widget->installEventFilter(this);

在监视者(this)里重新实现eventFilter()函数,此函数返回false时,表示监视者(this)不过滤此事件,事件将会继续发送到被监视者(ui->widge);返回true时表示监视者过滤此事件,事件将不会发送到被监视者

  1. bool CustomerSwitchet::eventFilter(QObject *obj,QEvent *e)
  2. {
  3. QWidget*wid = qobject_cast<QWidget*>(obj);
  4. if(wid==ui->widget)
  5. {
  6. //根据事件类型,写处理逻辑
  7. qDebug()<<"widget";
  8. }
  9. return false;
  10. }

发表评论

表情:
评论列表 (有 0 条评论,498人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Qt:用户界面

    Qt框架的主要用户界面技术是Qt快速控制和Qt小部件。Qt快速控制界面是流动的,动态的,最好的触摸界面。Qt小部件用于创建复杂的桌面应用程序。您可以创建带有目标平台原生外观的Q

    相关 Qt漂亮界面

    > 要做一个类似下面的qt界面,顶部是导航栏的样子——包含图标和程序名称,右边是界面切换按钮,然后放大、缩小和关闭按钮也在,还能拖动。这样,就更像一个商用的软件了。 ![在这

    相关 Qt界面开发(三)

    这次要给大家分享一些我在github和qtcn(主要是liudianwu大神,Qt界面开发(一)有很多都是他的作品)上找到的比较漂亮且实用Qt界面和控件集合。 \------