入门基础

模态对话框

MyDialog1::~MyDialog1() { delete ui; }

//三者都是解除阻塞
void MyDialog1::on_acceptButton_clicked() {
this->accept(); //发出accepted信号返回Accepted
}
//done信号可以传递数据,同时也会返回
void MyDialog1::on_doneButton_clicked() {
this->done(10); //发出finished并传递参数10,关闭模态框并且返回10
} void MyDialog1::on_rejectButton_clicked() //与accept一样
{
this->reject(); //发出rejected信号返回Rejected
} MyDialog1 dlg; //done信号向槽函数传递数据
connect(&dlg, &MyDialog1::finished, this,
[=](int res) { qDebug() << "res:" << res; }); connect(&dlg, &MyDialog1::accepted, this,
[=]() { qDebug() << "accept 信号发射"; }); connect(&dlg, &MyDialog1::rejected, this,
[=]() { qDebug() << "reject 信号发射"; }); int ret = dlg.exec(); switch (ret) {
case QDialog::Accepted:
qDebug() << "accept button clicked";
break;
case QDialog::Rejected:
qDebug() << "reject button clicked";
break;
default:
qDebug() << "done button clicked";
break;
}

消息提示框(messagebox)

//信息提示框
QMessageBox::about(this, "help", "我的messagebox");
//错误提示框
QMessageBox::critical(this, "critial", "error");
//确认提示框
auto ret =
QMessageBox::question(this, "question", "是否保存当前文件",
QMessageBox::Save | QMessageBox::Cancel, //按钮
QMessageBox::Cancel); //默认按钮
if (ret == QMessageBox::Save) {
QMessageBox::information(this, "info", "save success");
} else if (ret == QMessageBox::Cancel) {
QMessageBox::warning(this, "warning", "cancel");
}

文件和目录

  //只会显示目录								父控件	标题			默认目录
auto path = QFileDialog::getExistingDirectory(this, "打开一个目录", "..\\");
qDebug() << path; auto path = QFileDialog::getOpenFileName(
this, "打开一个文件", "..\\",
"Images(*.png *.xpm *.jpg);;Text files(*.txt);;XML files (*.xml);;Video "
"files(*.mp4)"); auto path = QFileDialog::getOpenFileNames(this, "打开一批文件", ".\\", "*.*");//返回文件列表
QMessageBox info(QMessageBox::Information, "文件路径", path[0],
QMessageBox::Yes | QMessageBox::No);
for (const auto &i : path) {
qDebug() << i;
}
info.exec(); //不会创建文件,二十返回保存文件的绝对路径
auto path =
QFileDialog::getSaveFileName(this, "保存文件", "..\\", "txt(*.txt)");
QMessageBox::information(this, "保存文件", path);
}

字体选择框


bool ok;
//点了确认返回true,否则返回false
QFont font = QFontDialog::getFont(&ok, QFont("微软雅黑", 12, QFont::Bold),
this, "选择字体");
qDebug() << ok; //不默认指定任何参数,通过字体对话框选择一个字体对象
auto font = QFontDialog::getFont(NULL); ui->fontLable->setFont(font);
//静态方法,设当前GUI所有的字体
QApplication::setFont(font);

输入对话框

void MainWindow::on_inputDialogButton_clicked() {

#ifdef text
auto in = QInputDialog::getText(this, "Text", "NO");
#endif
#ifdef INT
auto in = QInputDialog::getInt(this, "输入一个int", "年龄", 1, 1, 100, 2);
#endif
#ifdef Item
QStringList list;
list << "香蕉"
<< "苹果"
<< "香蕉"
<< "哈密瓜"
<< "桔子";
auto in = QInputDialog::getItem(this, "选择一个水果", "选择", list, 1, false); #endif
qDebug() << in;
}

进度条

