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
  • 知識點2QStringListModel模型獲取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的位置都修改成mainwindow2Mainwindow2,聲明#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
  • 知識點1mianwindow里面的組件,實際的操作對象是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();
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/895892.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/895892.shtml
英文地址,請注明出處:http://en.pswp.cn/news/895892.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

用 Python 實現簡易的 Web 爬蟲:從入門到實戰

一、引言 在信息爆炸的時代,網絡上蘊含著海量的數據。如果我們想要獲取特定的信息,手動從網頁上復制粘貼顯然效率極低。這時,Web 爬蟲就派上了用場。Web 爬蟲是一種自動獲取網頁內容的程序,它可以模擬人類在瀏覽器中的操作,快速地抓取網頁上的數據。本文將帶領大家使用 Py…

機器視覺檢測中,2D面陣相機和線掃相機的區別

2D面陣相機和線掃相機是工業視覺系統中常用的兩種相機類型&#xff0c;各有其特點和應用場景。 2D面陣相機 特點&#xff1a; 成像方式&#xff1a;通過二維傳感器一次性捕捉整個場景的圖像。 分辨率&#xff1a;分辨率由傳感器的像素數決定&#xff0c;常見的有百萬像素到幾千…

ECharts極簡入門

ECharts 是一個基于 JavaScript的開源可視化圖表庫&#xff0c;廣泛應用于數據可視化的場景中&#xff0c;支持多種圖表類型&#xff0c;如柱狀圖、折線圖、餅圖、散點圖、雷達圖等&#xff0c;且具有強大的自定義功能。 1. ECharts 基本使用 首先需要引入 ECharts 庫&#xf…

go設置鏡像代理

前言 在 Go 開發中&#xff0c;如果直接從官方源&#xff08;https://proxy.golang.org&#xff09;下載依賴包速度較慢&#xff0c;可以通過設置 鏡像代理 來加速依賴包的下載。以下是增加 Go 鏡像代理的詳細方法&#xff1a; 一、設置 Go 鏡像代理 1. 使用環境變量設置代理…

Linux部署DeepSeek r1 模型訓練

之前寫過一篇windows下部署deepseekR1的文章&#xff0c;有小伙伴反饋提供一篇linux下部署DeepSeek r1 模型訓練教程&#xff0c;在 Linux 環境下&#xff0c;我找了足夠的相關資料&#xff0c;花費了一些時間&#xff0c;我成功部署了 DeepSeek R1 模型訓練任務&#xff0c;結…

AI Agent架構深度解析:從ReAct到AutoGPT,自主智能體的技術演進與工程實踐

前言 覺得不錯就點個贊吧&#xff01;。 一、AI Agent技術架構演進圖譜 &#xff08;配圖&#xff1a;AI Agent架構演進時間軸&#xff0c;標注關鍵技術節點&#xff09; 1.1 三代架構對比分析 架構類型代表系統核心特征局限性反應式DeepBlue預置規則庫無長期記憶認知式Wats…

嵌入式經常用到串口,如何判斷串口數據接收完成?

說起通信&#xff0c;首先想到的肯定是串口&#xff0c;日常中232和485的使用比比皆是&#xff0c;數據的發送、接收是串口通信最基礎的內容。這篇文章主要討論串口接收數據的斷幀操作。 空閑中斷斷幀 一些mcu&#xff08;如&#xff1a;stm32f103&#xff09;在出廠時就已經在…

HTML/CSS中并集選擇器

1.作用:選中多個選擇器對應的元素,又稱:分組選擇器 所謂并集就是或者的含義. 2.語法:選擇器1,選擇器2,選擇器3,......選擇器n 多個選擇器通過,連接,此處,的含義就是:或. .rich,.beauty{color: blue;} 3.注意事項 1.并集選擇器,我們一般豎著寫 2.任何形式的選擇器,都可以作為并…

解鎖機器學習核心算法 | 隨機森林算法:機器學習的超強武器

一、引言 在機器學習的廣闊領域中&#xff0c;算法的選擇猶如為一場冒險挑選趁手的武器&#xff0c;至關重要。面對海量的數據和復雜的任務&#xff0c;合適的算法能夠化繁為簡&#xff0c;精準地挖掘出數據背后隱藏的模式與價值。機器學習領域有十大核心算法&#xff0c;而隨…

Shapr3D在ipad上無法識別鼠標點擊問題

