界面编程之QT窗口系统20180726

时间:2022-09-19 08:55:43

/*******************************************************************************************/

一、坐标系统

坐标系统相对于对于父窗口而言(最外层的父窗口就是屏幕了,也可以说外面没有窗口了,这时就是相对整个电脑屏幕而言了)

原点:就是左上角

x: 往右递增

y: 往下递增

具体见图1:

界面编程之QT窗口系统20180726

具体示例:

/* 对于主窗口,坐标系统相对于屏幕

* 原点:相对于屏幕左上角

* x: 往右递增

* y: 往下递增

*/

move(100, 100);

/* 子窗口,坐标系统相对于父窗口

* 原点:相对于窗口空白区域左上角(不包括边框)

* x: 往右递增

* y: 往下递增

*/

QPushButton *b1 = new QPushButton(this);

b1->move(100, 100);

b1->setText("^_^");

b1->resize(200, 100);//设置大小

QPushButton *b2 = new QPushButton(b1);

b2->move(10, 10);

b2->setText("@_@");

/*******************************************************************************************/

二、内存回收机制及qt对象模型

只要创建对象的时候指定了父对象,就会形成一个对象树(我们创建的这个QObject对象会自动添加到其父对象的children()列表),

当程序结束的时候,qt就会自动的从对象树叶子节点向根节点进行对象的释放(当父对象析构的时候,这个列表中的所有对象也会被析构。注意,这里的父对象并不是继承意义上的父类)。

验证这个结论可以在对象的析构函数中加打印信息。

所以在qt中new了对象并指定了父对象就不需要delete了,注意QWidget的父对象是QObject。QObject是对象树的根(当然,我们也可以自己删除子对象,

它们会自动从其父对象的children()列表中删除。比如,当我们删除了一个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,并且自动调整屏幕显示)

// : QPushButton(parent) ,表示给基类QPushButton构造函数传参

MyButton::MyButton(QWidget *parent) : QPushButton(parent)

{

}

MyButton *b3 = new MyButton(this);

b3->setText("123");

//自动释放的前提条件:1)指定父对象后  2)直接或间接继承于QObject

//子对象如果是动态分配空间的new,不需要手动释放delete

//系统会自动释放,自动回收

注意,所有窗口及窗口控件都是从QWidget直接或间接派生出来的。

注意,

如果QObject在栈上创建,Qt 保持同样的行为。正常情况下,这也不会发生什么问题。来看下下面的代码片段:

{

QWidget window;

QPushButton quit("Quit", &window);

}

作为父组件的 window 和作为子组件的 quit 都是QObject的子类(事实上,它们都是QWidget的子类,而QWidget是QObject的子类)。

这段代码是正确的,quit 的析构函数不会被调用两次,因为标准 C++要求,局部对象的析构顺序应该按照其创建顺序的相反过程。

因此,这段代码在超出作用域时,会先调用 quit 的析构函数,将其从父对象 window 的子对象列表中删除,然后才会再调用 window 的析构函数。

但是,如果我们使用下面的代码:

{

QPushButton quit("Quit");

QWidget window;

quit.setParent(&window);

}

情况又有所不同,析构顺序就有了问题。我们看到,在上面的代码中,作为父对象的 window 会首先被析构,因为它是最后一个创建的对象。

在析构过程中,它会调用子对象列表中每一个对象的析构函数,也就是说, quit 此时就被析构了。

然后,代码继续执行,在 window 析构之后,quit 也会被析构,因为 quit 也是一个局部变量,在超出作用域的时候当然也需要析构。

但是,这时候已经是第二次调用 quit 的析构函数了,C++ 不允许调用两次析构函数,因此,程序崩溃了。

由此我们看到,Qt 的对象树机制虽然帮助我们在一定程度上解决了内存问题,但是也引入了一些值得注意的事情。

这些细节在今后的开发过程中很可能时不时跳出来烦扰一下,所以,我们最好从开始就养成良好习惯,在 Qt 中,尽量在构造的时候就指定 parent 对象,并且大胆在堆上创建。

/*******************************************************************************************/

三、菜单栏_工具栏_状态栏

1.QMainWindow

QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个锚接部件(dock widgets)、

一个状态栏(status bar)及一个中心部件(central widget),是许多应用程序的基础,如文本编辑器,图片编辑器等,具体见图2:

界面编程之QT窗口系统20180726

2.菜单栏

一个主窗口最多只有一个菜单栏。位于主窗口顶部、主窗口标题栏下面。

带菜单栏的窗口在创建项目的时候选择继承的基类是QMainWindow(一般pc端用的最多)

#include <QMenuBar>//菜单栏

#include <QMenu>//菜单栏

#include <QAction>//菜单项

#include <QDebug>

#include <QToolBar>//工具栏

#include <QPushButton>

#include <QStatusBar>//状态栏

#include <QLabel>

#include <QTextEdit>//文本编辑区

#include <QDockWidget>//浮动窗口

//菜单栏

QMenuBar *mBar = menuBar();//添加菜单栏,菜单栏里还没有东西,mBar用于添加菜单

//添加菜单

QMenu *pFile = mBar->addMenu("文件");//pFile用于添加菜单项

//添加菜单项,也叫添加动作

QAction *pNew = pFile->addAction("新建");//动作pNew里面有信号。QAction::triggered表示点击新建后发出的信号

connect(pNew, &QAction::triggered,

[=]()

{

qDebug() << "新建被按下";

}

);

pFile->addSeparator(); //添加分割线·

QAction *pOpen = pFile->addAction("打开");

2.工具栏

主窗口的工具栏上可以有多个工具条,通常采用一个菜单对应一个工具条的的方式,也可根据需要进行工具条的划分。

//工具栏,其实是菜单项的快捷方式

QToolBar *toolBar = addToolBar("toolBar");//添加工具栏,工具栏里还没有东西

//工具栏添加快捷键(工具栏里添加内容)

toolBar->addAction(pNew);

QPushButton *b = new QPushButton(this);

b->setText("^_^");

//工具栏添加小控件(按钮)

toolBar->addWidget(b);

connect(b, &QPushButton::clicked,

[=]()

{

b->setText("123");

}

);

3.状态栏

//状态栏,一般是窗口的最下面,用来显示状态的

QStatusBar *sBar = statusBar();//添加状态栏

QLabel *label = new QLabel(this);//标签控件用于显示内容

label->setText("Normal text file");

sBar->addWidget(label);//状态栏使用标签来显示内容

//addWidget 从左往右添加状态项,状态栏中的状态项不断增加,各个状态项之间有分割符,它们互相独立,分别表示不同内容的状态

sBar->addWidget(new QLabel("2", this));

// addPermanentWidget 从右往左添加

sBar->addPermanentWidget(new QLabel("3", this));

4.核心控件

//核心控件(文本编辑区)

QTextEdit *textEdit = new QTextEdit(this);//创建控件

setCentralWidget(textEdit);//添加核心控件(文本编辑区)

5.浮动窗口

//浮动窗口

QDockWidget *dock = new QDockWidget(this);//创建控件

addDockWidget(Qt::RightDockWidgetArea, dock);//添加浮动窗口,Qt::RightDockWidgetAre是枚举类型,表示浮动窗口放的位置(右边)

//给浮动窗口添加控件

QTextEdit *textEdit1 = new QTextEdit(this);

dock->setWidget(textEdit1);

6.具体见《QMainWindow》

 #ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QMainWindow> class MainWindow : public QMainWindow
{
Q_OBJECT public:
MainWindow(QWidget *parent = );
~MainWindow();
}; #endif // MAINWINDOW_H

mainwindow.h

 #include "mainwindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QDebug>
