首页 > 编程语言 >C++编程笔记(QT)

C++编程笔记(QT)

时间:2022-10-24 19:46:03浏览次数:79  
标签:控件 QT age 编程 C++ ui 选中 new void

目录

入门基础

模态对话框

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()<<"女孩";
  }
}

标签:控件,QT,age,编程,C++,ui,选中,new,void
From: https://www.cnblogs.com/Lhh-9999/p/16822522.html

相关文章

  • shell编程之函数,递归
    函数定义函数格式一:function函数名{命令序列}格式二:函数名(){命令序列}#####main#####可以直接在主代码区直接使用函数名调用函数   删除函数格式:u......
  • SYSU-SSE 3D游戏编程与设计 学习笔记(2)--空间与运动
    前言中山大学软件工程学院3D游戏编程与设计课程学习记录博客游戏代码:游戏代码简答题游戏对象运动的本质是什么游戏对象的运动过程本质上就是游戏对象transform......
  • C++ 实现随机数生成(Windows、Linux)
    文章目录​​1、简介​​​​2、windows随机数​​​​2.1随机数范围计算公式​​​​2.2rand()​​​​2.3srand()​​​​2.4c++11<random>​​​​2.4.1随机数生成......
  • 为什么说C++太复杂?复杂的必要性是为什么?
    1常见观点可以轻易的找出许多文献说明C++太复杂了,例如学习C++的书籍的厚度。这样以至于C++的设计者Bjarne都曾怀疑具有类的C是不是已经太庞大了。因为,总有大量对语言的......
  • Java并发编程学习10-任务执行与Executor框架
    任务执行何为任务?任务通常是一些抽象且离散的工作单元。大多数并发应用程序都是围绕着“任务执行”来构造的。而围绕着“任务执行”来设计应用程序结构时,首先要做的......
  • 周日1040C++班级2022-10-23 初始C++
    初识C++一、C++程序框架C++的程序是有一个大的框架的,我们需要使用include去让我们的程序包含C++的头文件iostream;并且在下一行还有usingnamespacestd去使用C++的标准名......
  • c++ template std::void_t 是个啥
    源码在<type_traits>头文件里有void_t的定义template<class..._Types>usingvoid_t=void;很简单,其实就是void,只不过可以传入模板参数,比如std::void_t<int,float,......
  • C++中的try和catch
    程序运行时常会碰到一些异常情况,例如:做除法的时候除数为0;用户输入年龄时输入了一个负数;用new运算符动态分配空间时,空间不够导致无法分配;访问数组元素时,下标越界;打......
  • MQTT Host name verification failure (SSL)-增加--insecure选项解决
    增加一个选项即可解决:--insecure出问题:mosquitto_pub-d-h192.168.1.10-p1883-thello-m123--cafile~/cacert.pemClientnullsendingCONNECTError:hostn......
  • python渗透测试入门——基础的网络编程工具
    《Python黑帽子——黑客与渗透测试编程之道学习》这本书是我在学习安全的过程中发现的在我看来十分优秀的一本书,业内也拥有很高的评价,所以在这里将自己的学习内容分享出来......