06-2_Qt 5.9 C++开发指南_自定义对话框及其调用

本篇介绍到的对话框及其调用实例较为复杂但十分详细,如果做了解可以先参考:QT从入门到实战x篇_13_模态和非模态对话框创建。

文章目录

  • 1. 对话框的不同调用方式
  • 2. 对话框QWDialogSize 的创建和使用
    • 2.1 创建对话框QWDialogSize
    • 2.2 对话框的调用和返回值
  • 3. 对话框QWDialogHeaders 的创建和使用
    • 3.1 对话框的生存期
    • 3.2 QWDialogHeaders 的定义和实现
    • 3.3 QWDialogHeaders 对话框的使用
  • 4. 对话框QWDialogLocate 的创建与使用
    • 4.1 非模态对话框
    • 4.2 对话框的创建与调用,对话框与主窗口的交互
    • 4.3 对话框中操作主窗口
    • 4.4 主窗口中操作对话框
    • 4.5 窗口的CloseEvent事件及事件简介
  • 5. 利用信号与槽实现对话框及主窗口交互操作
  • 6. 源码
    • 6.1 程序框架
    • 6.2 可视化UI设计
      • 6.2.1 qwdialogsize.ui
      • 6.2.2 qwdialogheaders.ui
      • 6.2.3 qwdialoglocate.ui
      • 6.2.4 mainwindow.ui
    • 6.3 代码
      • 6.3.1 qwdialogsize
      • 6.3.2 qwdialogheaders
      • 6.3.3 qwdialoglocate
      • 6.3.4 mainwindow

1. 对话框的不同调用方式

在一个应用程序设计中,为了实现一些特定的功能,必须设计自定义对话框。自定义对话框的设计一般从QDialog 继承,并且可以采用 UI 设计器可视化地设计对话框。对话框的调用一般包括创建对话框、传递数据给对话框、显示对话框获取输入、判断对话框单击按钮的返回类型、获取对话框输入数据等过程。

本节将通过实例 samp6_2 来详细介绍这些原理。图6-5是实例 samp6_2 的主窗口,及其设置表格行列数的对话框。
主窗口采用 QTableView 和 QStandardItemModel、QItemSelectionModel 构成一个通用的数据表格编辑器,设计了3 个对话框,分别具有不同的功能,并且展示对话框不同调用方式的特点。

  • 设置表格行列数对话框QWDialogSize

该对话框每次动态创建,以模态方式显示(必须关闭此对话框才可以返回主窗口操作),对话框关闭后获取返回值,用于设置主窗口的表格行数和列数,并且删除对话框对象,释放内存

这种对话框创建和调用方式适用于比较简单,不需要从主窗口传递大量数据做初始化的对话框,调用后删除对话框对象可以节约内存。

在这里插入图片描述

  • 设置表头标题对话框QWDialogHeaders

图 6-6 是设置表格表头标题的对话框,该对话框在父窗口(本例中就是主窗口)存续期间只创建一次,创建时传递表格表头字符串列表给对话框,在对话框里编辑表头标题后,主窗口获取编辑之后的表头标题。对话框以模态方式显示,关闭后只是隐藏,并不删除对象,下次再调用时只是打开已创建的对话框对象

在这里插入图片描述

这种创建和调用方式适用于比较复杂的对话框,需要从父窗口传递大量数据做对话框初始化。下次调用时不需要重复初始化,能提高对话框调用速度,但是会一直占用内存,直到父窗口删除时,对话框才从内存中删除。

  • 单元格定位与文字设置对话框QWDialogLocate

图 6-7 是单元格定位和文字设置对话框,该对话框以非模态方式调用,显示对话框时还可以对主窗口进行操作,对话框只是浮动在窗口上方。在对话框里可以定位主窗口表格的某个单元格并设置其文字内容,在主窗口上的表格中单击鼠标时,单元格的行号、列号也会更新在对话框中。对话框关闭后将自动删除,释放内存。
这种对话框适用于主窗口与对话框需要交互操作的情况,例如用于查找和替换操作的对话框。

在这里插入图片描述

2. 对话框QWDialogSize 的创建和使用

2.1 创建对话框QWDialogSize

实例主窗口从QMainWindow 继承,主窗口用一个QTableView 组件作为界面中心组件,设计几个 Action 用于创建主工具栏按钮。主窗口采用 QStandardItemModel 作为数据模型,QItemSelectionModel 作为选择模型,界面和主窗口 Model/View 结构的设计可参考 5.4 节的实例本节不再详述。

在项目主窗口建立后,要创建如图 6-5 所示的设置表格行列数的对话框,单击 Qt Creator 的菜单项“File”-“New File or Project”,选择Qt类别下的“Qt Designer Form Class”,创建可视化设计的对话框类。在随后出现的向导里,选择窗口模板为 Dialog without Buttons,并设置自定义对话框的类名。

设置创建的对话框类名称为 QWDialogSize,系统自动生成 qwdialogsize.h、qwdialogsize.cpp和qwdialogsizeui3个文件。

QWDialogSize 对话框的界面设计在 UI 设计器里进行,放置界面组件并设置好布局

2.2 对话框的调用和返回值

设计 QWDialogSize 对话框的界面时,在上面放置了两个 QPushButton 按钮,并分别命名为btnOK 和 btnCancel,分别是“确定”和“取消”按钮,用于获取对话框运行时用户的选择。那么,如何获得用户操作的返回值呢?

在信号与槽编辑器里,将 btnOK的clicked()信号与对话框的 accept()槽关联,将 btnCancel 的 clicked()信号与对话框的 reject()槽关联即可,如图 6-8 所示

在这里插入图片描述

单击“确定”按钮会执行 accept()槽(或在代码里调用 accept()槽函数也是一样的),这会关闭对话框(默认情况下,对话框只是被隐藏,并不被删除),并返回 QDialog::Accepted 作为 exec()函数的返回值。

单击“取消”按钮会执行 reject()槽函数,也会关闭对话框,并返回QDialog::Rejected 作为 exec()函数的返回值。

完成后的QWDialogSize的类完整定义如下:

#ifndef QWDIALOGSIZE_H
#define QWDIALOGSIZE_H#include <QDialog>namespace Ui {
class QWDialogSize;
}class QWDialogSize : public QDialog
{Q_OBJECTpublic:explicit QWDialogSize(QWidget *parent = 0);~QWDialogSize();int     rowCount();//获取对话框输入的行数int     columnCount();//获取对话框输入的列数void    setRowColumn(int row, int column); //初始对话框上两个SpinBox的值private slots:private:Ui::QWDialogSize *ui;
};#endif // QWDIALOGSIZE_H