#include <QToolBar>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <QTextEdit>
#include <QDockWidget> MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//菜单栏
QMenuBar *mBar = menuBar(); //添加菜单
QMenu *pFile = mBar->addMenu("文件"); //添加菜单项,添加动作
QAction *pNew = pFile->addAction("新建"); connect(pNew, &QAction::triggered, [=]()
{
qDebug() << "新建被按下";
} );
pFile->addSeparator(); //添加分割线·
QAction *pOpen = pFile->addAction("打开"); //工具栏,菜单项的快捷方式
QToolBar *toolBar = addToolBar("toolBar"); //工具栏添加快捷键
toolBar->addAction(pNew); QPushButton *b = new QPushButton(this);
b->setText("^_^");
//添加小控件
toolBar->addWidget(b); connect(b, &QPushButton::clicked,
[=]()
{
b->setText("");
}
); //状态栏
QStatusBar *sBar = statusBar();
QLabel *label = new QLabel(this);
label->setText("Normal text file");
sBar->addWidget(label);
//addWidget 从左往右添加
sBar->addWidget(new QLabel("", this)); // addPermanentWidget 从右往左添加
sBar->addPermanentWidget(new QLabel("", this)); //核心控件
QTextEdit *textEdit = new QTextEdit(this);
setCentralWidget(textEdit); //浮动窗口
QDockWidget *dock = new QDockWidget(this);
addDockWidget(Qt::RightDockWidgetArea, dock); //给浮动窗口添加控件
QTextEdit *textEdit1 = new QTextEdit(this);
dock->setWidget(textEdit1);
} MainWindow::~MainWindow()
{ }

mainwindow.cpp

/*******************************************************************************************/

四、资源文件

1.介绍

Qt 资源系统是一个跨平台的资源机制,用于将程序运行时所需要的资源以二进制的形式存储于可执行文件内部。

如果你的程序需要加载特定的资源(图标、文本翻译等),那么,将其放置在资源文件中,就再也不需要担心这些文件的丢失。

也就是说,如果你将资源以资源文件形式存储,它是会编译到可执行文件内部。

2.使用

1).使用 Qt Creator 可以很方便地创建资源文件。我们可以在工程上点右键,选择“添加新文件…”,可以在 Qt 分类下找到“Qt 资源文件”,见图3:

界面编程之QT窗口系统20180726

2).点击“选择…”按钮,打开“新建 Qt 资源文件”对话框。在这里我们输入资源文件的名字和路径,见图4:

界面编程之QT窗口系统20180726

3).点击下一步,选择所需要的版本控制系统,然后直接选择完成。我们可以在 Qt Creator 的左侧文件列表中看到“资源文件”一项,

也就是我们新创建的资源文件,见图5:

界面编程之QT窗口系统20180726

4).右侧的编辑区有个“添加”,我们首先需要添加前缀,比如我们将前缀取名为 images。然后选中这个前缀,继续点击添加文件,

可以找到我们所需添加的文件。这里,我们选择 document-open.png 文件。当我们完成操作之后,Qt Creator 应该是这样子的,见图6:

界面编程之QT窗口系统20180726

5).接下来,我们还可以添加另外的前缀或者另外的文件。这取决于你的需要。当我们添加完成之后,我们可以像前面一章讲解的那样,

通过使用 : 开头的路径来找到这个文件。比如,我们的前缀是 /images,文件是 document-open.png,

那么就可以使用:/images/document-open.png找到这个文件。这么做带来的一个问题是,如果以后我们要更改文件名,比如将 docuemnt-open.png 改成 docopen.png,

那么,所有使用了这个名字的路径都需要修改。所以,更好的办法是,我们给这个文件去一个“别名”,以后就以这个别名来引用这个文件。

具体做法是,选中这个文件,添加别名信息,见图7:

界面编程之QT窗口系统20180726

这样,我们可以直接使用:/images/doc-open引用到这个资源,无需关心图片的真实文件名。

如果我们使用文本编辑器打开 res.qrc 文件,就会看到一下内容:

<RCC>

<qresource prefix="/images">

<file alias="doc-open">document-open.png</file>

</qresource>

<qresource prefix="/images/fr" lang="fr">

<file alias="doc-open">document-open-fr.png</file>

</qresource>

</RCC>

我们可以对比一下,看看 Qt Creator 帮我们生成的是怎样的 qrc 文件。当我们编译工程之后,

我们可以在构建目录中找到 qrc_res.cpp 文件,这就是 Qt 将我们的资源编译成了 C++ 代码。

/*******************************************************************************************/

五、模态和非模态对话框

