安装包下载地址
1、windows安装
msvc编译器模块需要安装Windows软件开发工具包。
MinGW是Windows平台使用GNU工具导入库的集合。
2、Linux环境安装
双击.run文件即可
安装常用的开发依赖
apt-get install g++
apt-get install make
apt-get install libgl1-mesa-dev #gui运行依赖库
3、visual studio中创建Qt项目以及配置
1、工具安装
a、工具->扩展和更新->联机右上角搜索qt,下载安装Qt Visual Studio Tools
b、下载离线安装
配置Qt编译器版本:
1、点击Qt VS Tools选项 -> Qt Versions, 再弹出的框中添加对应的编译器版本
比如:D:\Qt\Qt5.12.12\5.12.12\msvc2017_64\bin
visual studio中开发qt程序打开控制台:
右键项目 -> 属性 -> 链接器 -> 系统 -> 子系统 修改为控制台 然后保存
QT += core gui #项目依赖模块
# qt版本大于4才加入widgets模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
# app表示项目是exe应,lib表示是库
TEMPLATE = app
# 生成的可执行文件名称
TAEGET = “ceshi_demo”
# 使用C++11标准
CONFIG += c++11
# 设置头文件搜索路径
INCLUDEPATH += ../include
# $$PWD是pro的目录
INCLUDEPATH += $$PWD/../include
message("pwd = "$$PWD)
# 项目包含的源码
SOURCES += \
dialog.cpp \
main.cpp \
widget.cpp
# 项目包含的头文件
HEADERS += \
dialog.h \
widget.h
# 项目包含的窗体文件
FORMS += \
dialog.ui \
widget.ui
# 指定库引用路径和名称 -L库路径 -l库名
LIBS += -L"./lib" -ltest
#修改可执行文件/目标文件输出路径
DESTDIR += ../build
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
# 项目资源文件
RESOURCES += \
res.qrc
#debug和release环境判断
CONFIG(debug,debug|release){
TARGET = "ceshi_demo_debug"
} else {
TARGET = "ceshi_demo_relsease"
}
#跨平台编译配置 win32 linux macx unix
win32{
message("win32")
}
!win32{
message("!win")
}
win32|linux{
message("win32|linux")
}
# 查看编译器信息
message($$QMAKESPEC)
# 查看编译器包括那些 D:\Qt\Qt5.12.12\5.12.12\mingw73_32\mkspecs
# dll输出路径
DLLDESTDIR += "../bin"
# 设置可执行程序图标 demo.ico存放在pro相同目录
RC_ICONS = demo.ico
# OBJECTS_DIR 表示程序生成的中间临时文件的存放路径
# MOC_DIR moc命令生成的临时文件路径
# RCC_DIR 用来描述qt资源编译器输出文件路径
在中大型项目中用pri文件配置各个子项目的公共变量、公共编译选项、公共路径
# 用来在pro/pri中引入某pri文件 include空格()
include (../my.pri)
# 环境变量 $${环境变量}
#自定义变量
CUSTOM_PATH = "../../home"
1、编译pro生成makefile
2、jom或者make编译makefile
# 生成界面的源码
D:\Qt\Qt5.12.12\5.12.12\mingw73_32\bin\uic.exe widget.ui -o ui_widget.h
# 生成信号槽代码
D:\Qt\Qt5.12.12\5.12.12\mingw73_32\bin\moc.exe widget.h moc_widget.cpp
qmake -o makefile demo.pro
jom /f makefile.Debug #windows
make # linux/mac
QObject类是所有元对象系统的类的基类
在一个类的private部分声明Q_OBJECT宏,使得类可以使用元对象的特性如动态属性、信号与槽
Q_PROPERTY()宏可以定义属性
QObject ob;
// 设置动态属性
ob.setProperty("name", "zhansan");
// 获取属性值
ob.property("name")
顺序容器类:QList、QLinkedList、QVector、QStack、QQueue
QList数组列表
QLinkedList链式列表
QVector动态数组的功能,支持迭代器和下标访问
QStack类似堆栈先进后出
QQueue类似队列的先入先出
关联容器类:QMap、QMultiMap、QHash、QMultiHash、QSet
QMultiMap、QMultiHash支持一个键关联多个值
QSet是基于散列表的集合模板类,存储无顺序、查找速度快,内部用QHash实现
QMap存储基于键值对,存储按照key的顺序,不在乎顺序用QHash更快
QHash基于散列表来实现字典功能的模板类
类似windows的消息机制,信号函数只发送,不需要知道接受者,需要QObject来绑定。
原理:
1、绑定信号函数和槽函数
2、调用信号函数(将信号写入队列)
3、主线程从队列中获取信号,在信号线程中找到信号和槽关联的队列处理,调用槽函数
connect(sender, SIGNAL(signal), receiver, SLOT(slot));
1、一个信号可以连接多个槽
2、多个信号可以连接同一个槽
3、一个信号可以连接另外一个信号
4、信号与槽的参数个数需要一致,信号的参数不能少于槽的参数
5、信号与槽的类中需要加入Q_OBJECT
6、当信号发射时,与其关联的槽函数立即执行,当关联的槽函数执行完毕之后才能执行发射信号处后的代码
手动添加信号槽:
1、Q_OBJECT
2、手动创建信号signals
3、手动创建槽 public slots
1、所用用户界面对象的基类
2、窗口部件接收鼠标、键盘等事件
3、屏幕上绘制自己
4、父子关系有相对坐标
手动创建QWidget对象
QWidget w;
w.show(); //显示包含子窗口
w.hide(); // 隐藏包含子窗口
w.geometry(); // 获取窗口坐标大小
// 获取x.y.width.height
int x = w.x();
int y = w.y();
int width = w.width();
int height = w.height();
// 重新设置窗口大小、移动窗口位置
w.resize(300, 400);
w.move(0, 0);
// 设置窗口状态 WindowMinimized WindowFullScreen
setWindowState(Qt::WindowMaximized);
// 同setWindowState效果
showNormal();
showMinimized();
showMaximized();
showFullScreen();
// 去除界面边框和标题栏,无法缩放移动
//setWindowFlags(Qt::FramelessWindowHint);
// 标题栏保留,去除所有按钮
setWindowFlags(Qt::WindowTitleHint | Qt::CustomizeWindowHint);
QString中字符串是Unicode码,每一个字符是一个16位的QChar。所以处理中文没有问题。
// 1.字符串判空
QString str;
// QString str = nullptr;
str == ""
str.isNull()
str.isEmpty()
// 2.字符串拼接 =+ 、append()
str += " end";
// 3.格式化输出
QString str2 = QString("print %1 %2").arg("number = ").arg(45);
QString str3 = QString("格式化输出 %1, %2").arg(16, 0, 2).arg(255, 0, 16);
QString str;
str.sprintf("age is %d", 34);
// 4.数字转QString
QString num = QString::number(35);
// 5.字符串遍历
QString itstr = QString("hello, blob asfdfdasm fafasdfad");
// 方法一
for (QString::iterator itr = itstr.begin(); itr != itstr.end(); itr++) {
qDebug() << *itr;
}
// 方法二
for (int i = 0; i
Qt中文乱码问题:
1、默认字符集设置(默认UTF-8)
2、文件字符集格式vs qtcreator中设置,vs中默认是gbk的编码
3、字符集转换QStringLiteral
// qt creator中输出中文
QString str = "中文测试";
qDebug() << str;
// vscode中开发qt,输出中文
QString str1 = QStringLiteral("中文测试");
qDebug() << str1;
// vscode中开发qt,输出中文
// 1.头文件中设置编码方式
#pragma execution_character_set("UTF-8")
QString str = "中文测试";
qDebug() << str;
// 2.文件编码为GBK
const char* src = "元数据是中文GBK,多字节数据存入QString";
QString str1 = QString::fromLocal8Bit(src);
qDebug() << str1;
// 把QString转为gbk
std::cout << str1.toLocal8Bit().toStdString() << std::endl;
QString s = QStringLiteral("测试");
// win api调用QString作为参数
MessageBox(0, s.toStdWString().c_str(), L"标题", 0);
显示文字、换行、样式设置字体、颜色、背景色、显示图片、播放gif动画
换行直接输入\n
label = new QLabel(Widget);
label->setObjectName(QString::fromUtf8("label"));
label->setGeometry(QRect(190, 320, 251, 101));
// 设置样式表
label->setStyleSheet(QString::fromUtf8("font: 14pt \"Algerian\";color: rgb(119, 51, 255);"));
// 播放gif
QMovie *mov = new QMovie("test.gif");
label->setMovie(mov);
事件设置、快捷键、样式设置
click()/click(bool)/pressed()/released()
// 设置按钮快捷键
ui->pushButton->setShortcut(tr("Ctrl+x"));
// 设置样式
pushButton->setStyleSheet(QString::fromUtf8("background-color: rgb(255, 255, 0);color: rgb(42, 74, 255);border-radius:10px"));
// hover样式设置
pushButton->setStyleSheet(QString::fromUtf8("QPushButton::hover{background-color: rgb(0, 0, 0);}\n"
"QPushButton::!hover{background-color: rgb(255, 255, 0);color: rgb(42, 74, 255);border-radius:10px;}"));
QLineEdit *edit = new QLineEdit(this);
edit->setObjectName("edit");
// 占位文字
edit->setPlaceholderText(QString("中文测试2"));
edit->move(100, 30);
edit->resize(100, 80);
// 清除按钮
edit->setClearButtonEnabled(true);
edit->setMaxLength(10);
// 设置显示密码的显示模式
edit->setEchoMode(QLineEdit::Password);
edit->setStyleSheet(QString("color: rgb(170, 0, 0);border-raduis: 20px;"));
// 输入验证
//edit->setInputMask("00.00;_");
// 只读
//eiit->setReadOnly(true);
// 校验器
QDoubleValidator *validator = new QDoubleValidator();
validator->setRange(-100, 1000, 3);
edit->setValidator(validator);
// returnPressed 有效触发信号
connect(edit, SIGNAL(returnPressed()), this, SLOT(returnPressedTest()));
// 另外一个按钮事件里面获取相关数据
void Widget::on_pushButton_clicked()
{
QLineEdit *eiit = findChild("edit");
// 获取内容
qDebug() << eiit->text();
}
QObjectList list = this->children();
for (int i = 0; i < list.size(); i++) {
QObject* obj = list[i];
const QMetaObject* metaObject = obj->metaObject();
// 获取子元素类名
QString className = metaObject->className();
// 获取子元素objectName
qDebug() << obj->objectName();
qDebug() << className;
// 转化
if(className == "QPushButton") {
QPushButton *btn = qobject_cast(obj);
qDebug() << "找到了QPushButton text = " << btn->text();
}
}
//sizeHint推荐尺寸只能重载修改
//size() 不包含边框的窗口大小
//QSizePolicy::PolicyFlag
//GrowFlag 必要时可超过推荐
//ExpandFlag 尽可能的拓展
//ShrinkFlag 必要时可小于推荐
//IgnoreFlag 缺省大小被忽略
//QVBoxLayout
// 垂直布局
QVBoxLayout *layout = new QVBoxLayout(this);
// 设置距离边框的边距
layout->setContentsMargins(10,20,30,40);
// 设置元素之间的间距
layout->setSpacing(30);
QPushButton *btn = new QPushButton("btn1");
// 设置按钮size的策略 推荐的大小
btn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
layout->addWidget(btn);
QPushButton *btn2 = new QPushButton("btn2");
btn2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
layout->addWidget(btn2);
QPushButton *btn3 = new QPushButton("btn3");
// 忽略 大小尽量缩放
btn3->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
// 设置最大和最小值
btn3->setMaximumSize(300, 300);
btn3->setMinimumSize(50,50);
layout->addWidget(btn3);
// QGridLayout
QGridLayout *layout = new QGridLayout(this);
// 设置间距
layout->setVerticalSpacing(20);
layout->setHorizontalSpacing(10);
QPushButton *btn1 = new QPushButton("btn1");
layout->addWidget(btn1, 0, 0);
QPushButton *btn2 = new QPushButton("btn2");
layout->addWidget(btn2, 0, 1);
QPushButton *btn3 = new QPushButton("btn3");
layout->addWidget(btn3, 1, 0);
QPushButton *btn4 = new QPushButton("btn4");
layout->addWidget(btn4, 1, 1);
// QFormLayout
QFormLayout *layout = new QFormLayout(this);
layout->setVerticalSpacing(20);
layout->setHorizontalSpacing(10);
QLineEdit *account = new QLineEdit();
layout->addRow(QString("账号"), account);
QLineEdit *password = new QLineEdit();
layout->addRow(QString("密码"), password);
QHBoxLayout *hLayout = new QHBoxLayout();
layout->addRow(hLayout);
QPushButton *login = new QPushButton(QString("登录"));
hLayout->addWidget(login);
connect(login, SIGNAL(clicked()), this, SLOT(test()));
void Widget::test() {
qDebug() << "test";
QFormLayout *lay = qobject_cast(this->layout());
qDebug() << lay;
}
// 1
qDebug() << "state = " << state;
// 2
qDebug("message = %s", info);
// 3 自定义类输出到qDebug
// 4 将标准输出重定向为到文件qInstallMessageHandler()
QString res = ui->checkBox->text();
qDebug() << res;
ui->checkBox1->setText("text");
// 快捷键
ui->checkBox->setShortcut(tr("x"));
// 选中状态
ui->checkBox->isChecked();
// 同一父组件中的box单选
ui->checkBox->setAutoExclusive(true);
// QButtonGroup
QButtonGroup *group= new QButtonGroup(this);
// .ui 拖拽生成box1
// 加组后默认变单选
group->addButton(ui->box1);
group->addButton(ui->box2);
group->addButton(ui->box3);
// 单选变多选
group->setExclusive(false);
// 绑定信号
QObject::connect(group, SIGNAL(buttonClicked(QAbstractButton *)), this, SLOT(testClicked(QAbstractButton *)));
QButtonGroup *group= new QButtonGroup(this);
group->setObjectName("group");
QRadioButton *radio1 = new QRadioButton("QRadioButton1");
QRadioButton *radio2 = new QRadioButton("QRadioButton2");
QRadioButton *radio3 = new QRadioButton("QRadioButton3");
group->addButton(radio1);
group->addButton(radio2);
group->addButton(radio3);
QVBoxLayout *layout = new QVBoxLayout(this);
for (int i = 0; ibuttons().size() ; i++) {
layout->addWidget(group->buttons()[i]);
}
// 获取选中的radioButton
QButtonGroup *group = findChild("group");
QRadioButton *radio = (QRadioButton *)group->checkedButton();
qDebug() << radio->text();
属性编辑、图标大小、插入数据(字符串、图标、自定义数据)、读取数据、信号事件
// 自定义数据处理
struct CustomType
{
QString name;
};
Q_DECLARE_METATYPE(CustomType);
// 清空之前的item
ui->comboBox->clear();
ui->comboBox->addItem("item1");
ui->comboBox->addItem("item2");
// 添加带图标的item 图标在资源文件中
QIcon icon(":/tt/image/install_logo.png");
ui->comboBox->addItem(icon, "item_icon");
// 添加自定义数据item
CustomType type;
type.name = "zhansan";
QVariant ant;
ant.setValue(type);
ui->comboBox->addItem("custom_item", ant);
// 获取数据
QString res = ui->comboBox->itemText(0);
qDebug() << res;
// 获取自定义数据
QVariant ant = ui->comboBox->itemData(3);
CustomType type = ant.value();
qDebug() << type.name;
常用属性、信号事件、样式设计、重载鼠标自定义事件
// 滑动槽的样式
QSlider::groove {
border: 1px solid #999999;
height:28px;
background: rgba(155,155,155,200);
border-radius: 10px;
}
// 滑块的样式
QSlider::handle {
background: rgba(255,0,0,200);
border-radius: 10px;
width:20px;
margin: -10px 0;
}
// 剩余槽的样式
QSlider::add-page {
background: rgba(255, 0, 0, 10);
}
// 滑过的槽的样式
QSlider::sub-page {
background: rgba(0, 255, 0, 30);
}
QSlider重载鼠标事件:
1、界面设计器添加自定义CustomSlider类,提升控件
2、覆写mousePressEvent
3、计算鼠标位置
// customSlider.h
#ifndef CUSTOMSLIDER_H
#define CUSTOMSLIDER_H
#include
#include
class CustomSlider : public QSlider
{
public:
CustomSlider(QWidget *p = NULL);
virtual void mousePressEvent(QMouseEvent *ev);
};
#endif // CUSTOMSLIDER_H
// customSlider.cpp
#include "customslider.h"
#include
#include
CustomSlider::CustomSlider(QWidget *p): QSlider(p)
{
}
void CustomSlider::mousePressEvent(QMouseEvent *ev) {
qDebug() << ev->pos().x();
QSlider::mousePressEvent(ev);
// 百分比
double p = (double)ev->pos().x() / (double)width();
int val = p*(maximum() - minimum()) + minimum();
setValue(val);
}
基本属性、插入和获取选中内容、遍历和排序、在列表中显示其他控件
// 关闭 水平垂直滚动条
ui->listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui->listWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// 多选模式
//ui->listWidget->setSelectionMode(QAbstractItemView::MultiSelection);
// 设置方向
//ui->listWidget->setFlow(QListView::LeftToRight);
// 设置每一行的大小
//ui->listWidget->setGridSize(QSize(100, 50));
// 清除.ui中添加的数据
ui->listWidget->clear();
// 插入数据
QListWidgetItem *item = new QListWidgetItem("code insert");
ui->listWidget->addItem(item);
ui->listWidget->addItems({"item2","item 3", "item3"});
// 插入包含图标的item
QListWidgetItem *item_icon = new QListWidgetItem("icon item");
item_icon->setIcon(QIcon(":/tt/image/install_logo.png"));
ui->listWidget->addItem(item_icon);
// 遍历
for (int i = 0; i< ui->listWidget->count() ; i++) {
qDebug() << ui->listWidget->item(i)->text();
}
// 设置 双击为可编辑状态
ui->listWidget->setEditTriggers(QAbstractItemView::DoubleClicked);
for (int i = 0; i< ui->listWidget->count() ; i++) {
ui->listWidget->item(i)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
}
// 排序
ui->listWidget->sortItems(Qt::DescendingOrder);
// 添加其他控件
QLineEdit *edit = new QLineEdit("QLineEdit");
// item(0) 第一个组件替换为QLineEdit
ui->listWidget->setItemWidget(ui->listWidget->item(0), edit);
常用属性设置、设置水平/垂直标题、插入数据、获取选中数据、删除、信号
// 清空所有标题和内容
ui->tableWidget->setColumnCount(0);
ui->tableWidget->setRowCount(0);
ui->tableWidget->setColumnCount(4);
ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("header1"));
ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem());
ui->tableWidget->horizontalHeaderItem(1)->setText("header2");
ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("header3"));
ui->tableWidget->setHorizontalHeaderItem(3, new QTableWidgetItem("header4"));
// 设置 第0列 标题的宽度
ui->tableWidget->setColumnWidth(0, 200);
// 设置垂直标题
ui->tableWidget->setRowCount(3);
QStringList list = {"col1", "col2", "col3"};
ui->tableWidget->setVerticalHeaderLabels(list);
// 插入数据
ui->tableWidget->setItem(0,0, new QTableWidgetItem("col 0,0"));
ui->tableWidget->setItem(0,1, new QTableWidgetItem("col 0,1"));
ui->tableWidget->setItem(0,2, new QTableWidgetItem("col 0,2"));
ui->tableWidget->setItem(1,0, new QTableWidgetItem("col 1,0"));
ui->tableWidget->setItem(2,0, new QTableWidgetItem("col 2,0"));
// 结尾添加一行
int row = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(row);
ui->tableWidget->setItem(row, 0, new QTableWidgetItem("new row 4"));
// 开始添加一行
ui->tableWidget->insertRow(0);
ui->tableWidget->setItem(0, 0, new QTableWidgetItem("new row 0"));
// 插入图片
ui->tableWidget->setItem(0, 1, new QTableWidgetItem("new row 1 icon"));
ui->tableWidget->item(0, 1)->setIcon(QIcon(":/tt/image/install_logo.png"));
// 设置行高
ui->tableWidget->setRowHeight(0, 80);
// 设置图标显示大小
ui->tableWidget->setIconSize(QSize(ui->tableWidget->rowHeight(0), ui->tableWidget->rowHeight(0)));
// 插入widght 图片
QLabel *label = new QLabel();
QPixmap pix(":/tt/image/install_logo.png");
// 缩放图片
pix = pix.scaled(ui->tableWidget->columnWidth(0), ui->tableWidget->rowHeight(row));
label->setPixmap(pix);
ui->tableWidget->setCellWidget(row, 0, label);
// 如何获取选中的数据?
// 没有数据的item无法选择
auto items = ui->tableWidget->selectedItems();
for (int i = 0; i < items.size() ; i++ ) {
qDebug() << "row = " << items[i]->row() << " col = " << items[i]->column() << " text = " << items[i]->text();
}
// 选择模式器
QItemSelectionModel *mode = ui->tableWidget->selectionModel();
// 获取所有的选择索引
auto list = mode->selectedIndexes();
qDebug() << list;
样式:标题格式、间隔线、背景颜色间隔
// 标题样式
QHeaderView::section {
background-color: rgb(60, 193, 255);
color: white;
padding-left: 4px;
border: 1px solid #6c6c6c;
}
// 选中
QHeaderView::section:checked {
background-color: rgb(255, 170, 0);
}
// 悬停
QHeaderView::section:hover {
background-color: red;
}
常用属性、标题、内容插入、内容选择、拖动和删除、信号事件
// 清理.ui中生成的标题
ui->treeWidget->setHeaderItem(new QTreeWidgetItem());
// 清理数据
ui->treeWidget->clear();
ui->treeWidget->setColumnCount(3);
// 设置标题
ui->treeWidget->headerItem()->setText(0, "header1");
ui->treeWidget->headerItem()->setText(1, "header2");
ui->treeWidget->headerItem()->setText(2, "header3");
// 插入数据
// 从结尾处插入
ui->treeWidget->addTopLevelItem(new QTreeWidgetItem());
ui->treeWidget->topLevelItem(0)->setText(0, "tree node col1");
ui->treeWidget->topLevelItem(0)->setText(1, "tree node col2");
ui->treeWidget->addTopLevelItem(new QTreeWidgetItem({"tree row1 col1", "tree row1 col2"}));
// 开头插入
ui->treeWidget->insertTopLevelItem(0, new QTreeWidgetItem({"tree row0 col1", "tree row0 col2"}));
// 结尾插入
ui->treeWidget->insertTopLevelItem(ui->treeWidget->topLevelItemCount(), new QTreeWidgetItem({"tree end col1"}));
// 结尾插入
QTreeWidgetItem *node = new QTreeWidgetItem(ui->treeWidget);
node->setText(0, "new end col1");
// 插入子节点
ui->treeWidget->topLevelItem(0)->addChild(new QTreeWidgetItem({"child1"}));
ui->treeWidget->topLevelItem(0)->addChild(new QTreeWidgetItem({"child2"}));
ui->treeWidget->topLevelItem(0)->addChild(new QTreeWidgetItem({"child3"}));
ui->treeWidget->topLevelItem(1)->addChild(new QTreeWidgetItem({"2 - child1"}));
ui->treeWidget->topLevelItem(1)->addChild(new QTreeWidgetItem({"2 - child2"}));
// 插入孙节点
ui->treeWidget->topLevelItem(0)->child(1)->addChild(new QTreeWidgetItem({"grandSon"}));
// 设置图标
ui->treeWidget->setIconSize(QSize(50, 50));
ui->treeWidget->topLevelItem(0)->setIcon(0, QIcon(":/tt/image/install_logo.png"));
// 插入 widget
QPushButton *btn = new QPushButton("button");
ui->treeWidget->setItemWidget(ui->treeWidget->topLevelItem(1), 0, btn);
// 设置颜色交错
ui->treeWidget->setAlternatingRowColors(true);
样式处理
// 行列样式
QTreeView {
background-color:#fefff7;
alternate-background-color: #cbe8d9;
}
QTreeView::item {
border: 1px solid #c5daff;
}
// 选中和悬停的样式
QTreeView::item:hover {
background: #c5daff;
}
QTreeView::item:selected {
background: #debbe8;
}
// 标题样式
QTreeView::section {
background-color: #ffe0d8;
border: 1px solid #c5daff;
}
如何利用手册查看对应的样式示例:
点击帮助 -> 搜索 -> style sheeet -> Qt Style Sheets Examples -> 查找对应的控件设置详情
// 图片放在资源文件中
QTreeView::branch:has-siblings:!adjoins-item {
border-image: url(":/tt/image/vline.png") 0;
}
QTreeView::branch:has-siblings:adjoins-item {
border-image: url(":/tt/image/branch-more.png") 0;
}
QTreeView::branch:!has-children:!has-siblings:adjoins-item {
border-image: url(":/tt/image/branch-end.png") 0;
}
QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings {
border-image: none;
image: url(":/tt/image/branch-closed.png");
}
QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings {
border-image: none;
image: url(":/tt/image/branch-open.png");
}
QDialog包括QColorDialog、QErrorMessage、QFileDialog、QFontDialog、QInputDialog、QMessageBox、QProgressDialog.
CustomDialog dialog;
dialog.setWindowTitle("dialog");
int result = dialog.exec();
switch (result) {
case QDialog::Accepted:
qDebug() << "Accepted";
break;
case QDialog::Rejected:
qDebug() << "Rejected";
break;
default:
break;;
}
自定义messagebox
// 添加qt设计师界面类
// 在界面中自定义ui
// 添加必要的信号槽
// CustomMessageBox.h
#ifndef CUSTOMMESSAGEBOX_H
#define CUSTOMMESSAGEBOX_H
#include
namespace Ui {
class CustomMessageBox;
}
class CustomMessageBox : public QDialog
{
Q_OBJECT
public:
explicit CustomMessageBox(QWidget *parent = nullptr);
~CustomMessageBox();
static int info(QString msg);
private:
Ui::CustomMessageBox *ui;
};
#endif // CUSTOMMESSAGEBOX_H
// CustomMessageBox.cpp
#include "custommessagebox.h"
#include "ui_custommessagebox.h"
CustomMessageBox::CustomMessageBox(QWidget *parent) :
QDialog(parent),
ui(new Ui::CustomMessageBox)
{
ui->setupUi(this);
// 去掉标题栏
setWindowFlags(Qt::FramelessWindowHint);
// 设置背景透明
this->setAttribute(Qt::WA_TranslucentBackground, true);
}
CustomMessageBox::~CustomMessageBox()
{
delete ui;
}
int CustomMessageBox::info(QString msg)
{
CustomMessageBox box;
box.ui->label->setText(msg);
return box.exec();
}
// ui中添加了一个widght作为背景视图,添加一个label、两个按钮
// 添加样式表,圆角
#widget {
border-radius:30px;
background-color: rgb(204, 204, 204);
}
Qdialog {
border-radius:30px;
background-color: rgb(204, 204, 204);
border: 1px solid gray;
}
自定义processDialog进度条
// ProcessDialog.h
#include
namespace Ui {
class ProcessDialog;
}
class ProcessDialog : public QDialog
{
Q_OBJECT
public:
explicit ProcessDialog(QWidget *parent = nullptr);
~ProcessDialog();
public slots:
void setDialog(int value);
private:
Ui::ProcessDialog *ui;
};
#endif
// ProcessDialog.cpp
#include
ProcessDialog::ProcessDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ProcessDialog)
{
ui->setupUi(this);
// 去掉标题栏和设置背景透明
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);
}
ProcessDialog::~ProcessDialog()
{
delete ui;
}
void ProcessDialog::setDialog(int value)
{
ui->progressBar->setValue(value);
if (value == 1000) {
for (int i = 100; i > 0; i-- ) {
this->setWindowOpacity((float)i / 100.0);
QThread::msleep(5);
// 设置label,shoudon
// ui->label->setText(QString::number(i));
// QEventLoop loop;
// loop.processEvents();
}
this->close();
}
}
// 自定义多线程 CustomThread.h
#include
class CustomThread : public QThread
{
Q_OBJECT
public:
CustomThread();
void run();
signals:
void setPos(int value);
};
// CustomThread.cpp
void CustomThread::run()
{
for(int i = 0; i <= 1000; i ++)
{
setPos(i);
msleep(10);
}
}
// 外部使用
ProcessDialog dialog;
CustomThread thread;
QObject::connect(&thread, SIGNAL(setPos(int)), &dialog, SLOT(setDialog(int)));
thread.start();
dialog.exec();
QMenuBar、QMenu、QAction
// 插入菜单栏
QMenuBar *bar = new QMenuBar(this);
bar->resize(width(), bar->height());
// 一级菜单
QMenu *menu = bar->addMenu("菜单一");
m_menu = menu;
// 二级菜单
QAction *action1 = menu->addAction("二级菜单1");
QAction *action2 = menu->addAction("二级菜单2");
QAction *action3 = menu->addAction("二级菜单3");
QMenu *menu1 = menu->addMenu("二级菜单4");
// 菜单设置图标
menu1->setIcon(QIcon(":/tt/image/install_logo.png"));
menu1->addAction("三级菜单");
// 添加快捷键
action1->setShortcut(tr("x"));
// 绑定点击信号
connect(action1, SIGNAL(triggered()), this, SLOT(test()));
// 绑定鼠标悬停信号
connect(action2, SIGNAL(hovered()), this, SLOT(testHovered()));
// 设置action可以选中
action1->setCheckable(true);
action2->setCheckable(true);
action3->setCheckable(true);
// QActionGroup
QActionGroup *group = new QActionGroup(this);
group->addAction(action1);
group->addAction(action2);
group->addAction(action3);
// 设置group中的按钮单选
group->setExclusive(true);
// 鼠标位置显示菜单(用于动态显示创建好的菜单)
m_menu->exec(QCursor::pos());
QToolBar *toolbar = new QToolBar(this);
toolbar->setGeometry(0, bar->height(), width(), 40);
toolbar->setIconSize(QSize(30, 30));
QAction *a = new QAction(QIcon(":/tt/image/install_logo.png"), "toolaction");
//a->setIcon(QIcon(":/tt/image/install_logo.png"));
toolbar->addAction(a);
QStatusBar *statusBar = new QStatusBar(this);
statusBar->setGeometry(0, height() - 40, width(), 40);
statusBar->showMessage("测试status message", 3000);
menuBar()->addAction("menu1");
statusBar()->showMessage("status bar message");
QToolBar *toolBar = new QToolBar(this);
toolBar->addAction("topaction");
QAction *a = new QAction(QIcon(":/tt/image/install_logo.png"), "icon action");
toolBar->addAction(a);
// 设置action text在icon下面
toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
// 在左侧添加toolbar Qt::LeftToolBarArea
addToolBar(Qt::TopToolBarArea, toolBar);
事件函数event、鼠标事件、键盘事件、窗口大小变化事件、重绘事件QPainter
// QEvent子类 QKeyEvent、QMouseEvent、QWheelEvent、QTouchEvent
bool EventDemo::event(QEvent *ev)
{
qDebug() << ev->type();
// 键盘事件
if (ev->type() == QEvent::KeyPress)
{
QKeyEvent *keyEv = static_cast(ev);
qDebug() << keyEv->key();
// 代表处理,不会把事件传递给其他控件,继续处理下一个事件
return true;
}
// 父类处理
return QWidget::event(ev);
}
// 键盘按下
void EventDemo::keyPressEvent(QKeyEvent *event)
{
// 过滤自动重复触发的
if(event->isAutoRepeat()) return;
qDebug() << "keyPressEvent = " << event->key();
}
// 键盘弹起
void EventDemo::keyReleaseEvent(QKeyEvent *event)
{
qDebug() << "keyReleaseEvent = " << event->key();
}
鼠标事件
bool EventDemo::event(QEvent *ev)
{
qDebug() << ev->type();
// 鼠标事件
if (ev->type() == QEvent::MouseButtonPress)
{
QMouseEvent *event = static_cast(ev);
// 相对坐标
qDebug() << "QMouseEvent x = " << event->x() << " y = " << event->y();
// 程序坐标
qDebug() << "windowPos x = " << event->windowPos().x() << " y = " << event->windowPos().y();
// 屏幕坐标
qDebug() << "screenPos x = " << event->screenPos().x() << " y = " << event->screenPos().y();
// 本地坐标转屏幕坐标
QPoint point = mapToGlobal(event->pos());
qDebug() << "mapToGlobal x = " << point.x() << " y = " << point.y();
// 获取鼠标的屏幕坐标
qDebug() << "QCursor x = " << QCursor::pos().x() << " y = " << QCursor::pos().y();
// 鼠标按键事件
if (event->buttons() & Qt::LeftButton)
{
qDebug() << "LeftButton click";
}
if (event->buttons() & Qt::RightButton)
{
qDebug() << "RightButton click";
}
if (event->buttons() & Qt::MidButton)
{
qDebug() << "MidButton click";
}
if ((event->buttons() & Qt::LeftButton) && (event->buttons() & Qt::RightButton))
{
qDebug() << "LeftButton && RightButton click";
}
return true;
}
return QWidget::event(ev);
}
修改鼠标样式
QCursor cursor;
QPixmap map(":/tt/image/install_logo.png");
cursor = QCursor(map, -1, -1);
setCursor(cursor);
// 还原
setCursor(Qt::ArrowCursor);
窗口大小改变事件
void EventDemo::resizeEvent(QResizeEvent *event)
{
qDebug() << "resizeEvent";
// 改变子控件的大小
ui->pushButton->resize(width() * 0.3, height() * 0.3);
}
绘制文字、绘制线、绘制图形、绘制融合图片
QPen用于控制线条的颜色、宽度、线型等
QBrush用于设置填充颜色、填充方式、渐变特性等,可以使用图片做填充
QFont用于绘制文字时设置文字的样式大小
void PainterDemo::paintEvent(QPaintEvent *event)
{
// 设置绘制设备
QPainter p(this);
// 画笔颜色
p.setPen(QColor(255,0,0,150));
// 字体
p.setFont(QFont("黑体", 20));
p.drawText(100, 50, "绘制文字");
// 绘制线
QPen pen;
// 实线
pen.setStyle(Qt::SolidLine);
// 线的宽度
pen.setWidth(10);
// 线刷子
pen.setBrush(Qt::red);
// 设置刷子为图片
//pen.setBrush(QBrush(QImage(":/tt/image/install_logo.png")));
// 结尾端样式
pen.setCapStyle(Qt::RoundCap);
// 连接处样式
pen.setJoinStyle(Qt::RoundJoin);
p.setPen(pen);
p.drawLine(QLine(10, 10, 300, 90));
}
QImageDemo::QImageDemo(QWidget *parent) :
QWidget(parent),
ui(new Ui::QImageDemo)
{
ui->setupUi(this);
img = QImage(1280, 720, QImage::Format_RGBA8888);
// 填入颜色
img.fill(QColor(255,0,0,200));
// 遍历设置颜色
uchar *data = img.bits();
// 假定已对齐,不对齐就出错
for (int i = 0; i < img.width() ; i++ ) {
for (int j = 0; j < img.height() / 2 ; j++) {
data[j * img.width() * 4 + i * 4] = 0; // r
data[j * img.width() * 4 + i * 4 + 1] = 255; // g
data[j * img.width() * 4 + i * 4 + 1] = 0; // b
data[j * img.width() * 4 + i * 4 + 1] = 255; // a
}
}
for (int i = img.width() / 2; i < img.width() ; i++ ) {
for (int j = 0; j < img.height() ; j++) {
img.setPixelColor(i,j, QColor(0, 0, 0, 255));
}
}
}
void QImageDemo::paintEvent(QPaintEvent *ev)
{
QPainter p(this);
if(!img.isNull()) {
p.drawImage(0, 0, img);
}
}
QIODevice:所有 I/O 设备类的父类,提供了字节块读写的通用操作以及基本接口;
QFileDevice:Qt5新增加的类,提供了有关文件操作的通用实现。
QFlie:访问本地文件或者嵌入资源;
QTemporaryFile:创建和访问本地文件系统的临时文件;
QBuffer:读写QbyteArray, 内存文件;
QProcess:运行外部程序,处理进程间通讯;
QAbstractSocket:所有套接字类的父类;
QTcpSocket:TCP协议网络数据传输;
QUdpSocket:传输 UDP 报文;
QSslSocket:使用 SSL/TLS 传输数据;
顺序访问设备:
是指它们的数据只能访问一遍:从头走到尾,从第一个字节开始访问,直到最后一个字节,中途不能返回去读取上一个字节,这其中,QProcess、QTcpSocket、QUdpSoctet和QSslSocket是顺序访问设备。
随机访问设备:
可以访问任意位置任意次数,还可以使用QIODevice::seek()函数来重新定位文件访问位置指针,QFile、QTemporaryFile和QBuffer是随机访问设备
QFile file("D:\\code\\123.txt");
// 获取当前目录
//QDir::currentPath()
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Open file failed.";
return;
} else {
while (!file.atEnd()) {
qDebug() << file.readLine();
}
}
QFileInfo info(file);
qDebug() << info.isDir();
qDebug() << info.isExecutable();
qDebug() << info.baseName();
qDebug() << info.completeBaseName();
qDebug() << info.suffix();
qDebug() << info.completeSuffix();
QDataStream二进制文件读写
// 写入
QFile file("D:\\code\\123.txt");
if (!file.open(QIODevice::WriteOnly)) {
qDebug() << "Open file failed.";
return;
} else {
QDataStream out(&file);
out << QString("123");
file.close();
}
// 读取
QFile file("D:\\code\\123.txt");
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Open file failed.";
return;
} else {
// 读取
QString res;
QDataStream in(&file);
in >> res;
qDebug() << "res = " << res;
file.close();
}
QTextStream文本文件读写
// 写入
QFile file("D:\\code\\123.txt");
if (!file.open(QIODevice::WriteOnly| QIODevice::Truncate)) {
qDebug() << "Open file failed.";
return;
} else {
QTextStream out(&file);
out.setCodec("UTF-8");
// 写入一行换行
out << QString("test message") << endl;
out << QString("test message other");
file.close();
}
// 读取多行
QFile file("D:\\code\\123.txt");
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Open file failed.";
return;
} else {
QTextStream in(&file);
QString res;
while (in.readLineInto(&res)) {
qDebug() << res;
}
file.close();
}
1、Qt样式表支持CSS2中定义的所有选择器
选择器 | 例子 | 用途 |
---|---|---|
通用选择器 | * | 所有组件 |
类型选择器 | QPushButton | 所有QPushButton类及其子类 |
属性选择器 | QPushButton[flat=“false”] | 所有QPushButton属性flat=false的类及其子类 |
非子类选择器 | .QPushButton | 所有QPushButton类不包括其子类 |
ID选择器 | QPushButton#btn | ObjectName="btn"的QPushButton组件 |
从属对象选择器 | QDialog QPushButton | QDialog下面的所有QPushButton实例 |
子对象选择器 | QDialog>QPushButton | QDialog下面直接从属的所有QPushButton实例 |
2、子控件,组合组件下面的控件控制,例如QProgressBar::chunk 进度显示块的控制
3、伪状态的控制,如:hover
4、属性的控制 如:border
样式表的使用:
1、设计窗体中设置
2、setStyleSheet函数设置
基础使用
#ifndef CUSTOMTHREAD_H
#define CUSTOMTHREAD_H
#include
class CustomThread : public QThread
{
Q_OBJECT
public:
CustomThread();
void run();
signals:
void setPos(int value);
};
#endif // CUSTOMTHREAD_H
// cpp
#include "customthread.h"
CustomThread::CustomThread()
{
}
void CustomThread::run()
{
for(int i = 0; i <= 1000; i ++)
{
// 发送信号,外面绑定信号处理
setPos(i);
msleep(10);
}
}
1、基于互斥量的线程同步
QMutex、QMutexLocker 每次只有一个线程获得互斥量的权限
2、QReadWriteLock 适合用于一个线程写,多个线程获取的场景
3、QWaitCondition 适用于一个线程满足某个条件,然后通知其他线程响应的场景
4、基于信号量的线程同步 QSemaphore 适用于保护一定数量的资源
QHostInfo、QNetworkInterface
// QT += network
// 电脑设备名称
QString hostName = QHostInfo::localHostName();
QString domainName = QHostInfo::localDomainName();
qDebug() << hostName;
qDebug() << domainName;
QHostInfo host = QHostInfo::fromName(hostName);
// 获取地址列表
QList address = host.addresses();
for(int i = 0; i < address.size(); i++)
{
qDebug() << address[i];
if (address[i].protocol() == QAbstractSocket::IPv4Protocol) {
qDebug() << "IPv4Protocol";
} else {
qDebug() << "IPv6Protocol";
}
}
// 获取主机网络接口
QList interface = QNetworkInterface::allInterfaces();
for(int i = 0; i < interface.size(); i++)
{
// 设备名称
qDebug() << interface[i].humanReadableName();
// 设备地址
qDebug() << interface[i].hardwareAddress();
}
QTcpSocket
QUdpSocket
QNetworkRequest、QNetworkRequest、QNetworkAccessManager
#include
#include
#include
#include
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_readyRead();
void on_finished();
void on_process(qint64 current, qint64 totle);
private:
Ui::Widget *ui;
QNetworkRequest request;
QNetworkAccessManager manger;
QNetworkReply *reply;
QFile *downloadFile;
};
#endif // WIDGET_H
// cpp
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QString urlString = "http://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png";
QUrl url = QUrl::fromUserInput(urlString);
if (!url.isValid())
{
qDebug() << "url error";
return;
}
request = QNetworkRequest(url);
reply = manger.get(request);
connect(reply, SIGNAL(finished()), this, SLOT(on_finished()));
connect(reply, SIGNAL(readyRead()), this, SLOT(on_readyRead()));
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(on_process(qint64,qint64)));
QString fileName = QDir::currentPath() + "/" + url.fileName();
qDebug() << "fileName = " << fileName;
if (QFile::exists(fileName))
QFile::remove(fileName);
downloadFile = new QFile(fileName);
downloadFile->open(QIODevice::ReadWrite);
}
void Widget::on_readyRead()
{
qDebug() << "on_readyRead";
downloadFile->write(reply->readAll());
}
void Widget::on_finished()
{
qDebug() << "on_finished";
downloadFile->close();
}
void Widget::on_process(qint64 current, qint64 totle)
{
qDebug() << "current = " << current << " totle = " << totle;
}
静态发布:将所有的需要的运行库编译到应用程序中,生成独立的可执行文件
共享库形式发布:将程序依赖的共享库和可执行程序一起发布
1、进入编译完成的release版本安装包目录
2、找到对应编译器的工具windeployqt
# D:\Qt\Qt5.12.12\5.12.12\msvc2017\bin
# windeployqt一般再对应的编译器bin目录下
# 打包程序 等待完成即可
# windeployqt并不能保证一次将所有的依赖都复制到对应的目录下,需要移除qt环境变量或者找个不包含qt环境的电脑测试,如果有缺失dll,将缺失的dll复制到对应的目录
D:\Qt\Qt5.12.12\5.12.12\msvc2017\bin\windeployqt.exe demo.exe