void MainWindow::on_progressButton_clicked() {
auto *p = new QProgressDialog("正在拷贝", "取消拷贝", 0, 100,
this); //不指定父对象就需要自己析构
p->setWindowModality(Qt::WindowModal);
p->setWindowTitle("稍后");
p->show(); auto time = new QTimer(); //不指定父对象就需要自己析构
time->start(50); // 50ms更新一次
size_t *value = new size_t();
*value = 0;
connect(time, &QTimer::timeout, this, [value, p, time]() {
p->setValue(*value);
(*value)++;
if (*value > p->maximum()) {
time->stop();
*value = 0;
delete p;
delete time;
}
});

工具栏

工具栏主要是在ui文件中添加(菜单栏一样),通过以下方式添加工具栏中的控件

  ui->toolBar->addWidget(new QPushButton("搜索"));//不建议使用匿名对象
ui->toolBar->addWidget(new QLineEdit());

通过代码添加工具栏

	auto toolbar = new QToolBar(this);
toolbar->setMovable(false);
toolbar->setFloatable(false);
toolbar->setFixedWidth(50);
toolbar->setAllowedAreas(Qt::RightToolBarArea);
this->addToolBar(Qt::RightToolBarArea, toolbar);

控件布局


基本的控件布局就这些。布局一般是在Widget内,控件添加入Widget然后Widget自动按照布局排列,Widget里面可以套Widget
弹簧是布局中的重要工具,通过弹簧可以设置控件之间的相对距离。比如说,如果需要Widget中的label居中显示,可以在label的两侧各放一根弹簧,有水平弹簧和垂直弹簧

弹簧控件

使用示例

代码进行布局


Windows托盘案例

  • #include <QSystemTrayIcon>
  • 新建并且设置托盘图标
  QIcon icon = QIcon("D:\\MyProject\\C++\\transFile\\transfile.ico");
this->trayIcon = new QSystemTrayIcon(this);
this->trayIcon->setIcon(icon);
this->trayIcon->setToolTip("a tray example");
this->trayIcon->show();
  • 设置Action
  this->normal = new QAction("还原", this);
connect(this->normal, &QAction::triggered, this, &myForm::showNormal);//正常展示窗口 this->quit = new QAction("退出", this);
connect(this->quit, &QAction::triggered, qApp, &QApplication::quit); //qAPP是全局的,表示当前程序
  • 将Action放入托盘图标右键menu中并且设置右键点击
  this->trayMenu = new QMenu(this);
this->trayMenu->addAction(this->normal);
this->trayMenu->addAction(this->quit);
this->trayIcon->setContextMenu(this->trayMenu);
  • 重写右上角的关闭和隐藏按钮事件
//重写右上角按钮事件,需要在.h声名文件中声名
//设置右上角关闭按钮为最小化
void myForm::closeEvent(QCloseEvent *event) {
if (trayIcon->isVisible()) {
hide();
trayIcon->showMessage("title", "Close");
//忽略这个事件,则不会关闭
event->ignore();
}
}
void myForm::hideEvent(QHideEvent *event) {
if (trayIcon->isVisible()) {
hide();
trayIcon->showMessage("title", "hide");
event->ignore();
}
}
  • 托盘图标的点击事件
connect(this->trayIcon, &QSystemTrayIcon::activated, this,
&myForm::iconIsActived);//利用activated信号 //对应的槽函数 //一个枚举值
void myForm::iconIsActived(QSystemTrayIcon::ActivationReason reason) {
switch (reason) {
case QSystemTrayIcon::DoubleClick://双击图标窗口换源
this->showNormal();
break;
case QSystemTrayIcon::Trigger: //单击展示托盘菜单
this->trayMenu->move(QCursor().pos());
this->trayMenu->show();
break;
default:
break;
}
}

控件

button

都是基于QAbstractbutton,公共的信号有clicked,toggled,pressed,released,使用起来较为简单,常用的就是clicked
设置一个开关按钮,通过这种方式可以使一个pushbutton变为一个开关按钮

  ui->toggleButton->setCheckable(true);
connect(ui->toggleButton, &QPushButton::toggled, this, [=](bool bl) {
qDebug() << "check按钮当前状态为" << bl;
auto status = bl ? "开" : "关";
ui->toggleButton->setText(status);
});

                       


下拉菜单按钮

  ui->menuButton->setText("选择你最喜欢的水果");
auto menu = new QMenu();
auto act1 = new QAction("西瓜");
menu->addAction(act1);
menu->addAction("菠萝");
menu->addAction("香蕉");
menu->addAction("苹果");
menu->addAction("葡萄");
menu->addAction("脐橙");
ui->menuButton->setMenu(menu); connect(act1, &QAction::triggered, this,
[act1]() { qDebug() << act1->text(); });


上面的应用都可一用在QToolButton


radioButton单选按钮


同一组按钮只能选中一个,通常使用Group Box分组因为自带了标题,记得要设置布局


checkBox:复选框,

布局与上述一样,有三个状态选中 未选中 半选中,默认是选中和未选中两种状态,需要setTristate为True才有半选中状态。
常用信号stateChanged参数反应的就是CheckBox的状态

void MainWindow::on_checkBox_stateChanged(int arg1) {
QString str{};
str = (arg1 == Qt::Checked) ? "你讨厌加班" : "可以接受加班";
qDebug() << str;
}

树形结构复选框

内层是Widget,外层是Group Box都是垂直布局
逻辑设计思路

  1. 引入计数机制,记录子节点被中的个数
  2. 当子节点全部被选中,则父节点设置为Checked,部分被选中设置为PartiallyChecked,选中数为0则为Unchecked
  3. 对父节点的点击事件进行相应,若选中父节点,则子节点全部选中
    代码实现:
	//初始化

  ui->WenKe->setTristate(true);
connect(ui->ZhengZhi, &QCheckBox::stateChanged, this,&MainWindow::CheboxSlot);
connect(ui->LiShi, &QCheckBox::stateChanged, this, &MainWindow::CheboxSlot); //clicked信号属于父类,参数为选中状态,bool类型
connect(ui->WenKe, &QCheckBox::clicked, this, [this](bool bl) {
if (bl) { //被选中
ui->ZhengZhi->setCheckState(Qt::Checked);
ui->LiShi->setCheckState(Qt::Checked);
} else {
ui->ZhengZhi->setCheckState(Qt::Unchecked);
ui->LiShi->setCheckState(Qt::Unchecked);
}
});

子节点绑定的槽函数,所有子节点绑定同一个槽函数,槽函数只对计数进行操作

void MainWindow::CheboxSlot(int state) {
if (state == Qt::Checked) {
++(this->cheboxTrueNumWenKe);//int类型,初始化为0
} else {
--(this->cheboxTrueNumWenKe);
}
switch (this->cheboxTrueNumWenKe) {
case 0:
ui->WenKe->setCheckState(Qt::Unchecked);
break;
case 1:
ui->WenKe->setCheckState(Qt::PartiallyChecked);
break;
default://全部选中
ui->WenKe->setCheckState(Qt::Checked);
break;
}
}

对于重载信号,应该使用这种写法绑定,表示形参为int类型的重载

列表控件ToolBox和TableWidget


同时选中二者使用拆分器水平布局可以将二者绑定在一起

属性

QObject类:QT所有类的基类

class MyPerson:public QObject{
Q_OBJECT //必须的
Q_CLASSINFO("author", "lhh")
Q_CLASSINFO("date", "2022-05-08") Q_PROPERTY(unsigned age READ age WRITE setAge NOTIFY ageChanged)
Q_PROPERTY(QString name MEMBER m_name)
Q_PROPERTY(QString sex MEMBER m_sex)
Q_PROPERTY(unsigned score MEMBER m_score)
// Q_PROPERTY(unsigned age MEMBER m_age)
// //将成员变量m_age导出为属性值age,使得其可通过属性操作成员变量
private:
unsigned int m_age;
unsigned int m_score;
QString m_name;
QString m_sex;
public: unsigned int age(){
return m_age;
}
void setAge(unsigned int value){
m_age=value;
ageChanged();
}
signals:
void ageChanged();
}

上述类中使用了两个宏Q_PROPERTYQ_CLASSINFO
Q_CLASSINFO主要存放类的信息,可以不用

Q_PROPERTY定义

Q_PROPERTY(type name
READ getFunction
[WRITE setFunction]
[RESET resetFunction]
[NOTIFY notifySignal]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL]
)