对话框是 GUI 程序中不可或缺的组成部分。很多不能或者不适合放入主窗口的功能组件都必须放在对话框中设置。

对话框通常会是一个顶层窗口,出现在程序最上层,用于实现短期任务或者简洁的用户交互,对话框分为模态对话框和非模态对话框:

模态对话框只能操作当前的对话框,后面的东西(界面)没法操作。同理非模态的就可以可以操作的

模态与非模态的实现:

使用QDialog::exec()实现应用程序级别的模态对话框

使用QDialog::open()实现窗口级别的模态对话框

使用QDialog::show()实现非模态对话框。

#include <QDialog>//对话框

#include <QDebug>

#include <QMessageBox>

#include <QFileDialog>

QMenuBar *mBar = menuBar();

setMenuBar(mBar);

QMenu *menu = mBar->addMenu("对话框");

QAction *p1 = menu->addAction("模态对话框");

connect(p1, &QAction::triggered,

[=]()

{

QDialog dlg;

dlg.exec();//调出对话框,并且一直等在这里(阻塞),等事件(等用户操作)

qDebug() << "111111";

}

);

QAction *p2 = menu->addAction("非模态对话框");

connect(p2, &QAction::triggered,

[=]()

{

//           dlg.show();//非阻塞,注意这个dlg不能使用局部变量,因为非阻塞所以局部变量会释放掉就没了

//           qDebug() << "111111";//使用动态分配或者成员变量都可以

//           QDialog *p = new QDialog(this);//这种方式也可以,但是程序结束才释放,意味着一直点击,内存就越来越少

//           p->show();

QDialog *p = new QDialog;//所以不指定父对象,那么释放的方式是:通过设置属性

p->setAttribute(Qt::WA_DeleteOnClose);//设置属性为关闭的时候释放(Qt::WA_DeleteOnClose 枚举类型)

p->show();

}

);

/*******************************************************************************************/

六、标准对话框

前面两种创建的对话框仅仅就只是一个对话,没有按钮之类的。标准对话框:有按钮的对话框

所谓标准对话框,是 Qt 内置的一系列对话框,用于简化开发。事实上,有很多对话框都是通用的,

比如打开文件、设置颜色、打印设置等。这些对话框在所有程序中几乎相同,因此没有必要在每一个程序中都自己实现这么一个对话框。

Qt 的内置对话框大致分为以下几类:

QColorDialog:                          选择颜色;

QFileDialog:                     选择文件或者目录;

QFontDialog:                            选择字体;

QInputDialog:                          允许用户输入一个值,并将其值返回;

QMessageBox:                        模态对话框,用于显示信息、询问问题等;

QPageSetupDialog:                为打印机提供纸张相关的选项;

QPrintDialog:                           打印机配置;

QPrintPreviewDialog:   打印预览;

QProgressDialog:          显示操作过程。

1.消息对话框

#include <QMessageBox>//消息对话框

QAction *p3 = menu->addAction("关于对话框");

connect(p3, &QAction::triggered,

[=]()

{

QMessageBox::about(this, "about", "关于qt");//会产生一个有ok按钮的对话框

}

);

QAction *p4 = menu->addAction("问题对话框");

connect(p4, &QAction::triggered,

[=]()

{

//QMessageBox::question(this,"question", "Are you ok?");//默认是yes,no两个按钮

int ret = QMessageBox::question(this,//返回值为用户选中哪一个按钮的值(枚举)

"question", "Are you ok?",

QMessageBox::Ok |QMessageBox::Cancel

);//MessageBox::Ok |QMessageBox::Cancel指定按钮为ok和cancel两个按钮

switch(ret)

{

case QMessageBox::Ok:

qDebug() << "i am ok";

break;

case QMessageBox::Cancel:

qDebug() << "i am bad";

break;

default:

break;

}

}

);

2.文件对话框

文件对话框:显示一个让用户选择文件的对话框

#include <QFileDialog>//文件对话框

QAction *p5 = menu->addAction("文件对话框");