在QWDialogSize 的类定义中定义3 个 public 函数,用于与对话框调用者的数据交互。因为窗体上的组件都是私有成员,外界不能直接访问界面组件,只能通过接口函数访问。

下面是类的接口函数实现代码。在析构函数中弹出一个消息提示对话框,以便观察对话框是何时被删除的。

#include "qwdialogsize.h"
#include "ui_qwdialogsize.h"#include    <QMessageBox>QWDialogSize::QWDialogSize(QWidget *parent) :QDialog(parent),ui(new Ui::QWDialogSize)
{ui->setupUi(this);
}QWDialogSize::~QWDialogSize()
{QMessageBox::information(this,"info","Setting dialog object is deleted ");delete ui;
}int QWDialogSize::rowCount()
{ //用于主窗口调用获得行数的输入值return  ui->spinBoxRow->value();
}int QWDialogSize::columnCount()
{//用于主窗口调用获得列数的输入值return  ui->spinBoxColumn->value();
}void QWDialogSize::setRowColumn(int row, int column)
{ //初始化数据显示ui->spinBoxRow->setValue(row);ui->spinBoxColumn->setValue(column);
}

下面是主窗口中的“设置行数列数”工具栏按钮的响应代码,用于创建、显示对话框,并读取对话框上设置的行数、列数。

void MainWindow::on_actTab_SetSize_triggered()
{ //模态对话框,动态创建,用过后删除QWDialogSize    *dlgTableSize=new QWDialogSize(this); //创建对话框
//   dlgTableSize->setAttribute(Qt::WA_DeleteOnClose);
//对话框关闭时自动删除对话框对象,用于不需要读取返回值的对话框
//如果需要获取对话框的返回值,不能设置该属性,可以在调用完对话框后删除对话框Qt::WindowFlags    flags=dlgTableSize->windowFlags();dlgTableSize->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); //设置对话框固定大小dlgTableSize->setRowColumn(theModel->rowCount(),theModel->columnCount()); //对话框数据初始化int ret=dlgTableSize->exec();// 以模态方式显示对话框,用户关闭对话框时返回 DialogCode值if (ret==QDialog::Accepted) //OK键被按下,对话框关闭,若设置了setAttribute(Qt::WA_DeleteOnClose),对话框被释放,无法获得返回值{ //OK键被按下,获取对话框上的输入,设置行数和列数int cols=dlgTableSize->columnCount();theModel->setColumnCount(cols);int rows=dlgTableSize->rowCount();theModel->setRowCount(rows);}delete dlgTableSize; //删除对话框
}

从代码中可以看到,每次单击此工具栏按钮时,对话框都被重新创建。创建后用 QDialog 的setWindowFlags()函数将对话框设置为固定大小,然后调用对话框的自定义函数setRowColumn(),将主窗口数据模型 theModel 的现有的行数和列数显示到对话框上的两个 SpinBox 组件里。

调用对话框的 exec()函数,以模态显示的方式显示对话框。模态显示方式下,用户只能在对话框上操作,不能操作主窗口,主程序也在此处等待 exec()函数的返回结果。

当用户单击“确定”按钮关闭对话框后,exec()返回结果为 QDialog::Accepted,主程序获得此返回结果后,通过对话框的自定义函数 columnCount()和rowCount()获得对话框上新输入的列数和行数,然后设置为数据模型的列数和行数。
最后使用 delete 删除创建的对话框对象,释放内存。所以,关闭对话框时,会出现 QWDialogSize析构函数里的消息提示对话框。

注意:在对话框上单击按钮或关闭对话框时,对话框只是隐藏(缺省的),而并没有从内存中删除,如果对话框一关闭就自动删除,则在后面调用对话框的自定义函数获得输入的行数和列数时会出现严重错误

3. 对话框QWDialogHeaders 的创建和使用

3.1 对话框的生存期

对话框的生存期是指它从创建到删除的存续区间。前面介绍的设置表格行数和列数的对话框的生存期只在调用它的按钮的槽函数里,因为对话框是动态创建的,调用结束后就会被删除。

而对于图 6-6 所示的设置表头标题对话框,我们希望在主窗口里首次调用时创建它,对话框关闭时并不删除,只是隐藏,下次调用时再次显示此对话框。

只有在主窗口释放时该对话框才释放,所以这个对话框的生存期在主窗口存续期间。

3.2 QWDialogHeaders 的定义和实现

设置表头标题的对话框类是 QWDialogHeaders,它也是从 QDialog 继承的可视对话框类。其界面显示使用 QListView 组件,用 QStringListModel 变量管理字符串列表数据,构成 Model/View结构。对话框上同样有“确定”和“取消”两个按钮,设置与对话框的 accept()和 reject()槽关联。

QWDialogHeaders 类的定义如下:

#include "qwdialogheaders.h"
#include "ui_qwdialogheaders.h"#include    <QMessageBox>QWDialogHeaders::QWDialogHeaders(QWidget *parent) :QDialog(parent),ui(new Ui::QWDialogHeaders)
{ui->setupUi(this);model= new QStringListModel;ui->listView->setModel(model);
}QWDialogHeaders::~QWDialogHeaders()
{QMessageBox::information(this,"info","Setting dialog object is deleted ");delete ui;
}void QWDialogHeaders::setHeaderList(QStringList &headers)
{model->setStringList(headers);
}QStringList QWDialogHeaders::headerList()
{return  model->stringList();
}

3.3 QWDialogHeaders 对话框的使用

因为要在主窗口中重复调用此对话框,所以在 MainWindow 的 private 部分定义一个QWDialogHeaders 类型的指针变量,并且将此指针初始化设置为NULL,用于判断对话框是否已经被创建。在MainWindow中的定义如下:

QWDialogHeaders *dlgSetHeaders=NULL;//设置表头文字对话框, 一次创建,exec()重复调用

下面是主窗口工具栏上的“设置表头标题”按钮的响应代码

void MainWindow::on_actTab_SetHeader_triggered()
{//一次创建,多次调用,对话框关闭时只是隐藏if (dlgSetHeaders==NULL) //如果对象没有被创建过,就创建对象dlgSetHeaders = new QWDialogHeaders(this);if (dlgSetHeaders->headerList().count()!=theModel->columnCount()){//如果表头列数变化,重新初始化QStringList strList;for (int i=0;i<theModel->columnCount();i++)//获取现有的表头标题strList.append(theModel->headerData(i,Qt::Horizontal,Qt::DisplayRole).toString());dlgSetHeaders->setHeaderList(strList);//用于对话框初始化显示}int ret=dlgSetHeaders->exec();// 以模态方式显示对话框if (ret==QDialog::Accepted) //OK键被按下{QStringList strList=dlgSetHeaders->headerList();//获取对话框上修改后的StringListtheModel->setHorizontalHeaderLabels(strList);// 设置模型的表头标题}
}