上述MyPerson类中的Q_PROPERTY第一种用法就是定义一个属性age,设置读取属性的函数为age()
,写属性的函数为setAge(),信号为ageChanged(),其中读写函数必须实现,可以再相应的;
第二种用法就是使用MEMBER关键字将成员变量注册为属性,使用setproperty修改属性就可以操作成员变量

  boy = new QPerson;
boy->setProperty("score", 80);
boy->setProperty("age", 18);

由于age属性和m_age绑定,所以此处m_age=18;
获取属性:

QMetaProperty*b=boy.metaObject();
QString m_name= boy->property("name").toString();

利用属性辨别信号的发出者

同属于一个类的多个对象,可以同时向一个一个对象发出信号,那接收者如何分别发送信号的是哪一个类呢?

 this->boy = new QPerson();
this->girl = new QPerson(); //设置一个属性判断性别
ui->boyAgeSpinBox->setProperty("isBoy", true);
ui->girlAgeSpinBox->setProperty("isBoy", false); //二者同时绑定同一个槽函数
connect(this->girl, &QPerson::ageChanged, this, &on_spinBoxValue_Changed);
connect(this->boy, &QPerson::ageChanged, this, &on_spinBoxValue_Changed); //槽函数,接收ageChanged信号
void MainWindow::on_spinBoxValue_Changed(int value) {
QPerson*spinBox = qobject_cast<QPerson*>(sender());
if (spinBox->property("isBoy").toBool()) {
qDebug()<<"男孩";
} else {
qDebug()<<"女孩";
}
}