connect(p5, &QAction::triggered,

[=]()

{

QString path = QFileDialog::getOpenFileName(

this,

"open",

"../",

"souce(*.cpp *.h);;Text(*.txt);;all(*.*)"//没有这个参数则无法规定用户选择文件的格式,

);//"../"表示让用户选择文件的路径,也就是一打开显示的界面

qDebug() << path;//获取用户选择的文件,返回的是用户选择的文件的完整路径

}

);

button->setGeometry();//设置按钮的位置以及按钮的大小

信号与槽具体见图8,9

界面编程之QT窗口系统20180726

界面编程之QT窗口系统20180726

/*******************************************************************************************/

七、设计器的使用

从现在开始创建项目的时候,ui那个勾选框就要勾选上了。

勾选上项目中就会生成一个界面文件。

双击.ui界面文件就会自动的切换到设计器。

设计器作用:方便我们通过界面文件来设定窗口。

设计器里面也有信号与槽(这里添加的都只能用系统定义好的),不过一般不在这里操作,一般是在代码里操作

ui->setupUi(this);//界面上的任何操作都是在这句话里完成的。ui代表ui界面的控件

ui->对象名;//这个对象名就是在设计器里面的控件

ui->myButton->setText("123");//修改设计器上已有的控件

/*******************************************************************************************/

八、常用控件

设计器左边的控件分类介绍:

Layouts                               //布局

Spacers                               //空格,也是用来布局

Buttons(常用)                            //按钮

Item Views                                 //数据和显示是分离的,比如其中的listview就是类似表格,可以用来放置数据库数据

Item Widgets                             //用来显示项目和子项目的形式的,一层一层类似树

Containers                                  //容器,容纳一些别的控件,用于布局的时候很方便

Input Widgets(常用)     //输入控件,比如输入文本

Dispaly Widgets(常用)   //显示控件,比如显示图片,显示文字

1.Containers //容器中有:

Tool Box //抽屉式容器,点击一个选项就会展开来

Tab Widget //标签式容器,选择点击相应的标签出现(切换到)相应的界面

Stacked Widget //栈容器,内部也可以包含很多页,但是里面没有点击,需要外部的按钮之类的实现切换

ui中可以直接对按钮等信号添加槽函数,右击按钮选择转到槽即可,就会自动的在选择的控件的类中添加槽函数了,这个槽函数

在信号发出的时候会自动调用,无需connect,只需要在函数内部填上自己需要的逻辑就可以了。

void MainWindow::on_change_clicked()

{//自动添加的槽函数

static int i = 0;

ui->stackedWidget->setCurrentIndex( ++i % 4 );//点击后不断切换栈容器里面的页面,

}

Frame //带边框的容器,常用于布局

Widget //不带边框的容器,把窗口划分出若*分方便布局,常用于布局

MDI Araa //文档分栏显示

Dock Widget //浮窗

QAxWidget  //只能在win下使用,不常用

2.Input Widgets(常用)  //输入控件中有:

Conmbo Box //有选项,有下拉框

Font Conmbo Box //字体选择下拉框

Line Edit //行编辑,只能写一行,很常用,具体使用见讲义,注意这个可以做出输入有提示的效果

//QLineEdit

QString str = ui->lineEdit->text(); //获取内容

qDebug() << str;

//设置内容

ui->lineEdit->setText("12345678");

//设置内容显示间隙

ui->lineEdit->setTextMargins(15, 0, 0, 0);//输入内容的位置距离边框上下左右的距离(unit:px)

//设置内容显示方式

//ui->lineEdit->setEchoMode(QLineEdit::Password);//设置为密码的显示样式

//设置输入提示

QStringList list;//字符串列表

list << "hello" << "How are you" << "hehe";

QCompleter *com = new QCompleter(list, this);//构建模型

com->setCaseSensitivity(Qt::CaseInsensitive);//设置模型忽略大小写

ui->lineEdit->setCompleter(com);//设置输入模型

Text Edit //文本编辑区,可以多行,可以显示图片,或者网页内容都是可以的

Plain Text Edit //文本编辑区,可以多行,只能显示文字

Spin Box //微调整型数据,会有上下按钮,点击后数据会加或减

Double Spin Box //微调Double型数据,会有上下按钮,点击后数据会加或减

Time Edit  //和Spin Box类似,只是调时间的