在这段代码中,首先判断主窗口的成员变量 dlgSetHeaders 是否为 NULL,如果为 NULL(初始化为NULL),说明对话框还没有被创建,就创建对话框。
初始化的工作是获取主窗口数据模型现有的表头标题,然后调用对话框的自定义函数setHeaderList(),设置其为对话框的数据源。
使用 exec()函数模态显示对话框,然后在“确定”按钮被单击时获取对话框上输入的字符串列表,设置为主窗口数据模型的表头标题。

注意:这里在结束对话框操作后,并没有使用 delele 操作删除对话框对象,这样对话框就只是隐藏,它还在内存中。关闭对话框时不会出现析构函数里的消息提示对话框。

对话框创建时,传递主窗口的指针作为对话框的父对象,即:

dlgSetHeaders = new QWDialogHeaders(this);

所以,主窗口释放时才会自动删除此对话框对象,也就是程序退出时才删除此对话框,才会出现QWDialogHeaders 析构函数里的消息提示对话框。(此处涉及到了对象树的知识,可以参考:QT从入门到实战x篇_04_对象树及坐标系)进行了解和学习。

4. 对话框QWDialogLocate 的创建与使用

4.1 非模态对话框

前面设计的两个对话框是以模态 (Modal) 方式显示的,即用 QDialog::exec()函数显示。模态显示的对话框不允许鼠标再去单击其他窗口,直到对话框退出。
若使用 QDialog::show(),则能以非模态 (Modeless)方式显示对话框。非模态显示的对话框在显示后继续运行主程序,还可以在主窗口上操作,主窗口和非模态对话框之间可以交互控制。典型的例子是文字编辑软件里的“查找/替换”对话框。
图6-7 中的单元格定位与文字设置对话框以非模态方式显示,对话框类是 QWDialogLocate,它有如下的一些功能。

  • 主窗口每次调用此对话框时,就会创建此对话框对象,并以 StayOnTop 的方式显示,对话框关闭时自动删除。
  • 在对话框中可以定位主窗口上 TableView 组件的单元格,并设置单元格的文字。
  • 在主窗口的 TableView 组件中单击鼠标时,如果对话框已创建,则自动更新对话框上单元格的行号和列号 SpinBox 组件的值。
  • 主窗口上的 actTab_Locate 用于调用对话框,调用时actTab_Locate 设置为禁用,当对话框关闭时自动使能actTab_Locate。这样避免对话框显示时,在主窗口上再次单击“定位单元格”按钮,而在对话框关闭和释放后,按钮又恢复为可用。

对话框QWDialogLocate 的类定义代码如下,各接口函数的意义和实现在后面介绍。

#ifndef QWDIALOGLOCATE_H
#define QWDIALOGLOCATE_H#include <QDialog>namespace Ui {
class QWDialogLocate;
}class QWDialogLocate : public QDialog
{Q_OBJECTprivate:void closeEvent(QCloseEvent *event);void showEvent(QShowEvent *event);public:explicit QWDialogLocate(QWidget *parent = 0);~QWDialogLocate();void    setSpinRange(int rowCount, int colCount); //设置最大值void    setSpinValue(int rowNo, int colNo);//设置初始值private slots:void on_btnSetText_clicked();private:Ui::QWDialogLocate *ui;
};#endif // QWDIALOGLOCATE_H

4.2 对话框的创建与调用,对话框与主窗口的交互

对话框QWDialogLocate 是从QDialog 继承而来的可视化设计的对话框类,其界面设计不再详述。为了在主窗口中也能操作对话框,需要保留对话框实例对象名,所以在 MainWindow 定义对话框QWDialogLocate 的一个指针 dlgLocate,并初始化为NULL。

QWDialogLocate *dlgLocate=NULL;

主窗口上的 actTab_Locate 用于调用此对话框,其 triggered()信号槽函数代码如下:

void MainWindow::on_actTab_Locate_triggered()
{//创建 StayOnTop的对话框,对话框关闭时自动删除//通过控制actTab_Locate的enable属性避免重复点击ui->actTab_Locate->setEnabled(false);dlgLocate = new QWDialogLocate(this); //创建对话框,传递指针dlgLocate->setAttribute(Qt::WA_DeleteOnClose); //对话框关闭时自动删除对话框对象,用于不需要读取返回值的对话框Qt::WindowFlags    flags=dlgLocate->windowFlags(); //获取已有flags
//对话框设置为固定大小和StayOnTop
//    dlgLocate->setWindowFlags(flags |Qt::MSWindowsFixedSizeDialogHint |Qt::WindowStaysOnTopHint); //设置对话框固定大小,StayOnTopdlgLocate->setWindowFlags(flags | Qt::WindowStaysOnTopHint); //设置对话框固定大小,StayOnTop
//对话框初始化设置dlgLocate->setSpinRange(theModel->rowCount(),theModel->columnCount());QModelIndex curIndex=theSelection->currentIndex();if (curIndex.isValid())dlgLocate->setSpinValue(curIndex.row(),curIndex.column());dlgLocate->show(); //非模态显示对话框
}

在这段代码中,使用QWidget::setAttribute()函数将对话框设置为关闭时自动删除

dlgLocate->setAttribute(Qt::WA_DeleteOnClose);

setAttribute()用于对窗体的一些属性进行设置,当设置为 Qt::WA_DeleteOnClose 时,窗口关闭时会自动删除,以释放内存。这与前面两个对话框是不同的,前面两个对话框在关闭时缺省是隐藏自己,除非显式地使用 delete 进行删除。
程序还调用QWidget::setWindowFlags()将对话框设置为StayOnTop 显示

dlgLocate->setWindowFlags(flags | Qt::WindowStaysOnTopHint);

对话框窗口效果设置后,再设置其初始数据,然后调用 show()显示对话框。显示对话框后,主程序继续运行,不会等待对话框的返回结果。鼠标可以操作主窗口上的界面,但是因为actTab_Locate 被禁用了,不能再重复单击“定位单元格”按钮。

4.3 对话框中操作主窗口

在对话框上单击“设定文字”按钮,会在主窗口中定位到指定的单元格,并设定为输入的文字,按钮的代码如下:

void QWDialogLocate::on_btnSetText_clicked()
{//定位到单元格,并设置字符串int row=ui->spinBoxRow->value(); //行号int col=ui->spinBoxColumn->value();//列号MainWindow *parWind = (MainWindow*)parentWidget(); //获取主窗口parWind->setACellText(row,col,ui->edtCaption->text()); //设置单元格文字if (ui->chkBoxRow->isChecked()) //行增ui->spinBoxRow->setValue(1+ui->spinBoxRow->value());if (ui->chkBoxColumn->isChecked()) //列增ui->spinBoxColumn->setValue(1+ui->spinBoxColumn->value());
}