C++编程笔记(QT)的更多相关文章

  1. C# 高效编程笔记2

    C# 高效编程笔记2 1.理解GetHashCode()的陷阱 (1)作用:作为基于散列集合定义键的散列值,如:HashSet<T>,Dictionary<K,V>容器等 (2 ...

  2. C# 高效编程笔记1

    C# 高效编程笔记1 1.使用属性而不是可访问的数据成员 (1).NET Framework中的数据绑定类仅支持属性,而不支持共有数据成员 (2)属性相比数据成员更容易修改 2.用运行时常量(read ...

  3. storysnail的Linux串口编程笔记

    storysnail的Linux串口编程笔记 作者 He YiJun – storysnail<at>gmail.com 团队 ls 版权 转载请保留本声明! 本文档包含的原创代码根据Ge ...

  4. storysnail的Windows串口编程笔记

    storysnail的Windows串口编程笔记 作者 He YiJun – storysnail<at>gmail.com 团队 ls 版权 转载请保留本声明! 本文档包含的原创代码根据 ...

  5. DSP28377S - ADC学习编程笔记

    DSP28377S -  ADC学习编程笔记 彭会锋 2016-08-04  20:19:52 1 ADC类型导致的配置区别 F28377S的ADC类型是Type 4类型,我的理解是不同类型的ADC采 ...

  6. C# Socket编程笔记(转)

    C# Socket编程笔记 http://www.cnblogs.com/stg609/archive/2008/11/15/1333889.html TCP Socket:Server 端连接步骤: ...

  7. RX编程笔记——JavaScript 获取地理位置

    RX编程笔记——JavaScript 获取地理位置 2016-07-05

  8. Shell编程笔记

    Shell编程笔记与Windows下熟悉的批处理类似,也可以将一些重复性的命令操作写成一个脚本方便处理.   修改别人的脚本,运行后遇到个问题 setenv: command not found 查证 ...

  9. python核心编程--笔记

    python核心编程--笔记 的解释器options: 1.1 –d   提供调试输出 1.2 –O   生成优化的字节码(生成.pyo文件) 1.3 –S   不导入site模块以在启动时查找pyt ...

  10. Android高级编程笔记(四)深入探讨Activity(转)

    在应用程序中至少包含一个用来处理应用程序的主UI功能的主界面屏幕.这个主界面一般由多个Fragment组成,并由一组次要Activity支持.要在屏幕之间切换,就必须要启动一个新的Activity.一 ...

随机推荐

  1. MySQL的EXPLAIN会修改数据测试

    文章转载自:https://www.cnblogs.com/kerrycode/p/14138626.html 在博客"Explain命令可能会修改MySQL数据"了解到MySQL ...

  2. kvm里的虚拟机硬盘和网卡使用virtio驱动

    1.首先从虚拟机的xml文件中找到已经使用virtio驱动的硬件,复制里面的address这行参数出来 <address type='pci' domain='0x0000' bus='0x00 ...

  3. 【微服务】- 服务调用 - OpenFeign

    服务调用 - OpenFeign 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 介绍 O ...

  4. centos离线安装nvm

    PS:因为项目需,客户现场不能联网需要不同的node版本来切换,里面已经内置好了node 8.11.2和12.1.0 两个版本,使用nvm可以切换 链接:https://pan.baidu.com/s ...

  5. PAT (Basic Level) Practice 1028 人口普查 分数 20

    某城镇进行人口普查,得到了全体居民的生日.现请你写个程序,找出镇上最年长和最年轻的人. 这里确保每个输入的日期都是合法的,但不一定是合理的--假设已知镇上没有超过 200 岁的老人,而今天是 2014 ...

  6. Netty 学习(八):新连接接入源码说明

    Netty 学习(八):新连接接入源码说明 作者: Grey 原文地址: 博客园:Netty 学习(八):新连接接入源码说明 CSDN:Netty 学习(八):新连接接入源码说明 新连接的接入分为3个 ...

  7. Linux shell猜数游戏

    题目:猜随机数随机1-100中的一个数字,要求用户猜数字,猜中则退出脚本并告知用户猜测次 数和随机数字,否则要求用户继续猜,并告知当前猜的数字和随机数的关系. #!/bin/bash #猜数游戏 Ra ...

  8. Codeforces Round #710 (Div. 3)

    emmm,就ac了3题 A题转换推下公式. tB题模拟,在第一个与最后一个变x后,直接i下标+k,判断当前下标前一个befor与最后一个last距离是否>k,是的话在当前下标往前找*字符然后改为 ...

  9. P7800 [COCI2015-2016#6] PAROVI 方法记录

    原题链接 桔梗花于此开放 [COCI2015-2016#6] PAROVI 题目描述 \(\text{Mirko}\) 和 \(\text{Slavko}\) 在玩一个游戏,先由 \(\text{Mi ...

  10. el-cascader组件根据最后一级向上找到父级并设置默认值

    vue + elementUI项目中,el-cascader级联选择器使用频率非常高,一些基本使用方法可以参考elementUI官方文档,本文主要研究当接口只返回最后一级id时,如何向上找出所有父级数 ...