Date Edit  //和Spin Box类似,只是调日期的

Date/Time Edit  //和Spin Box类似,只是调时间和日期的

Dial //有个点在圈上转的模型

Horizontal Scroll Bar //单独的一个水平滚动条

Vertical Scroll Bar //单独的一个垂直滚动条

Horizontal Slider //水平滑块,比如调音量,调播放时间轴那种

Vertical Slider //垂直滑块,比如调音量,调播放时间轴那种

Key Sequence Edit //设置快捷方式使用

3.Dispaly Widgets(常用)  //显示控件中有:

Label//标签,可以显示文字,可以显示图片,可以显示动画,可以显示网址

//QLabel

ui->labelText->setText("^_^"); //设置文本内容

//设置图片

ui->labelImage->setPixmap(QPixmap("://image/LuffyQ.png"));//也可以在ui中的属性栏中直接添加

//让图片自动适应label大小

ui->labelImage->setScaledContents(true);

//创建动画对象

QMovie *myMovie = new QMovie("://image/mario.gif");

//设置动画

ui->labelGif->setMovie(myMovie);

//启动动画

myMovie->start();

ui->labelGif->setScaledContents(true);

//设置html(超链接)

ui->labelUrl->setText("<h1><a href=\"https://www.baidu.com\">百度一下</a></h1>");

ui->labelUrl->setOpenExternalLinks(true);//设置点击后可以跳转,如果不设置就需要自己来处理信号自己增加槽函数哈哈哈

Text Browser //文本浏览器,显示文本,比如qq聊天界面,显示双方消息的界面

Graphics View //绘图的时候用到

Calendar Widget //日历控件

LCD Number //数码管,可以显示整数,浮点型,字符串(只能a到f),也就是16进制

//数码管

ui->lcdNumber->display(123); //设置内容

Progress Bar //进度条

//进度条

ui->progressBar->setMinimum(0); //设置最小值

ui->progressBar->setMaximum(200);//设置最大值

ui->progressBar->setValue(100); //设置当前值

Horizontal Line //水平线,分割线

Vertical Line //垂直线,分割线

QDeclarative View //QML用到

QQuickWidget  //QML用到

QWebView       //网页显示的地方,用来显示网页

ui->webView_2->load(QUrl("http://www.baidu.com"));//需要加http,并且需要加上网页控件模块,也就是在项目文件中加上QT+=webkitWidgets

没有布局则缩放窗口,窗口内容不会跟着缩放。而布局后,缩放窗口,窗口中的内容也会跟着缩放。

3.Qt 提供了两种组件定位机制:绝对定位和布局定位(借助qt里面的布局管理器)。

绝对定位就是一种最原始的定位方法:给出这个组件的坐标和长宽值。

这样,Qt 就知道该把组件放在哪里以及如何设置组件的大小。但是这样做带来的一个问题是,如果用户改变了窗口大小,

比如点击最大化按钮或者使用鼠标拖动窗口边缘,采用绝对定位的组件是不会有任何响应的。这也很自然,因为你并没有告诉 Qt,

在窗口变化时,组件是否要更新自己以及如何更新。或者,还有更简单的方法:禁止用户改变窗口大小。但这总不是长远之计。

布局定位:你只要把组件放入某一种布局,布局由专门的布局管理器进行管理。当需要调整大小或者位置的时候,

Qt 使用对应的布局管理器进行调整。

布局定位完美的解决了使用绝对定位的缺陷。

4.Qt 提供的布局中以下三种是我们最常用的:

     QHBoxLayout:按照水平方向从左到右布局;

     QVBoxLayout:按照竖直方向从上到下布局;

     QGridLayout:在一个网格中进行布局,类似于 HTML 的 table,类似表格,需要先摆好大致位置

1).布局都是在ui设计器里面做的。布局一般都是先局部后全局

2).布局的时候常用到spacers(弹簧)控件

spacer分为水平和垂直,其实他们都是不可见的控件,也就是空格,只是用来占位置的,通过

占位置实现我们想要的布局。

同时在spacer对应控件的属性里,我们也可以修改其占用位置的大小。

3).两个文本显示区,可以来回拖动的那种效果,也是布局做的