想要在对话框中操作主窗口,就需要获取主窗口对象,调用主窗口的函数并传递参数。在上面的代码中,通过下面一行语句获得主窗口对象:

MainWindow *parWind = (MainWindow*)parentWidget(); //获取主窗口

parentWidget()是QWidget 类的一个函数,指向父窗口。在创建此对话框时,将主窗口的指针传递给对话框的构造函数,即:

dlgLocate = new QWDialogLocate(this);

所以,对话框的 parentWidget 指向主窗口。

然后调用主窗口的一个自定义的 public 函数 setACellText(),传递行号、列号和字符串,由主窗口更新指定单元格的文字。下面是主窗口的setACellText()函数的代码。

void MainWindow::setACellText(int row, int column, QString text)
{//定位到单元格,并设置字符串QModelIndex index=theModel->index(row,column);//获取模型索引theSelection->clearSelection(); //清除现有选择theSelection->setCurrentIndex(index,QItemSelectionModel::Select); //定位到单元格theModel->setData(index,text,Qt::DisplayRole);//设置单元格字符串
}

这样就实现了在对话框里对主窗口进行的操作,主要是获取主窗口对象,然后调用相应的函数

4.4 主窗口中操作对话框

在主窗口上用鼠标单击 TableView 组件的某个单元格时,如果单元格定位对话框 dlgLocate 已经存在,就将单元格的行号、列号更新到对话框上,实现代码如下:

void MainWindow::on_tableView_clicked(const QModelIndex &index)
{//单击单元格时,将单元格的行号、列号设置到对话框上if (dlgLocate!=NULL) //对话框存在dlgLocate->setSpinValue(index.row(),index.column());
}

因为主窗口中定义了对话框的指针,只要它不为 NULL,就说明对话框存在,调用对话框的-个自定义函数 setSpinValue(),刷新对话框显示界面。QWDialogLocate 的 setSpinValue()函数实现如下:

void QWDialogLocate::setSpinValue(int rowNo, int colNo)
{//设置SpinBox数值ui->spinBoxRow->setValue(rowNo);ui->spinBoxColumn->setValue(colNo);
}

4.5 窗口的CloseEvent事件及事件简介

对话框和主窗口之间互相操作的关键是要有对方对象的指针,然后才能传递参数并调用对方的函数。在对话框关闭时,还需要做一些处理: 将主窗口的 actTab_Locate 重新设置为使能,将主窗口的指向对话框的指针 dlgLocate 重新设置为NULL。
由于对话框 dlgLocate 是以非模态方式运行的,程序无法等待对话框结束后作出响应,但是可以利用窗口的 CloseEvent 事件。

事件(event)是由窗口系统产生的由某些操作触发的特殊函数,例如鼠标操作、键盘操作的一些事件,还有窗口显示、关闭、绘制等相关的事件。从QWidget 继承的窗口部件常用的事件函数有如下几种。

  • closeEvent(): 窗口关闭时触发的事件,通常在此事件做窗口关闭时的一些处理,例如显示
    一个对话框询问是否关闭窗口。
  • showEvent():窗口显示时触发的事件。
  • paintEvent():窗口绘制事件,第8章介绍绘图时会用到。mouseMoveEvent(): 鼠标移动事件。
  • mousePressEvent():鼠标键按下事件
  • mouseReleaseEvent(): 鼠标键释放事件。
  • keyPressEvent():键盘按键按下事件。
  • keyReleaseEvent():键盘按键释放事件

要利用某个事件进行一些处理,需要在窗口类里重定义事件函数并编写响应代码。在后面的例子中,将逐渐演示一些事件的用法。

在本例中,要利用对话框的 closeEvent()事件,在类定义中声明了此事件的函数,其实现代码如下:

void QWDialogLocate::closeEvent(QCloseEvent *event)
{ //窗口关闭事件,关闭时释放本窗口MainWindow *parWind = (MainWindow*)parentWidget(); //获取父窗口指针parWind->setActLocateEnable(true);//使能 actTab_LocateparWind->setDlgLocateNull(); //将窗口指针设置为NULL
}

在 closeEvent()事件里,调用主窗口的两个函数,将 actTab_Locate 重新使能,将主窗口内指向对话框的指针设置为NULL。主窗口中这两个函数的实现代码如下:

void MainWindow::setActLocateEnable(bool enable)
{ui->actTab_Locate->setEnabled(enable);
}
void MainWindow::setDlgLocateNull()
{dlgLocate=NULL;
}

利用 closeEvent()事件,可以询问窗口是否退出,例如为主窗口添加 closeEvent()事件的处理代码如下:

void MainWindow::closeEvent(QCloseEvent *event)
{ //窗口关闭时询问是否退出QMessageBox::StandardButton result=QMessageBox::question(this, "确认", "确定要退出本程序吗?",QMessageBox::Yes|QMessageBox::No |QMessageBox::Cancel,QMessageBox::No);if (result==QMessageBox::Yes)event->accept();elseevent->ignore();
}

这样,主窗口关闭时就会出现一个询问对话框,如果不单击“Yes”按钮,程序就不关闭;否则应用程序结束。

5. 利用信号与槽实现对话框及主窗口交互操作

前面设计的 QWDialogLocate 对话框与主窗口之间的交互采用互相引用的方式,实现起来比较复杂。另外一种实现方式就是利用 Qt 的信号与槽机制,设计相应的信号和槽,将信号与槽关联起来,在进行某个操作时发射信号,槽函数自动响应。
对MainWindow和QWDialogLocate 稍作修改,采用信号与槽机制实现交互操作下面是MainWindow 类定义中与此相关的定义,包括两个槽函数和一个信号。


