Qt学习(五)自定义对话框,多窗口开发---添加设计师类, MDI多窗口开发
一 对话框
- 实现功能:打开文件,选择目录,保存文件,选择颜色,选择字体,输入信息,
消息提示框
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButtonSelectOneFile_clicked();void on_pushButtonSelectMultiFile_clicked();void on_pushButtonSelectRoot_clicked();void on_pushButtonSaveFile_clicked();void on_pushButtonColor_clicked();void on_pushButtonFont_clicked();void on_pushButtonInputString_clicked();void on_pushButtonInputInt_clicked();void on_pushButtonInputFloat_clicked();void on_pushButtonSelectItem_clicked();void on_pushButtonQuestion_clicked();void on_pushButtonMessage_clicked();void on_pushButtonWarning_clicked();void on_pushButtonWarningSerious_clicked();void on_pushButtonVersion_clicked();void on_pushButtonVersionQT_clicked();void on_pushButton_clicked();private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QTextStream>
#include <QColorDialog>
#include <QFontDialog>
#include <QInputDialog>
#include <QMessageBox>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButtonSelectOneFile_clicked()
{QString filename = QFileDialog::getOpenFileName(this,"选择一个文件",QDir::currentPath(),"文本文件(*txt);;C/C++文件(*.h *.c *.cpp);; 图片文件(*.jpg *.png *.gif);;所有文件(*.*)");if(!filename.isEmpty()){ui->plainTextEdit->appendPlainText(filename);}
}void MainWindow::on_pushButtonSelectMultiFile_clicked()
{QStringList filename = QFileDialog::getOpenFileNames(this,"选择多个文件",QDir::currentPath(),"文本文件(*txt);;C/C++文件(*.h *.c *.cpp);; 图片文件(*.jpg *.png *.gif);;所有文件(*.*)");if(filename.count() > 0){for(int i = 0; i < filename.count() ; i++)ui->plainTextEdit->appendPlainText(filename[i]);}
}void MainWindow::on_pushButtonSelectRoot_clicked()
{QString filename = QFileDialog::getExistingDirectory(this,"选择一个目录",QDir::currentPath(),QFileDialog::ShowDirsOnly);if(!filename.isEmpty()){ui->plainTextEdit->appendPlainText(filename);}
}void MainWindow::on_pushButtonSaveFile_clicked()
{QString filename = QFileDialog::getSaveFileName(this,"保存文件",QDir::currentPath(),"文本文件(*txt);;C/C++文件(*.h *.c *.cpp);; 图片文件(*.jpg *.png *.gif);;所有文件(*.*)");if(!filename.isEmpty()){//把文本编辑器的内容保存到文本QFile qfile(filename);if(! qfile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)){return;}QTextStream stream(&qfile);stream << ui->plainTextEdit->toPlainText();qfile.close();ui->plainTextEdit->appendPlainText("已保存到:" + filename);}
}void MainWindow::on_pushButtonColor_clicked()
{QPalette pal = ui->plainTextEdit->palette(); //获取文本框的调色板QColor textColor = pal.color(QPalette::Text); //获取文本框里面的本文的颜色//调用颜色对话框QColor color = QColorDialog::getColor(textColor, //初始颜色this, //父窗口"选择文本颜色"); //显示信息if(color.isValid()){pal.setColor(QPalette::Text,color);ui->plainTextEdit->setPalette(pal);}
}void MainWindow::on_pushButtonFont_clicked()
{QFont currentFont = ui->plainTextEdit->font();bool ok = false;//调用字体选择对话框QFont font = QFontDialog::getFont(&ok,currentFont);if(ok){ui->plainTextEdit->setFont(font);}
}void MainWindow::on_pushButtonInputString_clicked()
{bool ok = false;//QLineEdit::Normal:一边输入一边显示//QLineEdit::NoEcho 输入不显示,如密码//QLineEdit::Password 密码输入方式,输入的时候显示掩码,离开显示星号QString str = QInputDialog::getText(this,"输入文本对话框","请输入姓名:",QLineEdit::Normal,"ROOK", //默认输入&ok); //是否输入成功if(ok && !str.isEmpty()){ui->plainTextEdit->appendPlainText(str);}
}void MainWindow::on_pushButtonInputInt_clicked()
{bool ok = false;int value = QInputDialog::getInt(this,"输入整数对话框","请输入字体大小:",ui->plainTextEdit->font().pointSize(), //默认输入10,80, //输入整数的最大最小值1,&ok); //是否输入成功if(ok){QFont font = ui->plainTextEdit->font();font.setPointSize(value);ui->plainTextEdit->setFont(font);}
}void MainWindow::on_pushButtonInputFloat_clicked()
{bool ok = false;double value = QInputDialog::getDouble(this,"输入浮点数对话框","请输入一个浮点数:",3.14, //默认输入1.0,100, //输入整数的最大最小值2, //小数点后面位数&ok); //是否输入成功if(ok){QString str = QString::asprintf("输入了以恶搞浮点数:%.2f",value);ui->plainTextEdit->appendPlainText(str);}
}void MainWindow::on_pushButtonSelectItem_clicked()
{bool ok = false;QStringList items = {"软件工程师","硬件工程师","测试工程师"};QString str = QInputDialog::getItem(this,"列表选择对话框","请选择岗位:",items, //有哪些可选项1, //默认选项true, //是否可编辑&ok);if(ok && !str.isEmpty()){ui->plainTextEdit->appendPlainText(str);}
}void MainWindow::on_pushButtonQuestion_clicked()
{QMessageBox::StandardButton ret = QMessageBox::question(this,"问题消息框","内容已经修改,是否保存", //提示的内容QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,QMessageBox::NoButton); //默认选项if(ret == QMessageBox::Yes){ui->plainTextEdit->appendPlainText("已选择: Yes");}else if(ret == QMessageBox::No){ui->plainTextEdit->appendPlainText("已选择: No");}else if(ret == QMessageBox::Cancel){ui->plainTextEdit->appendPlainText("已选择: 取消");}else{ui->plainTextEdit->appendPlainText("未选择");}
}void MainWindow::on_pushButtonMessage_clicked()
{QMessageBox::information(this,"消息提示框","文件已经保存!", //提示的内容QMessageBox::Ok,QMessageBox::NoButton); //默认选项
}void MainWindow::on_pushButtonWarning_clicked()
{QMessageBox::warning(this,"消息提示框","文件被篡改!"); //默认选项
}void MainWindow::on_pushButtonWarningSerious_clicked()
{QMessageBox::critical(this,"危机消息提示框","系统即将重启!"); //默认选项
}void MainWindow::on_pushButtonVersion_clicked()
{QMessageBox::about(this,"About消息提示框","hahahha!"); //默认选项
}void MainWindow::on_pushButtonVersionQT_clicked()
{QMessageBox::aboutQt(this,"aboutQt消息提示框"); //默认选项
}void MainWindow::on_pushButton_clicked()
{ui->plainTextEdit->clear();
}
二 自定义对话框 使用类对象的对外的接口完成窗口之间的通讯
2.1 调整行列的自定义对话框
- 步骤:Add new->新建设计师类()->设计当前类的窗口样式->定义接口
- 功能:单击调整行列按钮,弹出对话框,修改spinbox中对应的行列数,点击确定,对应表格中的行列会发生变化
- mainwindow.h 主函数调用的时候,需要包含该类的头文件
#include "dialogresize.h"
,定义接口 - 知识点:点击确定按钮,或者关闭按钮,如果不需要,实现的时候
accept()
或者reject() / close()
即可
private:Ui::MainWindow *ui;DialogResize *dialogResize;DialogHeader *dialogHeader;DialogLocation *dialogLocation;
“dialogresize.h”
#ifndef DIALOGRESIZE_H
#define DIALOGRESIZE_H#include <QDialog>namespace Ui {
class DialogResize;
}class DialogResize : public QDialog
{Q_OBJECTpublic:explicit DialogResize(QWidget *parent = nullptr);~DialogResize();int getRow();int getCol();
private slots:void on_pushButtonok_clicked();void on_pushButtonCancle_clicked();private:Ui::DialogResize *ui;
};#endif // DIALOGRESIZE_H
“dialogresize.cpp”
#include "dialogresize.h"
#include "ui_dialogresize.h"DialogResize::DialogResize(QWidget *parent) :QDialog(parent),ui(new Ui::DialogResize)
{ui->setupUi(this);
}DialogResize::~DialogResize()
{delete ui;
}int DialogResize::getRow()
{return ui->spinBoxRow->value();
}int DialogResize::getCol()
{return ui->spinBoxCol->value();
}void DialogResize::on_pushButtonok_clicked()
{accept();
}void DialogResize::on_pushButtonCancle_clicked()
{reject();
}
2.2 编辑表头按钮
- 功能:点击编辑表头按钮,对话框中会同步显示出已有的表头信息,如果在对话框中编辑表头,点击确定,那么对话框将关闭,对应的表的表头也将发生变化
- 知识点1:在当前的设计师类中,新建了一个
QStringListModel
,因为对话框里面使用了listview
- 知识点2:
QStringListModel
模型获取listview
中的字符串,用语句model->stringList();
,设置listview
中的字符串,用语句model->setStringList(list);
#ifndef DIALOGEDITHEAD_H
#define DIALOGEDITHEAD_H#include <QDialog>
#include <QStringListModel>namespace Ui {
class DialogEditHead;
}class DialogEditHead : public QDialog
{Q_OBJECTpublic:explicit DialogEditHead(QWidget *parent = nullptr);~DialogEditHead();void setHeadList(const QStringList& list);QStringList getHeaderList();private slots:void on_pushButtonOk_clicked();void on_pushButtonOk_2_clicked();private:Ui::DialogEditHead *ui;QStringListModel *model;
};#endif // DIALOGEDITHEAD_H
#include "dialogedithead.h"
#include "ui_dialogedithead.h"DialogEditHead::DialogEditHead(QWidget *parent) :QDialog(parent),ui(new Ui::DialogEditHead)
{ui->setupUi(this);model = new QStringListModel;ui->listView->setModel(model);
}DialogEditHead::~DialogEditHead()
{delete ui;
}void DialogEditHead::setHeadList(const QStringList &list)
{model->setStringList(list);
}void DialogEditHead::on_pushButtonOk_clicked()
{accept();
}void DialogEditHead::on_pushButtonOk_2_clicked()
{reject();
}QStringList DialogEditHead::getHeaderList()
{return model->stringList();
}
2.3 定位按钮
- 功能:点击定位单元格,弹出对话框,会显示当前单元格对应的位置,在对话框中输入文本,点击确定,文本会更新在相应的单元格里面
- 知识点1:一般情况,按钮单击之后,会变成灰色
void showEvent(QShowEvent *event);
,不会再变成原有的黑色,如果希望实现对话框关闭时,相应的按钮恢复成黑色,也就是恢复成可点击状态,添加函数void closeEvent(QCloseEvent *);
- 知识点2:通过对话框,更新主窗口的内容,需要定义主窗口的接口,同时在mainwindow函数中自定义相应的接口,
setCellText
就是在mainwindow函数中自定义的公共函数接口
MainWindow *mainwindow = (MainWindow*)parentWidget();mainwindow->setCellText(ui->spinBoxRow->value(),ui->spinBoxCol->value(),ui->plainTextEdit->toPlainText());
#ifndef DIALOGLOCATION_H
#define DIALOGLOCATION_H#include <QDialog>namespace Ui {
class DialogLocation;
}class DialogLocation : public QDialog
{Q_OBJECTpublic:explicit DialogLocation(QWidget *parent = nullptr);~DialogLocation();void setCurrentColRow(int row, int col);void setRowColMax(int maxRow, int maxCol);private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();private:Ui::DialogLocation *ui;//窗口关闭的时候调用这个函数void closeEvent(QCloseEvent *event);void showEvent(QShowEvent *event);};#endif // DIALOGLOCATION_H
#include "dialoglocation.h"
#include "ui_dialoglocation.h"
#include "mainwindow.h"
DialogLocation::DialogLocation(QWidget *parent) :QDialog(parent),ui(new Ui::DialogLocation)
{ui->setupUi(this);
}DialogLocation::~DialogLocation()
{delete ui;
}void DialogLocation::setCurrentColRow(int row, int col)
{ui->spinBoxCol->setValue(col);ui->spinBoxRow->setValue(row);
}void DialogLocation::setRowColMax(int maxRow, int maxCol)
{ui->spinBoxRow->setMaximum(maxRow-1);ui->spinBoxCol->setMaximum(maxCol-1);
}void DialogLocation::showEvent(QShowEvent *event){//把主窗口的定位组件再次设置为可以点击MainWindow *mainwindow = (MainWindow*)parentWidget();mainwindow->setActionLocationEnable(false);}void DialogLocation::closeEvent(QCloseEvent * )
{//把主窗口的定位组件再次设置为可以点击MainWindow *mainwindow = (MainWindow*)parentWidget();mainwindow->setActionLocationEnable(true);
}void DialogLocation::on_pushButton_clicked()
{//将指定位置的表格的内容设置为plaintext中的内容MainWindow *mainwindow = (MainWindow*)parentWidget();mainwindow->setCellText(ui->spinBoxRow->value(),ui->spinBoxCol->value(),ui->plainTextEdit->toPlainText());//列自增和行自增的框的相应实现if(ui->checkBoxRow->isChecked()){ui->spinBoxRow->setValue(ui->spinBoxRow->value() + 1);}if(ui->checkBoxCol->isChecked()){ui->spinBoxCol->setValue(ui->spinBoxCol->value() + 1);}
}void DialogLocation::on_pushButton_2_clicked()
{//reject(); //不会真正关闭对话框,不触发closeEvent,导致关闭对话框之后,标题栏的按钮没有恢复可点击状态close();
}
2.4 MainWindow函数
2.4.1 知识点1:新建对话框的方式有3种,
DialogResize *dialogresize = new DialogResize(this);
。。。。//删除对话框delete dialogresize;
dialogLocation = new DialogLocation(this);
if(dialogHead == NULL){//只创建一次,可以重复使用dialogHead = new DialogEditHead(this); //这种调用方式,不需要delete,this是父节点,关闭的时候会同时关闭子节点}
2.4.2 知识点2:模态显示2种,一种是打开当前操作,其余地方不允许操作;另一种是其他地方允许操作
其它地方不允许操作
//把自定义的对话框显示出来int ret = dialogresize->exec(); //模态显示,当前对话框工作,其他地方不允许操作if(ret == QDialog::Accepted){ //点击了确定按钮,。。。。}
其它地方允许操作
dialogLocation->show(); //以非模态方式显示
2.4.3 知识点3:获取tabelview模型种当前单元格的行列
QModelIndex index = selectionModel->currentIndex();
index.row(),
index.column()
2.4.4 获取表头信息
QStringList list;for(int i =0; i < model->columnCount(); i++){list.append(model->headerData(i,Qt::Horizontal).toString());}
函数实现
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include "dialogedithead.h"
#include "dialoglocation.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void setActionLocationEnable(bool enable);void setCellText(int row, int col, QString text);
private slots:void on_actionResize_triggered();void on_actionEditHead_triggered();void on_actionLocation_triggered();private:Ui::MainWindow *ui;QStandardItemModel *model;QItemSelectionModel *selectionModel;DialogEditHead *dialogHead = NULL;DialogLocation *dialogLocation = NULL;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialogresize.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);setCentralWidget(ui->tableView);model = new QStandardItemModel(10,6,this);selectionModel = new QItemSelectionModel(model);ui->tableView->setModel(model);ui->tableView->setSelectionModel(selectionModel);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::setActionLocationEnable(bool enable)
{ui->actionLocation->setEnabled(enable);
}void MainWindow::setCellText(int row, int col, QString text)
{//清除原来的选择项selectionModel->clearSelection();selectionModel->setCurrentIndex(model->index(row,col),QItemSelectionModel::Select);model->setData(model->index(row,col),text);
}void MainWindow::on_actionResize_triggered()
{DialogResize *dialogresize = new DialogResize(this);//固定对话框大小,不允许拉伸dialogresize->setWindowFlags(dialogresize->windowFlags() |Qt::MSWindowsFixedSizeDialogHint);//获取模型的当前的行列数,设置到自定义对话框,作为默认值显示dialogresize->setRowCount(model->rowCount());dialogresize->setColCount(model->columnCount());//把自定义的对话框显示出来int ret = dialogresize->exec(); //模态显示,当前对话框工作,其他地方不允许操作if(ret == QDialog::Accepted){ //点击了确定按钮int rows = dialogresize->rowCount();int cols = dialogresize->colCount();//改变tabelview的大小model->setRowCount(rows);model->setColumnCount(cols);}//删除对话框delete dialogresize;
}void MainWindow::on_actionEditHead_triggered()
{if(dialogHead == NULL){//只创建一次,可以重复使用dialogHead = new DialogEditHead(this); //这种调用方式,不需要delete,this是父节点,关闭的时候会同时关闭子节点}//将tabelview的表头都传递给这个对话框QStringList list;for(int i =0; i < model->columnCount(); i++){list.append(model->headerData(i,Qt::Horizontal).toString());}dialogHead->setHeadList(list);int ret = dialogHead->exec();if(ret == QDialog::Accepted){QStringList list = dialogHead->getHeaderList();model->setHorizontalHeaderLabels(list);}
}void MainWindow::on_actionLocation_triggered()
{ui->actionLocation->setEnabled(false); //一次只允许创建一个窗口//不同的新建方式dialogLocation = new DialogLocation(this);//设置窗口样式 显示在最顶层,这样不会被其他窗口覆盖dialogLocation->setWindowFlags(dialogLocation->windowFlags() |Qt::WindowStaysOnTopHint);//传递数据dialogLocation->setRowColMax(model->rowCount(),model->columnCount());QModelIndex index = selectionModel->currentIndex();if(index.isValid()){dialogLocation->setCurrentColRow(index.row(), index.column());}dialogLocation->show(); //以非模态方式显示}
三 自定义对话框 使用信号槽完成窗口之间的通讯
补充
- 知识点:两个窗口之间的通讯,需要定义信号和槽函数,信号一般定义在发送信号的窗口里面,槽函数一般定义在接收信号的窗口里面,在二案例的例子的基础上,对
DialogLocation
类进行修改,将类对象接口的通讯方式修改为信号与槽之间的通讯 - 步骤1:点击对话框的确定按钮,要发送信号;单击定位单元格按钮之后,要求图标变成灰色,关闭单元格之后,要求突变恢复黑色,因此当前操作需要发送两个信号,在
DialogLocation
类中添加信号,信号不需要做实现
//信号定义在信号发送者
signals:void setCellText(int row, int col, QString &text);void setActionEnable(bool enable);
- 步骤2:在mainwindow.h中添加信号槽,重点:由于是不同窗口之间的信号传递,接口需要定义成
public
类型的
//槽函数定义在信号的接收者,因为是其它窗口信号和当前窗口的槽函数关联
public slots:void setCellText2(int row, int col, QString &text);void setActionEnable2(bool enable);
- 步骤3:槽函数的实现,在对应的按键,也即控制对话框弹出的按钮里面进行信号的关联,在之前的代码上没有任何改动,只是对信号进行了连接
void MainWindow::on_actionLocation_triggered()
{ui->actionLocation->setEnabled(false); //一次只允许创建一个窗口//不同的新建方式dialogLocation = new DialogLocation(this);//设置窗口样式 显示在最顶层,这样不会被其他窗口覆盖dialogLocation->setWindowFlags(dialogLocation->windowFlags() |Qt::WindowStaysOnTopHint);//传递数据dialogLocation->setRowColMax(model->rowCount(),model->columnCount());QModelIndex index = selectionModel->currentIndex();if(index.isValid()){dialogLocation->setCurrentColRow(index.row(), index.column());}//关联connect(dialogLocation, SIGNAL(setCellText(int, int ,QString &)),this,SLOT(setCellText2(int, int ,QString &)));connect(dialogLocation, SIGNAL(setActionEnable(bool)),this,SLOT(setActionEnable2(bool)));dialogLocation->show(); //以非模态方式显示}
- 步骤4:在自定义窗口类中,发送信号
void DialogLocation::closeEvent(QCloseEvent * event)
{//把主窗口的定位组件再次设置为可以点击
// MainWindow *mainwindow = (MainWindow*)parentWidget();
// mainwindow->setActionLocationEnable(true);emit setActionEnable(true);
}void DialogLocation::showEvent(QShowEvent *event){//把主窗口的定位组件再次设置为可以点击
// MainWindow *mainwindow = (MainWindow*)parentWidget();
// mainwindow->setActionLocationEnable(false);emit setActionEnable(false);
}void DialogLocation::on_pushButton_clicked()
{
// //将指定位置的表格的内容设置为plaintext中的内容
// MainWindow *mainwindow = (MainWindow*)parentWidget();
// mainwindow->setCellText(ui->spinBoxRow->value(),
// ui->spinBoxCol->value(),
// ui->plainTextEdit->toPlainText());QString text = ui->plainTextEdit->toPlainText();emit setCellText(ui->spinBoxRow->value(),ui->spinBoxCol->value(),text);//列自增和行自增的框的相应实现if(ui->checkBoxRow->isChecked()){ui->spinBoxRow->setValue(ui->spinBoxRow->value() + 1);}if(ui->checkBoxCol->isChecked()){ui->spinBoxCol->setValue(ui->spinBoxCol->value() + 1);}
}
四 多窗口开发 —类似WPS的同时可以打开多个窗口
- Qt主要窗口类
4.1 案例实现功能
- formedit.h
#ifndef FORMEDIT_H
#define FORMEDIT_H#include <QWidget>namespace Ui {
class FormEdit;
}class FormEdit : public QWidget
{Q_OBJECTpublic:explicit FormEdit(QWidget *parent = nullptr);~FormEdit();private:Ui::FormEdit *ui;
};#endif // FORMEDIT_H
- formedit.cpp
#include "formedit.h"
#include "ui_formedit.h"
#include <QToolBar>
#include <QVBoxLayout>FormEdit::FormEdit(QWidget *parent) :QWidget(parent),ui(new Ui::FormEdit)
{ui->setupUi(this);//设计器里面没有toolbox,手动创建QToolBar *bar = new QToolBar(this);bar->addAction(ui->actionOpen);bar->addSeparator();bar->addAction(ui->actionFont);bar->addAction(ui->actionCut);bar->addAction(ui->actionCopy);bar->addAction(ui->actionPsate);bar->addAction(ui->actionCancle);bar->addAction(ui->actionRepeat);bar->addSeparator();bar->addAction(ui->actionClose);bar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);//代码布局 plaintextEdit ,不能手动布局,否则手动添加的按钮没有位置了QVBoxLayout *layout = new QVBoxLayout();layout->addWidget(bar);layout->addWidget(ui->plainTextEdit);this->setLayout(layout);}FormEdit::~FormEdit()
{delete ui;
}
- mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();
private slots://void tabCloseRequested(int index);void on_tabWidget_tabCloseRequested(int index);void on_action_insideWidget_triggered();void on_action_widget_triggered();void on_action_insisdeMainwindow_triggered();void on_action_mainwindow_triggered();private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
- mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "formedit.h"
#include "mainwindow2.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);ui->tabWidget->clear(); //清除tabWidget中的默认选项//让tab子窗口可关闭,有关闭按钮,但不会自动关闭,点击按钮会发送信号,需要自定义槽函数ui->tabWidget->setTabsClosable(true);//设置主窗口的默认状态是最大化this->setWindowState(Qt::WindowMaximized);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_tabWidget_tabCloseRequested(int index)
{//获取对应的窗口QWidget *widget = ui->tabWidget->widget(index);widget->close();}void MainWindow::on_action_insideWidget_triggered()
{FormEdit *form = new FormEdit(this);form->setAttribute(Qt::WA_DeleteOnClose); //设置窗体关闭时,自动销毁资源//将当前的表插入tabWidget,index是对应窗口的序号int index = ui->tabWidget->addTab(form,QString::asprintf("窗口%d",ui->tabWidget->count()+1));ui->tabWidget->setCurrentIndex(index);}void MainWindow::on_action_widget_triggered()
{FormEdit *form = new FormEdit(this);form->setAttribute(Qt::WA_DeleteOnClose); //设置窗体关闭时,自动销毁资源form->setWindowTitle("基于widget的独立窗口");form->setWindowFlag(Qt::Window, true); //这一行必须加,否则显示的独立窗口没有边框form->show();
}void MainWindow::on_action_insisdeMainwindow_triggered()
{MainWindow2 *window = new MainWindow2(this);window->setAttribute(Qt::WA_DeleteOnClose);int index = ui->tabWidget->addTab(window,QString::asprintf("窗口%d",ui->tabWidget->count()+1));ui->tabWidget->setCurrentIndex(index);
}void MainWindow::on_action_mainwindow_triggered()
{MainWindow2 *window = new MainWindow2(this);window->setAttribute(Qt::WA_DeleteOnClose); //设置窗体关闭时,自动销毁资源window->setWindowTitle("基于MainWindow2的独立窗口");window->setWindowFlag(Qt::Window, true); //这一行必须加,否则显示的独立窗口没有边框window->show();
}
- 其余文件代码见案例三,没有改动
4.2 案例4.1知识点总结
4.2.1 案例4.1的代码,是创建新的项目,完成formedit.h
函数及其实现之后,直接将案例三中的代码合成添加到当前案例,在此合成过程中,两个案例中都有mainwindow
同名函数,因此案例三中的该函数需要修改名字
- 直接将案例三中涉及
mainwindow
的位置都修改成mainwindow2
或Mainwindow2
,声明#ifndef MAINWINDOW2_H , #define MAINWINDOW2_H
,头文件#include "mainwindow2.h"
都要进行相应的修改 - 另外,
mainwindow2.ui
文件也要进行修改,选中该文件->在explorer中显示->找到mainwindow2.ui
->用记事本打开->修改如下对应位置,注意此处不是所有的都改,只改一个地方
- 选中项目文件名
untitled27
->添加现有文件->将案例三中的.cpp
文件,.ui
文件,以及.h
文件,案例三共有12个文件,导入当前项目即可,在案例四中调用案例三中的项目,直接通过MainWindow2 *window = new MainWindow2(this);
创建街接口,就可以显示
4.2.2 Tab Widget
的子窗口里面默认是没有关闭按钮的,需要手动建立信号槽来是实现
- 步骤1:在
mainwindow.cpp
文件中的构造函数里面,添加ui->tabWidget->setTabsClosable(true);
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);ui->tabWidget->clear(); //清除tabWidget中的默认选项//让tab子窗口可关闭,有关闭按钮,但不会自动关闭,点击按钮会发送信号,需要自定义槽函数ui->tabWidget->setTabsClosable(true);//设置主窗口的默认状态是最大化this->setWindowState(Qt::WindowMaximized);
}
- 步骤2:在
mainwindow.h
文件, 自定义信号槽void on_tabWidget_tabCloseRequested(int index);
- 步骤3:实现槽函数
void MainWindow::on_tabWidget_tabCloseRequested(int index)
{//获取对应的窗口QWidget *widget = ui->tabWidget->widget(index);widget->close();
}
4.2.3 formedit.h
是头通过新建设计师类,选择Widget
来实现的,和Dialog without Buttons
(案例三中使用的)不同,前者无法添加toolbox
来手动拖动action,后者可以,所以当前案例的做法是,还是手动创建action以及plain text eidt,但是是在formedit.cpp
中来布局和添加,不能手动布局
五 MDI开发案例 多窗口
- 组件名称
5.1 知识点总结
- 当前项目步骤:
(1)创建一个设计师类,选择widget
,对应文件名字formdoc
,在对应的ui设计界面,只添加plain text edit
组件
(2)对于mianwindow
类,在ui界面添加一个MDI area
组件,然后手动添加toolbox对应的action - 知识点1:
mianwindow
里面的组件,实际的操作对象是formdoc
里面的plain text edit
组件,所以对应的复制粘贴等选项,需要formdoc
提供对外的接口,使得点击mianwindow
里面的组件时能完成对文本的相关操作 - 知识点2:MDI模式不需要手动为弹出的对话框添加取消按钮,也即每个框右上角的×
5.2 MDI模式
MDI效果图
非MDI效果图
5.3 展开模式
5.4 平铺模式
formdoc.h
#ifndef FORMDOC_H
#define FORMDOC_H#include <QWidget>namespace Ui {
class FormDoc;
}class FormDoc : public QWidget
{Q_OBJECTpublic:explicit FormDoc(QWidget *parent = nullptr);~FormDoc();bool fileOpen();void loadFile(const QString &filename);void cut();void paste();void copy();void setFont();private:Ui::FormDoc *ui;bool m_fileOpen = false;
};#endif // FORMDOC_H
formdoc.cpp
#include "formdoc.h"
#include "ui_formdoc.h"
#include <QFile>
#include <QTextStream>
#include <QFileInfo>
#include <QFontDialog>
FormDoc::FormDoc(QWidget *parent) :QWidget(parent),ui(new Ui::FormDoc)
{ui->setupUi(this);this->setAttribute(Qt::WA_DeleteOnClose); //窗口关闭消除资源
}FormDoc::~FormDoc()
{delete ui;
}bool FormDoc::fileOpen()
{return m_fileOpen;
}void FormDoc::loadFile(const QString &filename)
{QFile file(filename);if(file.open(QIODevice::ReadOnly | QIODevice::Text)){QTextStream stream(&file);ui->plainTextEdit->clear();ui->plainTextEdit->setPlainText(stream.readAll());file.close();m_fileOpen = true;//把文件名作为窗口标题 filename是文件路径QFileInfo info(filename);QString name = info.fileName();this->setWindowTitle(name);}
}void FormDoc::cut(){ui->plainTextEdit->cut();
}void FormDoc::paste()
{ui->plainTextEdit->paste();
}void FormDoc::copy()
{ui->plainTextEdit->copy();
}void FormDoc::setFont()
{QFont font = ui->plainTextEdit->font(); //获取当前字体bool ok;font = QFontDialog:: getFont(&ok, font);ui->plainTextEdit->setFont(font);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_actionNew_triggered();void on_actionOpen_triggered();void on_actionCloseALL_triggered();void on_actionCopy_triggered();void on_actionCut_triggered();void on_actionFont_triggered();void on_actionPaste_triggered();void on_actionMDI_toggled(bool arg1);void on_actionExpand_triggered();void on_actionPing_triggered();private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "formdoc.h"
#include <QMdiSubWindow>
#include <QFileDialog>
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}//新建文档
void MainWindow::on_actionNew_triggered()
{FormDoc *form = new FormDoc(this);//把新建的床口添加到MDIui->mdiArea->addSubWindow(form);//把当前新的文档编辑窗口,以独立的窗口显示form->show();
}void MainWindow::on_actionOpen_triggered()
{//如果当前MDI没有任何子窗口,open直接创建新的子窗口//MDI当前已经有子窗口,就创新新的窗口bool newNewForm = false;FormDoc *form = NULL;if(ui->mdiArea->subWindowList().count() == 0){newNewForm = true;}else {//去除当前激活的窗口form = (FormDoc*)ui->mdiArea->activeSubWindow()->widget();if(form->fileOpen()){newNewForm = true;}}//打开文件对话框QString filename = QFileDialog::getOpenFileName(this, "打开一个文件", QDir::currentPath(),"源文件(*.h *.cpp);;文本文件(*.txt);;所有文件(*.*)");if(filename.isEmpty()){return;}if(newNewForm){FormDoc *form2 = new FormDoc(this);ui->mdiArea->addSubWindow(form2);form2->show();form2->loadFile(filename);}
}void MainWindow::on_actionCloseALL_triggered()
{ui->mdiArea->closeAllSubWindows();
}void MainWindow::on_actionCopy_triggered()
{FormDoc *form = (FormDoc*)ui->mdiArea->activeSubWindow()->widget();form->copy();
}void MainWindow::on_actionCut_triggered()
{FormDoc *form = (FormDoc*)ui->mdiArea->activeSubWindow()->widget();form->cut();
}void MainWindow::on_actionFont_triggered()
{FormDoc *form = (FormDoc*)ui->mdiArea->activeSubWindow()->widget();form->setFont();
}void MainWindow::on_actionPaste_triggered()
{FormDoc *form = (FormDoc*)ui->mdiArea->activeSubWindow()->widget();form->paste();
}void MainWindow::on_actionMDI_toggled(bool check)
{if(check){ui->mdiArea->setViewMode(QMdiArea::TabbedView);ui->actionPing->setEnabled(false);ui->actionExpand->setEnabled(false);//设置MDI子窗口的tab关闭按钮可以使用ui->mdiArea->setTabsClosable(true);}else{ui->mdiArea->setViewMode(QMdiArea::SubWindowView);ui->actionPing->setEnabled(true);ui->actionExpand->setEnabled(true);}
}void MainWindow::on_actionExpand_triggered()
{ui->mdiArea->cascadeSubWindows();
}void MainWindow::on_actionPing_triggered()
{ui->mdiArea->tileSubWindows();
}
相关文章:
Qt学习(五)自定义对话框,多窗口开发---添加设计师类, MDI多窗口开发
一 对话框 实现功能:打开文件,选择目录,保存文件,选择颜色,选择字体,输入信息, 消息提示框 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE na…...
【部署优化篇三】《DeepSeek边缘计算实战:把目标检测模型塞进树莓派,让AI在巴掌大的设备上“开天眼“》
“谁说只有超级计算机才能跑AI?今天咱们就要在树莓派上玩转DeepSeek目标检测,让这个巴掌大的小盒子变成会‘看’世界的智能终端!” 本文手把手教你从零开始,把最潮的目标检测模型塞进树莓派。全程高能预警,建议准备好你的树莓派4B/5和散热风扇,咱们这就开启边缘计算的魔法…...
深入浅出CSS复合选择器:掌控元素关系与层级选择
目录 前言 一、子代选择器(Descendant Selector) 1. 什么是子代选择器? 2. 基本语法 3. 示例 4. 注意事项 二、直接子元素选择器(Child Selector) 1. 什么是直接子元素选择器? 2. 基本语法 3. 示例…...
LLM 推理中推理-时间计算技巧
25年2月来自香港科技大学广州分校的论文“Bag of Tricks for Inference-time Computation of LLM Reasoning”。 随着大语言模型 (LLM) 的进步,解决复杂的推理任务越来越受到关注。推理-时间计算方法(例如 Best-of-N、波束搜索等)特别有价值…...
【模板】图论 最短路 (Floyd+SPFA+Dijkstra)
FloydSPFADijkstra 温故而知新,这三种算法都是求最短路问题常用的算法(特别是Dijkstra) 1.Floyd (多源最短路) 基于动态规划思想,时间复杂度为 O ( N 3 ) O(N^3) O(N3) 较高。 注意点: 初始化距离为INF…...
vite-vue-ts使用arco-design-vue定制主题的后动态变更主题思路
定制主题的后动态变更主题思路 安装依赖与主题定制动态变更主题过程尝试修改主题色(结果失败)尝试修改主题色(结果成功,但是hover的主题色没有变,未覆盖10个梯度的色值)根据主题色实现10个梯度颜色实现10个…...
递归爬取网页测试
我们正在做基于大模型的数据分析平台。 当前需要测试ezdata的递归爬取功能,爬取到第几层 测试网址 https://blog.csdn.net/m0_68177611/article/details/144936089...
【论文学习】RVS-FDSC:一种基于四方向条带卷积的视网膜血管分割方法以增强特征提取
写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除! 文章目录 前言论文论文内容RSC模块MSPF2 模块RPDA模块 实验效果 总结互动致谢参考往期回顾 前言…...
交友项目-交友软件简介
一、 项目背景 在线社交是互联网时代的产物,已成为互联网用户的基础需求之一。移动互联网自2003年起快速发展,促使在线社交逐渐从PC端转移至移动端。移动社交最初以熟人社交为主,以维系熟人关系、共享资源信息的形式存在。随着人们交友需求的…...
新手向:SpringBoot后端查询到数据,前端404?(附联调时各传参方式注解总结-带你一文搞定联调参数)
前言: 在 Spring Boot 项目开发中,后端小伙伴可能经常遇到这样诡异的场景: 后台日志显示查询到了数据,但前端却一脸懵逼地告诉你 404 Not Found?接口明明写好了,Postman 直接访问却提示找不到?…...
Elasticsearch7.6.2 安装过程
一. 安装JDK1.8 (1)创建安装目录 mkdir /usr/local/java/ (2)解压至安装目录 tar -zxvf jdk-8u251-linux-x64.tar.gz -C /usr/local/java/ (3)设置环境变量 vim /etc/profile 在末尾添加 export JA…...
汇能感知的光谱相机/模块产品有哪些?
CM020A 分辨率:1600H1200V 光谱范围:350~950nm 光谱分辨率:1nm 接口:USB2.0 帧率:16001200 (6帧) 输出格式:Raw 8bit FOV:D73.5H58.8V44.1 相机尺寸:505055mm VM02S10 分辨率…...
【机器学习】K折交叉验证(K-Fold Cross-Validation)
文章目录 K折交叉验证步骤详解一. 核心目标二. 具体步骤与操作三. 关键变体与场景适配3.1 分层K折交叉验证3.2 时间序列K折交叉验证3.3 留一法(LOO)3.4 重复K折交叉验证 四. 实践注意事项五. Python代码示例六. 总结 K折交叉验证步骤详解 一. 核心目标 …...
【核心算法篇十九】《 DeepSeek因果推断:双重差分模型如何破解政策评估的「时空难题」》
一、当AB实验不可行时,我们该相信什么?(因果推断困局解析) 假设某城市推出「夜间地铁免费」政策,市长想知道这个政策是否真的提升了夜间经济。这时候你会发现: 1️⃣ 无法克隆城市:不能同时存在一个「实施政策」和「不实施政策」的平行宇宙 2️⃣ 数据混杂严重:疫情反…...
使用vue3框架vue-next-admin导出列表数据
在 Vue3 中实现 Excel 导出功能可以通过以下步骤完成,这里使用 xlsx 库来实现前端 Excel 导出: 1. 安装依赖 npm install xlsx file-saver # 或 yarn add xlsx file-saver2. 实现代码示例 需要在当前页引入 import * as XLSX from "xlsx";注…...
机器学习(1)安装Pytorch
1.安装命令 pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 2.安装过程Log: Looking in indexes: https://download.pytorch.org/whl/cu118 Co…...
讯方·智汇云校华为官方授权培训机构
1.官方授权 讯方智汇云校是华为领先级授权培训机构(华为授权培训合作伙伴(HALP)体系,分为认证、优选、领先三个等级,领先级是HALP最高级),代表着华为对培训合作伙伴在专业能力、师资队伍、合作…...
彻底理解零拷贝技术,zero-copy
计算机处理的任务大体可以分为两类:CPU密集型与IO密集型。当前流行的互联网应用更多的属于IO密集型,传统的IO标准接口都是基于数据拷贝的,这篇文章我们主要关注该怎样从数据拷贝的角度来优化IO性能,让你的程序在IO性能方面赶超P8。…...
使用 MySQL 从 JSON 字符串提取数据
使用 MySQL 从 JSON 字符串提取数据 在现代数据库管理中,JSON 格式因其灵活性而广泛使用。然而,当数据存储在 JSON 中时,我们经常需要将其转换为更易于处理的格式。本篇文章将通过一个具体的 SQL 查询示例,展示如何从存储在 MySQ…...
矛盾(WEB)
##解题思路 打开靶场就是一段自相矛盾的代码,既要num是数字类型,又要判断为1 这种情况我们会想到弱类型的编程语言,插件查看过后,php就是弱类型的语言,此处并非是严格相等,只是 因此可以根据弱类型编程语言…...
优先队列(典型算法思想)—— OJ例题算法解析思路
目录 一、1046. 最后一块石头的重量 - 力扣(LeetCode) 算法代码: 代码思路 使用优先队列(大根堆) 将所有石头放入堆中 模拟碰撞过程 返回最后的重量 代码解析 时间复杂度 示例 输入 输出 二、703. 数据流…...
IGBT的损耗性分析
铝合金外壳设计器地址:嘉立创铝合金外壳/壳体/盒型-让您的产品更出彩 IGBT和MOS的损耗谁大: 电子元器件常见失效模式: 电子元器件的失效模式多种多样,以下是一些常见的失效模式及其原因: 开路: 原因:内部连接断开、焊点断裂、导线断裂等。 影响:电流无法通过,电路中断。…...
TypeScript跟js,es6这些的区别
TypeScript 一、TypeScript 是什么 想象 JavaScript 是一个自由奔放的艺术家,它在创作(编写代码)时不受太多约束,非常灵活,但有时也容易犯错且难以调试。而 TypeScript 就像是给这位艺术家配备了一套精确的工具和规范…...
单例模式代码示例
饿汉式:在类加载时就创建单例实例,线程安全。代码如下: public class Singleton {// 私有静态实例private static final Singleton instance new Singleton();// 私有构造函数private Singleton() {}// 公共访问方法public static Singleto…...
掌握 ElasticSearch的 _source 过滤
掌握 ElasticSearch的 _source 过滤 1. 引言2. _source 元数据基础2.1 什么是 _source 字段?2.2 _source 的基本用法 3. 禁用 _source3.1 如何禁用 _source 字段3.2 禁用 _source 的利弊3.3 最佳实践建议 4. _source 数据源过滤4.1 为什么需要数据源过滤?…...
车载音频配置(二)
目录 OEM 自定义的车载音频上下文 动态音频区配置 向前兼容性 Android 14 车载音频配置 在 Android 14 中,AAOS 引入了 OEM 插件服务,使你可以更主动地管理由车载音频服务监督的音频行为。 随着新的插件服务的引入,车载音频配置文件中添加了以下更改: • OEM 自定义的车…...
开目3DCAPP系列:三维制造成本分析与估算软件3DDFC
开目3DDFC 是一款基于 MBD 模型和工艺知识库的专业三维制造成本分析与估算软件,在不依赖详细工艺路线的情况下,根据零件几何信息和精度信息一键式完成零件成本的分析与估算,为面向成本的设计优化提供参考指引,也为企业对外产品报价…...
化学品安全数据表(MSDS)的全面解析与实用指南
SDS(安全数据表),也称为MSDS(材料安全数据表),是用于详细说明化学品的理化特性(如pH值、闪点、易燃性、反应活性等)及其对使用者健康(如致癌、致畸等)潜在危害…...
赛前启航 | Azure 应用开发实战指南:开启创意的无限可能
在 AI 时代,如何高效构建、优化和部署你的应用?如何充分利用微软 Azure 的强大能力,让开发更敏捷,性能更卓越?2 月 21 日 14:00-16:00,微软 AI 开发者挑战赛赛前指导第二场直播,带你全方位掌握 …...
Visual Studio Code的下载安装与汉化
1.下载安装 Visual Studio Code的下载安装十分简单,在本电脑的应用商店直接下载安装----注意这是社区版-----一般社区版就足够用了---另外注意更改安装地址 2.下载插件 重启后就是中文版本了...
home assistant ddns动态域名解析插件
home assistant ddns动态域名解析插件 使用方法 在HACS中搜索 ddns安装(hacs目前还没有合并我的提交,目前不可用),或者 clone https://github.com/weiangongsi/ddns.git, 将 custom_components/ddns目录拷贝至 Home Assistant 配置目录的 custom_compon…...
金融交易算法单介绍
0.背景 股票交易时,常见的订单类型有基础订单和条件订单。 基础订单 市价单限价单碎股单等等 条件订单 止损市价单止损限价单触及市价单(止盈)触及限价单(止盈)跟踪止损市价单跟踪止损限价单等等 除了基础订单和…...
LabVIEW利用CANopen的Batch SDO写入
本示例展示了如何通过CANopen协议向设备写入Batch SDO(批量服务数据对象)。Batch SDO允许用户在一次操作中配置多个参数,适用于设备的批量配置和参数设置。此方法能够简化多个参数的写入过程,提高设备管理效率。 主要步骤…...
正式页面开发-登录注册页面
整体路由设计: 登录和注册的切换是切换组件或者是切换内容(v-if和 v-else),因为点击两个之间路径是没有变化的。也就是登录和注册共用同一个路由。登录是独立的一级路由。登录之后进到首页,有三个大模块:文章分类&…...
vLLM专题(二):安装-CPU
vLLM 是一个 Python 库,支持以下 CPU 变体。选择您的 CPU 类型以查看供应商特定的说明: Intel/AMD x86 vLLM 最初支持在 x86 CPU 平台上进行基本模型推理和服务,支持的数据类型包括 FP32、FP16 和 BF16。 注意 此设备没有预构建的 wheel 包或镜像,因此您必须从源代码构建 v…...
【CSS进阶】常见的页面自适应的方法
在前端开发中,自适应布局(Responsive Design)是一种让网页能够适应不同屏幕尺寸、设备和分辨率的技术。常见的自适应布局方法包括 流式布局、弹性布局(Flexbox)、栅格布局(Grid)、媒体查询&…...
Java编程语言:从基础到高级应用的全面探索
在当今的软件开发领域中,Java无疑是一种极为流行且强大的编程语言。自1995年由Sun Microsystems推出以来,Java凭借其跨平台性、面向对象特性和丰富的API库,迅速成为企业级应用开发的首选语言。本文将带您从Java的基础语法入手,逐步…...
计算机视觉:神经网络实战之手势识别(附代码)
第一章:计算机视觉中图像的基础认知 第二章:计算机视觉:卷积神经网络(CNN)基本概念(一) 第三章:计算机视觉:卷积神经网络(CNN)基本概念(二) 第四章:搭建一个经典的LeNet5神经网络(附代码) 第五章࿱…...
linux 面试题
1. 文件与目录操作 ls 功能:列出目录内容 常用参数: -l:长格式显示(权限、大小、时间等)-a:显示隐藏文件(以.开头的文件)-h:以易读格式显示文件大小(如KB/…...
利用websocket检测网络连接稳定性
浏览器中打开F12,控制台中输入以下内容 > 回车 > 等待结果 连接关闭 表示断网 let reconnectDelay 1000; // 初始重连间隔 let pingInterval null; let socketManuallyClosed false; // 标志是否手动关闭function createWebSocket() {if (socketManuallyCl…...
Go入门之数组与切片
var arr1 [...]int{1, 2, 3}fmt.Println(len(arr1)) 数组长度不能扩展 var arr2 [...]int{0: 100, 5: 101}fmt.Println(len(arr2)) } 指定索引初始化 可以通过for和range遍历 值类型:基本数据类型和数组都是值类型,改变副本的值不会改变本身的值 切片为引用数…...
《Nuxt.js 实战:从放弃到入门》六、打造个性化文字转图片工具
在当今短视频的时代,将文字转化为图片是一个常见且实用的需求,无论是用于社交媒体分享、设计宣传材料,还是制作个性化的视觉内容。今天,我们就来深入剖析一个使用 Vue 3 和 ElementPlus 构建的文字转图片工具的代码…...
软硬链接?
目录 1. 硬链接(Hard Link) 2. 软链接(Symbolic Link,符号链接) 总结: 1. 硬链接(Hard Link) 定义: 硬链接是直接指向文件数据块(inode)的链接。…...
轻松搭建本地大语言模型(二)Open-WebUI安装与使用
文章目录 前置条件目标一、安装 Open-WebUI使用 Docker 部署 二、使用 Open-WebUI(一)访问Open-WebUI(二)注册账号(三)模型选择(四)交互 四、常见问题(一)容器…...
windows Redis Insight 如何查看宝塔docker里的redis数据
1、ping 命令用于测试网络连通性,它只需要目标 IP 地址作为参数,不需要端口号。正确的命令如下: ping 公网地址2、使用 Telnet 测试端口连通性 telnet 公网地址 端口 telnet 47.108.67.228 6379如果连接成功,窗口会变为空白&am…...
Python高级语法之urllib
目录: 1、爬虫的介绍2、urllib的使用2.1、urllib的异常捕获2.2、urllib的实现微博cookie登陆2.3、urllib的handler处理器2.4、urllib的代理服务器2.5、urllib的代理服务池 1、爬虫的介绍 2、urllib的使用 2.1、urllib的异常捕获 2.2、urllib的实现微博cookie登陆 2…...
word$deepseep
1、进入官网地址。 DeepSeek 2、进入DeepSeek的API文档 3、点击DeepSeek开放平台左侧的“API Keys”, 再点击“创建API Key” 4、在弹出的对话框中,输入自己的API Key名称,点击创建。 sk-0385cad5e19346a0a4ac8b7f0d7be428 5、打开Word文档。 6、Word找…...
【koa】05-koa+mysql实现数据库集成:连接和增删改查
前言 前面我们已经介绍了第二阶段的第1-4点内容,本篇介绍第5点内容:数据库集成(koamysql) 也是第二阶段内容的完结。 一、学习目标 在koa项目中正常连接数据库,对数据表进行增删改查的操作。 二、操作步骤 本篇文章…...
【深度学习】分布偏移纠正
分布偏移纠正 正如我们所讨论的,在许多情况下训练和测试分布 P ( x , y ) P(\mathbf{x}, y) P(x,y)是不同的。 在一些情况下,我们很幸运,不管协变量、标签或概念如何发生偏移,模型都能正常工作。 在另一些情况下,我们…...
数据结构_前言
本次我们将进入一个新的阶段啦~ 要注意哦: 在学数据结构之前,我们要先掌握c语言中所学的指针、结构体、内存的存储这几部分,如果还没太掌握的话,那记得去复习回顾一下噢。 下面我们就一起进入数据结构的学习吧! 知识…...