1.最终效果展示

2.Qt默认的程序框架介绍
当我们用QtDesigner打开ui文件的时候,可以看到下图,下图是一个QMainWindow的框架,它包含了:菜单栏,工具栏,中心区域,状态栏
接下来,准备展示一下程序运行后的界面,但是为了让读者更容易看到每个区域的位置,我在MainWindow的构造函数中加了一丢丢代码:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//以下是作者添加的代码,分别向菜单栏、工具栏、状态栏添加了内容
QMenu *menu1 = new QMenu(tr("文件"));
menuBar()->addMenu(menu1);
QMenu *menu2 = new QMenu(tr("编辑"));
menuBar()->addMenu(menu2);
QToolButton *toolBtn1 = new QToolButton(this);
ui->mainToolBar->addWidget(toolBtn1);
QLabel *label = new QLabel(tr("2021-10-12 11:50"));
ui->statusBar->addWidget(label);
}
上面的代码运行之后,是这样的:
从上图可以清晰地找出菜单栏、工具栏、状态栏,而且我们能看到左上角有个程序的名称叫“MainWindow”,然后右上角有3个按钮,程序自带了黑色边框,边框外围有阴影。上述这些小部件都是Qt自动帮我们加上去的,只要你用的是QMainWindow,显示出来就会是这个样子。
上面这个界面可以看出,Qt默认的框架做出来的界面和商业化的桌面应用软件相比,可以说是很丑了。虽然Qt提供了样式表,也可以自绘,但是如果使用默认的框架,那依然有很多效果是无法实现的。以360安全卫士和HBuilder X为例,如果你想要用Qt默认的框架来实现下面这两个界面,可以说是很不好做了。
3.去掉默认的按钮和边框
从上一节的内容,可以看出Qt的默认框架有很大局限性,不利于我们实现很多炫酷漂亮的功能,那么应该怎么办呢?
- (1).去掉右上角三个按钮
- (2).去掉左上角标题
- (3).去掉边框和阴影
- (4).去掉菜单栏、工具栏、状态栏
- (5).自己实现上述去掉的所有部件
那么代码怎么写呢?
上面列出的(1)、(2)、(3)可以通过下面的代码实现
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowFlags(Qt::FramelessWindowHint);
}
第(4)点,需要去QtDesigner上删除,右键点击对应区域,选择删除即可。
上面的步骤执行完后,我们再来运行程序,将会是下面这个样子的:
4.实现可拖拽/可最大化/可最小化/可关闭功能
经过第3节中的步骤之后,我们现在看到的程序是没有关闭按钮的,也无法移动位置,这肯定不是我们想要的结果。接下来,我将说明如何逐一实现“可拖拽/可最大化/可最小化/可关闭功能”。
4.1 第1步:新建资源文件
4.2 第2步:添加图标到资源文件中
在工程目录下,新建一个Resources目录,然后在网上找4个图标,分别用于最小化,最大化,关闭按钮的背景图片,以及应用程序的右上角图标。
打开qrc文件
添加前缀
修改前缀
添加图片文件
选择图片
添加图片后的样子
至此,图标已添加完成,记得按下CTRL+S保存一下。
4.3 第3步:添加控件
双击ui文件,用Qt设计师打开后,拖动5个Widget控件到界面上,并调整好位置和大小,然后修改控件名称,下图中右侧列表是我建议的名称:
添加两个Label控件,分别用于显示应用程序图标和名称
添加3个按钮控件到右上角,分别用于最小化,最大化,关闭。
4.4 第4步:设置控件文字和背景
使用上面的方法为每个按钮都设置一下背景图片,变成下面这样:
这里由于图片的尺寸和按钮尺寸不吻合,导致被拉伸了,不好看,没关系,后面想办法处理。
4.5 第5步:实现用鼠标移动程序窗口的功能
头文件中增加如下代码:
protected:
void mouseMoveEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *);
private:
bool m_bMousePressed;
QPoint m_mousePoint;
QRect m_areaMovable;//可移动窗口的区域,鼠标只有在该区域按下才能移动窗口
cpp中增加如下代码:
void MainWindow::mouseMoveEvent(QMouseEvent *e)
{
if (m_bMousePressed && (e->buttons() && Qt::LeftButton)) {
this->move(e->globalPos() - m_mousePoint);
e->accept();
}
}
void MainWindow::mousePressEvent(QMouseEvent *e)
{
if (e->button() == Qt::LeftButton) {
if (m_areaMovable.contains(e->pos()))
{
m_bMousePressed = true;
m_mousePoint = e->globalPos() - this->pos();
}
e->accept();
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent *)
{
m_bMousePressed = false;
}
并在构造函数中初始化m_areaMovable的值,
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowFlags(Qt::FramelessWindowHint);
m_areaMovable = QRect(0,0,500,30);
}
然后运行一下程序,看看效果:
先切换到Release版本,不然图片显示不出来,
然后点击运行按钮
4.6 第6步:响应右上角按钮点击事件
在头文件中添加如下代码:
public slots:
void OnClickMinimizeBtn();
void OnClickMaximizeBtn();
void OnClickCloseBtn();
在cpp文件中添加如下代码:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
/*
....
....
*/
connect(ui->minimizeBtn,SIGNAL(clicked()),this,SLOT(OnClickMinimizeBtn()));
connect(ui->maximizeBtn,SIGNAL(clicked()),this,SLOT(OnClickMaximizeBtn()));
connect(ui->closeBtn,SIGNAL(clicked()),this,SLOT(OnClickCloseBtn()));
}
void MainWindow::OnClickMinimizeBtn()
{
showMinimized();
}
void MainWindow::OnClickMaximizeBtn()
{
showMaximized();
}
void MainWindow::OnClickCloseBtn()
{
close();
}
4.7 第7步:优化按钮图片显示效果
假如之前你添加的背景图片显示出来是正常的,那么这一节的内容可以不用看,我这里因为按钮尺寸是30*30,图片是16*16的,所以图片被拉伸了,显示出来后图片有点模糊。
下面说如何优化,我这里调整了一下margin的值:
加了这句:
margin:6px;
加了之后图片的显示空间被压缩了,就不会被拉伸得很明显。对3个图片按钮对作同样的处理,然后下面看效果:
下面看一下动画效果
到现在为止,我们实现了用鼠标移动窗口的功能,也实现了最小化、最大化、关闭按钮对应的功能,并且修改了应用程序图标,修改了按钮的样式。但是这还远远不够,比如说最大化按钮点击后,右上角的三个按钮跑到中间了,这肯定是不行的,还有标题栏、菜单栏、工具栏等全都是一个颜色,很丑。
想要了解如何解决上述问题,实现更加炫酷的效果,可以点一下左上角“关注”,右上角“订阅”,以免找不到我了,我将在后续的博客中一一讲述。