class MainWindow : public QMainWindow
{public slots:void    setACellText(int row, int column, QString &text);//设置一个单元格的内容void    setActLocateEnable(bool enable);//设置actTab_Locate的enabled属性signals:void    cellIndexChanged(int rowNo, int colNo);//当前单元格发生变化};

两个槽函数是对话框操作主窗口时,主窗口作出的响应。信号是主窗口上 tableView 的当前单元格发生变化时发射的一个信号,以便对话框作出响应。
下面是两个槽函数的实现,以及 tableView 的 clicked()信号的槽函数里发射自定义信号的代码,代码中都无须引用对话框对象。

void MainWindow::setACellText(int row, int column, QString &text)
{//定位到单元格,并设置字符串QModelIndex index=theModel->index(row,column);//获取模型索引theSelection->clearSelection(); //清除现有选择theSelection->setCurrentIndex(index,QItemSelectionModel::Select); //定位到单元格theModel->setData(index,text,Qt::DisplayRole);//设置单元格字符串
}void MainWindow::setActLocateEnable(bool enable)
{ //设置actTab_Locate的enable属性ui->actTab_Locate->setEnabled(enable);
}void MainWindow::on_tableView_clicked(const QModelIndex &index)
{//单击单元格时,将单元格的行号、列号设置到对话框上emit cellIndexChanged(index.row(),index.column());
}

在主窗口上,“定位单元格”按钮的响应代码与前面有较大的差别。

void MainWindow::on_actTab_Locate_triggered()
{//创建 StayOnTop的对话框,对话框关闭时自动删除//通过控制actTab_Locate的enable属性避免重复点击
//    ui->actTab_Locate->setEnabled(false);QWDialogLocate  *dlgLocate;//定位单元格对话框,show()调用,关闭时自己删除dlgLocate = new QWDialogLocate(this); //创建对话框,传递指针dlgLocate->setAttribute(Qt::WA_DeleteOnClose); //对话框关闭时自动删除对话框对象,用于不需要读取返回值的对话框Qt::WindowFlags    flags=dlgLocate->windowFlags(); //获取已有flags
//对话框设置为固定大小和StayOnTop
//    dlgLocate->setWindowFlags(flags |Qt::MSWindowsFixedSizeDialogHint |Qt::WindowStaysOnTopHint); //设置对话框固定大小,StayOnTopdlgLocate->setWindowFlags(flags | Qt::WindowStaysOnTopHint); //设置对话框固定大小,StayOnTop
//对话框初始化设置dlgLocate->setSpinRange(theModel->rowCount(),theModel->columnCount());QModelIndex curIndex=theSelection->currentIndex();if (curIndex.isValid())dlgLocate->setSpinValue(curIndex.row(),curIndex.column());//对话框释放信号,设置单元格文字connect(dlgLocate,SIGNAL(changeCellText(int,int,QString&)),this,SLOT(setACellText(int,int,QString&)));//对话框是否信号,设置action的属性connect(dlgLocate,SIGNAL(changeActionEnable(bool)),this,SLOT(setActLocateEnable(bool)));//主窗口是否信号,修改对话框上的spinBox的值connect(this,SIGNAL(cellIndexChanged(int,int)),dlgLocate,SLOT(setSpinValue(int,int)));dlgLocate->show(); //非模态显示对话框
//    this->show();
}

在这里,对话框变量声明为了局部变量,不再需要在主窗口类里保存对话框的指针。这段代码的关键是设置了3 对信号与槽的关联。
在QWDialogLocate 类定义中,与信号和槽相关的定义如下。

class QWDialogLocate : public QDialog
{
private:void closeEvent(QCloseEvent *event);void showEvent(QShowEvent *event);public slots:void    setSpinValue(int rowNo, int colNo);//响应主窗口信号,设置spinBox的值signals:void    changeCellText(int row, int column, QString &text); //释放信号,定位单元格,并设置文字void    changeActionEnable(bool en); //是否信号,改变action的enable
};

QWDialogLocate 自定义了一个槽函数和两个信号,还增加了 showEvent()事件的处理,用于对话框显示时发射信号使主窗口的 actTab_Locate 失效。这些槽函数,以及发射信号的实现代码如下,代码中没有出现对主窗口的引用。

void QWDialogLocate::closeEvent(QCloseEvent *event)
{ //窗口关闭 event,释放信号使 actTab_Locate 能用Q_UNUSED(event)emit changeActionEnable(true);
}void QWDialogLocate::showEvent(QShowEvent *event)
{//窗口显示 event,释放信号使 actTab_Locate 不能用Q_UNUSED(event)emit changeActionEnable(false);
}
void QWDialogLocate::setSpinValue(int rowNo, int colNo)
{//响应主窗口信号,更新spinBox的值ui->spinBoxRow->setValue(rowNo);ui->spinBoxColumn->setValue(colNo);
}void QWDialogLocate::on_btnSetText_clicked()
{//定位到单元格,并设置字符串int row=ui->spinBoxRow->value(); //行号int col=ui->spinBoxColumn->value();//列号QString text=ui->edtCaption->text();//文字emit changeCellText(row,col,text);//释放信号if (ui->chkBoxRow->isChecked()) //行增ui->spinBoxRow->setValue(1+ui->spinBoxRow->value());if (ui->chkBoxColumn->isChecked()) //列增ui->spinBoxColumn->setValue(1+ui->spinBoxColumn->value());
}

经过这样修改后的程序,能实现与前面的实例完全相同的主窗口与对话框交互的功能,但是与前面互相引用的方式不同,这里使用 Qt 的信号与槽的机制,无须获取对方的指针,程序结构上更简单一些。

大家是不是看到这里就有些懵逼了,没事,后期真正涉及到主窗口与自定义对话框的交互,那就用信号槽的方式,整个源码及结构我放在底下。

6. 源码

6.1 程序框架

在这里插入图片描述

6.2 可视化UI设计

6.2.1 qwdialogsize.ui

在这里插入图片描述

6.2.2 qwdialogheaders.ui

在这里插入图片描述

6.2.3 qwdialoglocate.ui

在这里插入图片描述

6.2.4 mainwindow.ui

在这里插入图片描述

6.3 代码

6.3.1 qwdialogsize

(1)qwdialogsize.h

#ifndef QWDIALOGSIZE_H
#define QWDIALOGSIZE_H#include <QDialog>namespace Ui {
class QWDialogSize;
}class QWDialogSize : public QDialog
{Q_OBJECTpublic:explicit QWDialogSize(QWidget *parent = 0);~QWDialogSize();int rowCount();//获取对话框输入的行数int columnCount();//获取对话框输入的列数void    setRowColumn(int row, int column); //初始对话框上两个SpinBox的值private slots:private:Ui::QWDialogSize *ui;
};#endif // QWDIALOGSIZE_H

(2)qwdialogsize.cpp

#include "qwdialogsize.h"
#include "ui_qwdialogsize.h"#include    <QMessageBox>QWDialogSize::QWDialogSize(QWidget *parent) :QDialog(parent),ui(new Ui::QWDialogSize)
{ui->setupUi(this);
}QWDialogSize::~QWDialogSize()
{
//    QMessageBox::information(this,"提示","设置表格行列数对话框被删除");delete ui;
}int QWDialogSize::rowCount()
{ //用于主窗口调用获得行数的输入值return  ui->spinBoxRow->value();
}int QWDialogSize::columnCount()
{//用于主窗口调用获得列数的输入值return  ui->spinBoxColumn->value();
}void QWDialogSize::setRowColumn(int row, int column)
{ //初始化数据显示ui->spinBoxRow->setValue(row);ui->spinBoxColumn->setValue(column);
}