此問題我去過長沙Apple官方直營店咨詢過此問題&#xff0c;官方直營店也不知道解決方案&#xff0c;遂在此提醒長沙Apple官方線下直營店的所有店員。 問題描述 1.不知道為什么在買了Magic Keyboard后還是無法識別單擊觸控板&#xff0c;遂為了解決這個問題我特意從江西跑到長沙…

【架構】微內核架構(Microkernel Architecture)

微內核架構(Microkernel Architecture) 核心思想 微內核架構(又稱插件式架構)通過最小化核心系統,將可擴展功能以插件模塊形式動態加載,實現高內聚低耦合。其核心設計原則: 核心最小化:僅封裝基礎通用能力(如插件管理、通信機制、安全校驗)功能插件化:所有業務功能…

AI 編程助手 cursor的系統提示詞 prompt

# Role 你是一名極其優秀具有10年經驗的產品經理和精通java編程語言的架構師。與你交流的用戶是不懂代碼的初中生&#xff0c;不善于表達產品和代碼需求。你的工作對用戶來說非常重要&#xff0c;完成后將獲得10000美元獎勵。 # Goal 你的目標是幫助用戶以他容易理解的…

javaSE學習筆記21-線程(thread)-鎖(synchronized 與Lock)

死鎖 多個線程各自占有一些共享資源&#xff0c;并且互相等待其他線程占有的資源才能運行&#xff0c;而導致兩個或者多個線程 都在等待對方釋放資源&#xff0c;都停止執行的情形&#xff0c;某一個同步塊同時擁有“兩個以上對象的鎖”時&#xff0c;就可能 會發生“死鎖&quo…

uni-app發起網絡請求的三種方式

uni.request(OBJECT) 發起網絡請求 具體參數可查看官方文檔uni-app data:請求的參數; header&#xff1a;設置請求的 header&#xff0c;header 中不能設置 Referer&#xff1b; method&#xff1a;請求方法&#xff1b; timeout&#xff1a;超時時間&#xff0c;單位 ms&a…

SpringBoot速成概括

視頻&#xff1a;黑馬程序員SpringBoot3Vue3全套視頻教程&#xff0c;springbootvue企業級全棧開發從基礎、實戰到面試一套通關_嗶哩嗶哩_bilibili 圖示&#xff1a;

GoFound 與 MySQL 集成優化方案

GoFound 與 MySQL 集成優化方案 1. 明確需求 文章信息存儲在 MySQL 數據庫中。使用 GoFound 實現全文搜索功能。搜索時&#xff0c;先從 GoFound 中獲取匹配的文章 ID&#xff0c;然后從 MySQL 中查詢完整的文章信息。 2. 優化思路 數據同步&#xff1a;將 MySQL 中的文章數…

基于開源Odoo模塊、SKF Phoenix API與IMAX-8數采網關的資產密集型企業設備智慧運維實施方案

一、方案背景與需求分析 1.1 華東地區產業特點與設備管理痛點 華東地區作為中國制造業核心區域&#xff0c;聚集了鋼鐵、化工、汽車、裝備制造等資產密集型企業。以某長三角鋼鐵集團為例&#xff0c;其設備管理面臨以下挑戰&#xff1a; 非計劃停機損失嚴重&#xff1a;2023…

《魔女的夜宴》無廣版手游安卓蘋果免費下載直裝版

自娶 https://pan.xunlei.com/s/VOJS77k8NDrVawqcOerQln2lA1?pwdn6k8 《魔女的夜宴》&#xff1a;一場魔法與戀愛的奇幻之旅 在美少女游戲的世界中&#xff0c;柚子社&#xff08;Yuzusoft&#xff09;的作品總是以其精美的畫面、動人的劇情和豐富的角色塑造而備受玩家喜愛…

深化與細化:提示工程(Prompt Engineering)的進階策略與實踐指南2

深化與細化&#xff1a;提示工程&#xff08;Prompt Engineering&#xff09;的進階策略與實踐指南 一、結構化提示的黃金框架 1. CRISPE框架&#xff08;角色-約束-意圖-風格-示例&#xff09; 適用于復雜技術場景&#xff0c;確保輸出精準可控&#xff1a; [角色] 你是一名…

N-bit ADC過采樣和L階噪聲整形后的SQNR表達式

對于采用L階理想高通濾波器進行噪聲整形的DSM&#xff0c;OSR每增加一倍&#xff0c;SQNR提高3(2L1)dB,文中給出了DSM量化精度與量化器位數N、環路濾波器階數L和過采樣率OSR的關系&#xff0c;在進行DSM系統設計時通過設置目標SQNR即可篩選出滿足設計需要的參數組合。