4).存在(设置)布局后(包括水平,垂直,网格三种布局管理器),

则在属性里面有layout一栏,表示当前控件的布局属性,可以进行调整设置等。

注意这个调整还受限于属性中的Qwidget栏中的水平或垂直策略。

5).布局的时候经常用到容器(比如容器中的Widget)将内容分为多个模块,然后进行模块与模块之间的布局

对一个窗口进行布局,布局的是里面最外层的模块。

/*******************************************************************************************/

九、自定义控件

#include <QSpinBox>//数字条

#include <QSlider>//滑块

#include <QHBoxLayout>//水平布局

QSpinBox *spin = new QSpinBox(this);

QSlider *slider = new QSlider(Qt::Horizontal, this);//Horizontal指定滑块的方向(水平)

//把控件添加到布局中

QHBoxLayout *hLayout = new QHBoxLayout(this);//指定父对象,表示该布局从属于哪个控件中,也就是在哪个控件下

hLayout->addWidget(spin);

hLayout->addWidget(slider);

//setLayout(hLayout);//如果前面没有指定父对象,则需要这里设置

//把当前通过布局形成的新的控件添加到ui里面的方法:

//在ui中添加一个新控件的基类的控件(Qwidget),然后右击选择提升为,在里面填上新控件的类名,见图10,11

界面编程之QT窗口系统20180726

界面编程之QT窗口系统20180726

//然后全局包含打勾(方便再次添加该新的控件),点击添加再点提升就可以了。见图12

界面编程之QT窗口系统20180726

connect(spin, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),//强制类型转换(函数类型)

slider, &QSlider::setValue);

connect(slider,  &QSlider::valueChanged, spin, &QSpinBox::setValue);

/*******************************************************************************************/

十、qt样式表

Qt样式表的思想很大程度上是来自于HTML的层叠样式表css,通过调用Qwidget::setStyletSheet(QString)或者

Apllication::setStyleSheet(QString),就可以为一个独立的子部件,整个窗口,甚至是整个应用指定一个样式表。

Qt样式表与CSS的语法规则几乎完全相同。

Qt样式表选择器通常是一个类名,

具体见图13,14

界面编程之QT窗口系统20180726

界面编程之QT窗口系统20180726

this->setStyleSheet("QLabel{color:rgb(0, 255, 255);"//rgb表示通过红绿蓝配色

"background-color:red;"

"}");//表示整个控件(窗口)只要是QLabel的都是以这个为样式

ui->label->setStyleSheet("QLabel{color:rgb(0, 255, 255);"

"background-color:blue;"

"border-image:url(:/new/prefix1/image/Sunny.jpg);"//设置图片背景

"}");

前景与背景:

具体见图15

界面编程之QT窗口系统20180726

方箱模型(css 盒子):

具体见图16

界面编程之QT窗口系统20180726

创建可缩放样式:

ui->label->setStyleSheet("QLabel{color:rgb(0, 255, 255);"

"background-color:blue;"

"border-image:url(:/new/prefix1/image/Sunny.jpg);"//border-image图片自动适应控件大小,有图片背景色就不生效

"border-image:url(:/new/prefix1/image/Sunny.jpg); 4 4 4 4 stretch stretch}");

//4 4 4 4 stretch stretch表示四个方向裁剪4个像素后的进行缩放,比如控件向左缩放,则图片随之向左裁剪4个像素后的进行缩放。所以一般用的少

具体见图17,18

界面编程之QT窗口系统20180726

界面编程之QT窗口系统20180726

处理伪状态(css中也有对应的)

ui->pushButton->setStyleSheet("QPushButton{"

"border-image:url(:/new/prefix1/image/Sunny.jpg);"

"}"

"QPushButton:hover{"

"border-image:url(:/new/prefix1/image/up.png);"

"}"

"QPushButton:pressed{"

"border-image:url(:/new/prefix1/image/Luffy.png);"

"}"

);

具体见图19,20

界面编程之QT窗口系统20180726

界面编程之QT窗口系统20180726

使用子部件点故意微观样式

具体见图21

界面编程之QT窗口系统20180726