6.3.2 qwdialogheaders

(1)qwdialogheaders.h

#ifndef QWDIALOGHEADERS_H
#define QWDIALOGHEADERS_H#include <QDialog>#include    <QStringListModel>namespace Ui {
class QWDialogHeaders;
}class QWDialogHeaders : public QDialog
{Q_OBJECTprivate:QStringListModel  *model;public:explicit QWDialogHeaders(QWidget *parent = 0);~QWDialogHeaders();void    setHeaderList(QStringList& headers);QStringList headerList();
private:Ui::QWDialogHeaders *ui;
};#endif // QWDIALOGHEADERS_H

(2)qwdialogheaders.cpp

#include "qwdialogheaders.h"
#include "ui_qwdialogheaders.h"QWDialogHeaders::QWDialogHeaders(QWidget *parent) :QDialog(parent),ui(new Ui::QWDialogHeaders)
{ui->setupUi(this);model= new QStringListModel;ui->listView->setModel(model);
}QWDialogHeaders::~QWDialogHeaders()
{delete ui;
}void QWDialogHeaders::setHeaderList(QStringList &headers)
{model->setStringList(headers);
}QStringList QWDialogHeaders::headerList()
{return  model->stringList();
}

6.3.3 qwdialoglocate

(1)qwdialoglocate.h

#ifndef QWDIALOGLOCATE_H
#define QWDIALOGLOCATE_H#include <QDialog>
namespace Ui {
class QWDialogLocate;
}class QWDialogLocate : public QDialog
{Q_OBJECTprivate:void closeEvent(QCloseEvent *event);void showEvent(QShowEvent *event);public:explicit QWDialogLocate(QWidget *parent = 0);~QWDialogLocate();void    setSpinRange(int rowCount, int colCount); //设置最大值,用于初始化private slots:void on_btnSetText_clicked();public slots:void    setSpinValue(int rowNo, int colNo);//响应主窗口信号,设置spinBox的值signals:void    changeCellText(int row, int column, QString &text); //释放信号,定位单元格,并设置文字void    changeActionEnable(bool en); //是否信号,改变action的enableprivate:Ui::QWDialogLocate *ui;
};#endif // QWDIALOGLOCATE_H

(2)qwdialoglocate.cpp

#include "qwdialoglocate.h"
#include "ui_qwdialoglocate.h"#include    <QCloseEvent>
#include    "mainwindow.h"void QWDialogLocate::closeEvent(QCloseEvent *event)
{ //窗口关闭 event,释放信号使 actTab_Locate 能用Q_UNUSED(event)emit changeActionEnable(true);
}void QWDialogLocate::showEvent(QShowEvent *event)
{//窗口显示 event,释放信号使 actTab_Locate 不能用Q_UNUSED(event)emit changeActionEnable(false);
}QWDialogLocate::QWDialogLocate(QWidget *parent) :QDialog(parent),ui(new Ui::QWDialogLocate)
{ui->setupUi(this);
}QWDialogLocate::~QWDialogLocate()
{delete ui;
}void QWDialogLocate::setSpinRange(int rowCount, int colCount)
{//设置SpinBox输入最大值ui->spinBoxRow->setMaximum(rowCount-1);ui->spinBoxColumn->setMaximum(colCount-1);
}void QWDialogLocate::setSpinValue(int rowNo, int colNo)
{//响应主窗口信号,更新spinBox的值ui->spinBoxRow->setValue(rowNo);ui->spinBoxColumn->setValue(colNo);
}void QWDialogLocate::on_btnSetText_clicked()
{//定位到单元格,并设置字符串int row=ui->spinBoxRow->value(); //行号int col=ui->spinBoxColumn->value();//列号QString text=ui->edtCaption->text();//文字emit changeCellText(row,col,text);//释放信号if (ui->chkBoxRow->isChecked()) //行增ui->spinBoxRow->setValue(1+ui->spinBoxRow->value());if (ui->chkBoxColumn->isChecked()) //列增ui->spinBoxColumn->setValue(1+ui->spinBoxColumn->value());
}

6.3.4 mainwindow

(1)mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>#include    <QLabel>
#include    <QStandardItemModel>
#include    <QItemSelectionModel>
#include    <QModelIndex>#include    "qwdialogheaders.h"
#include    "qwdialoglocate.h"class   QWDialogLocate;namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTprivate://用于状态栏的信息显示QLabel  *LabCellPos;    //当前单元格行列号QLabel  *LabCellText;   //当前单元格内容QStandardItemModel  *theModel;//数据模型QItemSelectionModel *theSelection;//Item选择模型QWDialogHeaders *dlgSetHeaders=NULL;//设置表头文字对话框, 一次创建,exec()重复调用void closeEvent(QCloseEvent *event);//关闭窗口时间,可以询问是否退出public:explicit MainWindow(QWidget *parent = 0);~MainWindow();void    selectACell(int row,int column);//选择一个单元格,由dlgLocate调用
private slots:void on_currentChanged(const QModelIndex &current, const QModelIndex &previous);void on_actTab_SetSize_triggered();void on_actTab_SetHeader_triggered();void on_actTab_Locate_triggered();void on_tableView_clicked(const QModelIndex &index);public slots:void    setACellText(int row, int column, QString &text);//设置一个单元格的内容void    setActLocateEnable(bool enable);//设置actTab_Locate的enabled属性signals:void    cellIndexChanged(int rowNo, int colNo);//当前单元格发生变化private:Ui::MainWindow *ui;};#endif // MAINWINDOW_H

(2)mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"#include    <QMessageBox>
#include    <QCloseEvent>#include    "qwdialogsize.h"void MainWindow::closeEvent(QCloseEvent *event)
{ //窗口关闭时询问是否退出QMessageBox::StandardButton result=QMessageBox::question(this, "确认", "确定要退出本程序吗?",QMessageBox::Yes|QMessageBox::No |QMessageBox::Cancel,QMessageBox::No);if (result==QMessageBox::Yes)event->accept();elseevent->ignore();
}MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);theModel = new QStandardItemModel(10,5,this); //创建数据模型theSelection = new QItemSelectionModel(theModel);//Item选择模型connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));//为tableView设置数据模型ui->tableView->setModel(theModel); //设置数据模型ui->tableView->setSelectionModel(theSelection);//设置选择模型setCentralWidget(ui->tableView); ////创建状态栏组件LabCellPos = new QLabel("当前单元格:",this);LabCellPos->setMinimumWidth(180);LabCellPos->setAlignment(Qt::AlignHCenter);LabCellText = new QLabel("单元格内容:",this);LabCellText->setMinimumWidth(200);ui->statusBar->addWidget(LabCellPos);ui->statusBar->addWidget(LabCellText);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::setActLocateEnable(bool enable)
{ //设置actTab_Locate的enable属性ui->actTab_Locate->setEnabled(enable);
}void MainWindow::selectACell(int row, int column)
{QModelIndex index=theModel->index(row,column);theSelection->clearSelection();theSelection->setCurrentIndex(index,QItemSelectionModel::Select);
}void MainWindow::setACellText(int row, int column, QString &text)
{//定位到单元格,并设置字符串QModelIndex index=theModel->index(row,column);//获取模型索引theSelection->clearSelection(); //清除现有选择theSelection->setCurrentIndex(index,QItemSelectionModel::Select); //定位到单元格theModel->setData(index,text,Qt::DisplayRole);//设置单元格字符串
}void MainWindow::on_currentChanged(const QModelIndex &current, const QModelIndex &previous)
{Q_UNUSED(previous)if (current.isValid()) //当前模型索引有效{LabCellPos->setText(QString::asprintf("当前单元格:%d行,%d列",current.row(),current.column())); //显示模型索引的行和列号QStandardItem   *aItem;aItem=theModel->itemFromIndex(current); //从模型索引获得Itemthis->LabCellText->setText("单元格内容:"+aItem->text()); //显示item的文字内容}
}void MainWindow::on_actTab_SetSize_triggered()
{ //模态对话框,动态创建,用过后删除QWDialogSize    *dlgTableSize=new QWDialogSize(this); //创建对话框
//   dlgTableSize->setAttribute(Qt::WA_DeleteOnClose);
//对话框关闭时自动删除对话框对象,用于不需要读取返回值的对话框
//如果需要获取对话框的返回值,不能设置该属性,可以在调用完对话框后删除对话框Qt::WindowFlags    flags=dlgTableSize->windowFlags();dlgTableSize->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); //设置对话框固定大小dlgTableSize->setRowColumn(theModel->rowCount(),theModel->columnCount()); //对话框数据初始化int ret=dlgTableSize->exec();// 以模态方式显示对话框,用户关闭对话框时返回 DialogCode值if (ret==QDialog::Accepted) //OK键被按下,对话框关闭,若设置了setAttribute(Qt::WA_DeleteOnClose),对话框被释放,无法获得返回值{ //OK键被按下,获取对话框上的输入,设置行数和列数int cols=dlgTableSize->columnCount();theModel->setColumnCount(cols);int rows=dlgTableSize->rowCount();theModel->setRowCount(rows);}delete dlgTableSize; //删除对话框
}void MainWindow::on_actTab_SetHeader_triggered()
{//一次创建,多次调用,对话框关闭时只是隐藏if (dlgSetHeaders==NULL) //如果对象没有被创建过,就创建对象dlgSetHeaders = new QWDialogHeaders(this);if (dlgSetHeaders->headerList().count()!=theModel->columnCount()){
//只需在创建时传递参数给对话框,由于对话框只是隐藏,界面内容保存QStringList strList;for (int i=0;i<theModel->columnCount();i++)//获取现有的表头标题strList.append(theModel->headerData(i,Qt::Horizontal,Qt::DisplayRole).toString());dlgSetHeaders->setHeaderList(strList);//用于对话框初始化显示}int ret=dlgSetHeaders->exec();// 以模态方式显示对话框if (ret==QDialog::Accepted) //OK键被按下{QStringList strList=dlgSetHeaders->headerList();//获取对话框上修改后的StringListtheModel->setHorizontalHeaderLabels(strList);// 设置模型的表头标题}
}void MainWindow::on_actTab_Locate_triggered()
{//创建 StayOnTop的对话框,对话框关闭时自动删除//通过控制actTab_Locate的enable属性避免重复点击
//    ui->actTab_Locate->setEnabled(false);QWDialogLocate  *dlgLocate;//定位单元格对话框,show()调用,关闭时自己删除dlgLocate = new QWDialogLocate(this); //创建对话框,传递指针dlgLocate->setAttribute(Qt::WA_DeleteOnClose); //对话框关闭时自动删除对话框对象,用于不需要读取返回值的对话框Qt::WindowFlags    flags=dlgLocate->windowFlags(); //获取已有flags
//对话框设置为固定大小和StayOnTop
//    dlgLocate->setWindowFlags(flags |Qt::MSWindowsFixedSizeDialogHint |Qt::WindowStaysOnTopHint); //设置对话框固定大小,StayOnTopdlgLocate->setWindowFlags(flags | Qt::WindowStaysOnTopHint); //设置对话框固定大小,StayOnTop
//对话框初始化设置dlgLocate->setSpinRange(theModel->rowCount(),theModel->columnCount());QModelIndex curIndex=theSelection->currentIndex();if (curIndex.isValid())dlgLocate->setSpinValue(curIndex.row(),curIndex.column());//对话框释放信号,设置单元格文字connect(dlgLocate,SIGNAL(changeCellText(int,int,QString&)),this,SLOT(setACellText(int,int,QString&)));//对话框是否信号,设置action的属性connect(dlgLocate,SIGNAL(changeActionEnable(bool)),this,SLOT(setActLocateEnable(bool)));//主窗口是否信号,修改对话框上的spinBox的值connect(this,SIGNAL(cellIndexChanged(int,int)),dlgLocate,SLOT(setSpinValue(int,int)));dlgLocate->show(); //非模态显示对话框
//    this->show();
}void MainWindow::on_tableView_clicked(const QModelIndex &index)
{//单击单元格时,将单元格的行号、列号设置到对话框上emit cellIndexChanged(index.row(),index.column());
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/86236.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PE启动盘和U启动盘(第三十六课)

PE启动盘和U启动盘(第三十六课) 一 WindowsPE工具盘 1. 制作WinPE镜像光盘 双击WePE64_V2.2-是-点击右下角光盘图标-选择ISO的输出位置-立即生成ISO 2. 通过光盘启动WinPE

Android平台GB28181设备接入端如何实现多视频通道接入?

技术背景 我们在设计Android平台GB28181设备接入模块的时候&#xff0c;有这样的场景诉求&#xff0c;一个设备可能需要多个通道&#xff0c;常见的场景&#xff0c;比如车载终端&#xff0c;一台设备&#xff0c;可能需要接入多个摄像头&#xff0c;那么这台车载终端设备可以…

QT创建项目

可选择CMake或qmake

实例036 使窗体标题栏文字右对齐

实例说明 窗口标题栏中的文字是窗口的重要说明&#xff0c;该文字可以标示窗口的功能、状态或名称等信息&#xff0c;一般该文字是居左显示的&#xff0c;在本例中设计一个标题栏文字右对齐的窗口。本实例运行结果如图1.36所示。 技术要点 在C# 2.0中实现这一功能非常容易&am…

【Spring】-Spring的IoC和DI

作者&#xff1a;学Java的冬瓜 博客主页&#xff1a;☀冬瓜的主页&#x1f319; 专栏&#xff1a;【Framework】 主要内容&#xff1a;什么是spring&#xff1f;IoC容器是什么&#xff1f;如何使代码解耦合&#xff1f;IoC的核心原理&#xff0c;IoC的优点。依赖注入/对象装配/…

【C++基础(九)】C++内存管理--new一个对象出来

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; C内存管理 1. 前言2. new2.1 new的使用方法2.2 …

MIT 6.830数据库系统 -- lab six

MIT 6.830数据库系统 -- lab six 项目拉取引言steal/no-force策略redo log与undo log日志格式和检查点 开始回滚练习1&#xff1a;LogFile.rollback() 恢复练习2&#xff1a;LogFile.recover() 测试结果疑问点分析 项目拉取 原项目使用ant进行项目构建&#xff0c;我已经更改为…

Nodejs安装及环境变量配置(修改全局安装依赖工具包和缓存文件夹及npm镜像源)

本机环境&#xff1a;win11家庭中文版 一、官网下载 二、安装 三、查看nodejs及npm版本号 1、查看node版本号 node -v 2、查看NPM版本号&#xff08;安装nodejs时已自动安装npm&#xff09; npm -v 四、配置npm全局下载工具包和缓存目录 1、查看安装目录 在本目录下创建no…

【学习日记】【FreeRTOS】手动任务切换详解

前言 本文是关于 FreeRTOS 中实现两个任务轮流切换并执行的代码详解。目前不支持优先级&#xff0c;仅实现两个任务轮流切换。 一、任务的自传 任务从生到死的过程究竟是怎么样的呢&#xff1f;&#xff08;其实也没死&#xff09;&#xff0c;这个问题一直困扰着我&#xf…

【前端 | CSS】滚动到底部加载,滚动监听、懒加载

背景 在日常开发过程中&#xff0c;我们会遇到图片懒加载的功能&#xff0c;基本原理是&#xff0c;滚动条滚动到底部后再次获取数据进行渲染。 那怎么判断滚动条是否滚动到底部呢&#xff1f;滚动条滚动到底部触发时间的时机和方法又该怎样定义&#xff1f; 针对以上问题我…

关于技术转管理角色的认知

软件质量保障&#xff1a;所寫即所思&#xff5c;一个阿里质量人对测试的所感所悟。 程序员发展的岔路口 技术人做了几年专业工作之后&#xff0c;会来到一个重要的“分岔路口”&#xff0c;一边是专业的技术路线&#xff0c;一边是技术团队的管理路线。不少人就开始犯难&…

redis 数据结构(一)

Redis 为什么那么快 redis是一种内存数据库&#xff0c;所有的操作都是在内存中进行的&#xff0c;还有一种重要原因是&#xff1a;它的数据结构的设计对数据进行增删查改操作很高效。 redis的数据结构是什么 redis数据结构是对redis键值对值的数据类型的底层的实现&#xff0c…

网站SSL安全证书是什么及其重要性

网站SSL安全证书具体来说是一个数字文件&#xff0c;是由受信任的数字证书颁发机构&#xff08;CA机构&#xff09;进行审核颁发的&#xff0c;其中包含CA发布的信息&#xff0c;该信息表明该网站已使用加密连接进行了安全保护。 网站SSL安全证书也被称为SSL证书、https证书和…

CosmosAI欧盟数字超算新时代战略合作签约仪式在伦敦举行

据英国权威媒体获悉&#xff0c;由分布式超算网络服务商CosmosAI主办的欧盟数字超算新时代战略合作签约仪式将于8月14日英国伦敦历史悠久的莱福士OWO酒店隆重举办&#xff0c;该酒店曾作为爱德华七世国王加冕仪式以及丘吉尔二战办公室享誉盛名。 本次活动CosmosAI基金会联合创…

护网专题简单介绍

护网专题简单介绍 一、护网红蓝队介绍1.1、网络安全大事件1.2、护网行动由来1.3、护网行动中的角色二、红队介绍2.1、红队所需技能2.2、红队攻击流程 三、蓝队介绍3.1、蓝队所需技能3.2、蓝队防守四阶段3.3、蓝队前期准备 四、常见安全厂商介绍4.1、常见安全厂商 五、常见安全产…

【vue3】基础知识点-pinia

学习vue3&#xff0c;都会从基础知识点学起。了解setup函数&#xff0c;ref&#xff0c;recative&#xff0c;watch、computed、pinia等如何使用 今天说vue3组合式api&#xff0c;pinia 戳这里&#xff0c;跳转pinia中文文档 官网的基础示例中提供了三种写法 1、选择式api&a…

树莓派命令行运行调用音频文件的函数,不报错,没有声音解决办法

树莓派接上音频首先需要切换音频不是HDMI&#xff0c;然后可以双击运行wav文件可以播放&#xff0c;但是&#xff1a; 命令行直接运行wav文件报错&#xff1a; Playing WAVE twzc.wav : Signed 16 bit Little Endian, Rate 16000 Hz, Mono命令行运行main方法也是无法播放&am…

Zebec Protocol 将进军尼泊尔市场,通过 Zebec Card 推动地区金融平等

流支付正在成为一种全新的支付形态&#xff0c;Zebec Protocol 作为流支付的主要推崇者&#xff0c;正在积极的推动该支付方案向更广泛的应用场景拓展。目前&#xff0c;Zebec Protocol 成功的将流支付应用在薪酬支付领域&#xff0c;并通过收购 WageLink 将其纳入旗下&#xf…

消息中间件 —— 初识Kafka

文章目录 1、Kafka简介1.1、消息队列1.1.1、为什么要有消息队列&#xff1f;1.1.2、消息队列1.1.3、消息队列的分类1.1.4、p2p 和 发布订阅MQ的比较1.1.5、消息系统的使用场景1.1.6、常见的消息系统 1.2、Kafka简介1.2.1、简介1.2.2、设计目标1.2.3、kafka核心的概念 2、Kafka的…

git 报错 protocol ‘https‘ is not supported解决

报错原因&#xff1a;选择不了其他分支代码&#xff0c;甚至都看不到其他分支&#xff0c;我这边解决了两次报错&#xff0c;情况如下&#xff1a; 第一种报错&#xff1a; idea中刷新分支报错如下&#xff1a; Fetch Failed protocol https is not supported 话不多说&#…