Qt5 Write a Notepad (Multi-Document Editor)

Posted by jason.carter on Wed, 10 Nov 2021 19:47:25 +0100

Catalog

I. Preparations

1.1 Create a project

1.2 Create a resource file (myimages.qrc)

1.3 Create an interface file (mainwindow.ui)

2. Implementing Functions

1.1 New c++class

1.2 MainWindow class code is as follows

1.3 Principal Functions

3. Procedure Release

          summary

Use qt5 to write a project with multi-document editor functions (can write multiple documents, save, open, edit, undo, cut, copy, paste, and so on).

ps: This project is developed using Qt5.6 and Chapter 1 of "Qt and Qt Quick Development of Actual Combat Resolution". (The original book was developed using Qt4.7 and Qt Creator 2.1.0).

Here's how the program works:

Attach program and source address:

Links: https://pan.baidu.com/s/1sNCOUqrQnX0Com6zxZhfKA  
Extraction Code: idug

I. Preparations

Prepare the desired icon file (preferably one with practical icons), save it as a Qt resource file, call it later, and use the ui to design the window interface.

    1.1 Create a project

        Open Qt Creator, create a new project, create a new Application ->Qt Widgets Application project name changed to myMid

Set the base class to QMainWindow. The creation was successful as follows:

1.2 Create a resource file (myimages.qrc)

      Right-click the project name, add a new file, select Qt Resource File, change the file name to myimages.qrc, click myimages.qrc, and add a prefix name/images to the add menu bar below. Then create a new folder in the project directory called images and put the icon file in it (it can be in any format such as. **ico **.png **.jpg, but the file size is not too large). Back in myimages.qrc, add the image file you just created to images by adding the file from the Add menu. Add it as follows

1.3 Create an interface file (mainwindow.ui)

  These operational UI interfaces are designed. Change the names of the four Run menu items to menuF,menuE,menuW,menuH.

Can run to see the effect;

2. Implementing Functions

Let each module implement its own functions, such as opening files, copying and pasting, undoing and so on.

1.1 New c++class

Right-click the new c++class base class in the project and select the QDialog class named MdiChild.

MdiChild.h:

#ifndef MDICHILD_H
#define MDICHILD_H

#include <QTextEdit>

class MdiChild : public QTextEdit
{
    Q_OBJECT
public:
    explicit MdiChild(QWidget *parent = 0);
    void newFile(); // New Operation
    bool loadFile(const QString &fileName); // load file
    bool save();  // Save Operation
    bool saveAs();  // Save As Operation
    bool saveFile(const QString &fileName); // Save File
    QString userFriendlyCurrentFile(); // Extract File Name
    QString currentFile(){return curFile;} // Return to current file path
protected:
    void closeEvent(QCloseEvent *event); // Close Event
    void contextMenuEvent(QContextMenuEvent *e); // Right-click menu events
private slots:
    void documentWasModified();  // Display change status flag when document is changed
private:
    bool maybeSave();  // Do you need to save
    void setCurrentFile(const QString &fileName); // Set Current File
    QString curFile;  // Save the current file path
    bool isUntitled;  // As a flag whether the current file is saved to the hard disk or not
};

#endif // MDICHILD_H

MdiChild.cpp

#include "mdichild.h"
#include <QFile>
#include <QTextStream>
#include <QMessageBox>
#include <QFileInfo>
#include <QApplication>
#include <QFileDialog>
#include <QCloseEvent>
#include <QPushButton>
#include <QMenu>
#include <qtextcodec.h>
MdiChild::MdiChild(QWidget *parent) :
    QTextEdit(parent)
{
    setAttribute(Qt::WA_DeleteOnClose); // This will destroy objects of this class when the child window closes
    isUntitled = true;  // Initial isUntitled is true
}

QTextCodec *codec1 = QTextCodec::codecForName("GB2312");//Show as Chinese Character

void MdiChild::newFile() // New File Operation
{
    static int sequenceNumber = 1;
    // Set the window number because it is always saved, so you need to use a static variable

    isUntitled = true; // New document not saved

    // Name the current file unnamed and numbered. Use the numbering first and add 1
    curFile = codec1->toUnicode("Unnamed Document%1.txt").arg(sequenceNumber++);


    // Set the window title, use [*] to display "*" number after the file name is changed
    setWindowTitle(curFile + "[*]" + codec1->toUnicode(" - Xiao Yi Multi-document Editor"));

    // Sends a contentsChanged() signal when the document is changed.
    // Execute our documentWasModified() slot function
    connect(document(), SIGNAL(contentsChanged()),
            this, SLOT(documentWasModified()));

}

void MdiChild::documentWasModified() //When a document is changed, the window displays a change status flag
{
    // Determine if our editor content has changed based on the return value of the document's isModified() function
    // If it's changed, the'*'sign will be displayed where the [*] sign is set, and here we'll show it in the window title
    setWindowModified(document()->isModified());
}

bool MdiChild::loadFile(const QString &fileName) // load file
{
    QFile file(fileName); // New QFile Object
    if (!file.open(QFile::ReadOnly | QFile::Text)) {
        QMessageBox::warning(this, codec1->toUnicode("Xiao Yi Multi-document Editor"),
                             codec1->toUnicode("Unable to read file %1:\n%2.")
                             .arg(fileName).arg(file.errorString()));
        return false; // Open the file read-only, prompt for errors, and return false
    }

    QTextStream in(&file); // New Text Flow Object
    QApplication::setOverrideCursor(Qt::WaitCursor); // Set the mouse state to wait
    setPlainText(in.readAll());  // Read the entire text of the file and add it to the editor
    QApplication::restoreOverrideCursor(); // Restore mouse state

    setCurrentFile(fileName); // Set Current File

    connect(document(), SIGNAL(contentsChanged()),
            this, SLOT(documentWasModified()));

    return true;
}

void MdiChild::setCurrentFile(const QString &fileName) // Set Current File
{
    // canonicalFilePath() removes symbolic links in paths, such as'. 'and'.'.
    curFile = QFileInfo(fileName).canonicalFilePath();

    isUntitled = false; // The file has been saved
    document()->setModified(false); // Document has not been changed
    setWindowModified(false); // Window does not display changed flag

    // Set the window title, userFriendlyCurrentFile() returns the file name
    setWindowTitle(userFriendlyCurrentFile() + "[*]");

}

QString MdiChild::userFriendlyCurrentFile() // Extract File Name
{
    return QFileInfo(curFile).fileName(); // Extract file name from file path
}

bool MdiChild::save() // Save Operation
{
    if (isUntitled) { // Save as operation if file has not been saved
        return saveAs();
    } else {
        return saveFile(curFile); // Otherwise save the file directly
    }
}

bool MdiChild::saveAs() // Save As Operation
{
    // Gets the file path and returns false if it is empty
    QString fileName = QFileDialog::getSaveFileName(this, codec1->toUnicode("Save As"),curFile);
    if (fileName.isEmpty())
        return false;

    return saveFile(fileName); // Otherwise save the file
}

bool MdiChild::saveFile(const QString &fileName) // Save File
{
    QFile file(fileName);
    if (!file.open(QFile::WriteOnly | QFile::Text)) {
        QMessageBox::warning(this, codec1->toUnicode("Xiao Yi Multi-document Editor"),
                             codec1->toUnicode("Cannot write to file %1:\n%2.")
                             .arg(fileName).arg(file.errorString()));
        return false;
    }

    QTextStream out(&file);
    QApplication::setOverrideCursor(Qt::WaitCursor);
    out << toPlainText(); // Write as plain text file
    QApplication::restoreOverrideCursor();

    setCurrentFile(fileName);
    return true;
}


void MdiChild::closeEvent(QCloseEvent *event)
{
    if (maybeSave()) { // Close the window if the maybeSave() function returns true
        event->accept();
    } else {   // Otherwise ignore the event
        event->ignore();
    }
}


bool MdiChild::maybeSave()  // Do you need to save
{
    if (document()->isModified()) { // If the document has been changed
        QMessageBox box;
        box.setWindowTitle(codec1->toUnicode("Xiao Yi Multi-document Editor"));
        box.setText(codec1->toUnicode("Whether to save pairs of%1"Change?")
                    .arg(userFriendlyCurrentFile()));
        box.setIcon(QMessageBox::Warning);

        // Add button, QMessageBox::YesRole can indicate the behavior of this button
        QPushButton *yesBtn = box.addButton(codec1->toUnicode("yes(&Y)"),QMessageBox::YesRole);

        box.addButton(codec1->toUnicode("no(&N)"),QMessageBox::NoRole);
        QPushButton *cancelBtn = box.addButton(codec1->toUnicode("cancel"),
                                               QMessageBox::RejectRole);
        box.exec(); // Pop up a dialog box to let the user choose whether to save the changes or cancel the close operation
        if (box.clickedButton() == yesBtn)// Returns the result of the save operation if the user chooses yes
            return save();
        else if (box.clickedButton() == cancelBtn) // Return false if you choose to cancel
            return false;
    }
    return true; // Return true directly if the document has not changed
}

void MdiChild::contextMenuEvent(QContextMenuEvent *e) // Right-click menu events
{
    QMenu *menu = new QMenu; // Create a menu and add actions to it
    QAction *undo = menu->addAction(codec1->toUnicode("Revoke(&U)"),this,
                                    SLOT(undo()),QKeySequence::Undo);
    undo->setEnabled(document()->isUndoAvailable());
    QAction *redo = menu->addAction(codec1->toUnicode("recovery(&R)"),this,
                                    SLOT(redo()),QKeySequence::Redo);
    redo->setEnabled(document()->isRedoAvailable());
    menu->addSeparator();
    QAction *cut = menu->addAction(codec1->toUnicode("shear(&T)"),this,
                                   SLOT(cut()),QKeySequence::Cut);
    cut->setEnabled(textCursor().hasSelection());
    QAction *copy = menu->addAction(codec1->toUnicode("copy(&C)"),this,
                                    SLOT(copy()),QKeySequence::Copy);
    copy->setEnabled(textCursor().hasSelection());
    menu->addAction(codec1->toUnicode("paste(&P)"),this,SLOT(paste()),QKeySequence::Paste);
    QAction *clear = menu->addAction(codec1->toUnicode("empty"),this,SLOT(clear()));
    clear->setEnabled(!document()->isEmpty());
    menu->addSeparator();
    QAction *select = menu->addAction(codec1->toUnicode("Select All"),this,
                                SLOT(selectAll()),QKeySequence::SelectAll);
    select->setEnabled(!document()->isEmpty());
    menu->exec(e->globalPos()); // Get the location of the mouse and display the menu in that location
    delete menu; // Finally destroy this menu
}



1.2 MainWindow class code is as follows

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
class MdiChild;
class QMdiSubWindow;
class QSignalMapper;
namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_actionNew_triggered(); // New File Menu
    void updateMenus(); // Update Menu
    MdiChild *createMdiChild(); // Create subwindows
    void setActiveSubWindow(QWidget *window); // Set Active Subwindow

    void on_actionOpen_triggered(); // Open File Menu

    void updateWindowMenu(); // Update Window Menu

    void on_actionSave_triggered();

    void on_actionSaveAs_triggered();

    void on_actionUndo_triggered();

    void on_actionRedo_triggered();

    void on_actionCut_triggered();

    void on_actionCopy_triggered();

    void on_actionPaste_triggered();

    void on_actionClose_triggered();

    void on_actionCloseAll_triggered();

    void on_actionTile_triggered();

    void on_actionCascade_triggered();

    void on_actionNext_triggered();

    void on_actionPrevious_triggered();

    void on_actionAbout_triggered();

    void on_actionAboutQt_triggered();

    void on_actionExit_triggered();

    void showTextRowAndCol(); // Display line and column numbers for text

private:
    Ui::MainWindow *ui;
    QAction *actionSeparator; // Separator
    MdiChild *activeMdiChild(); // Active Window
    QMdiSubWindow *findMdiChild(const QString &fileName);// Find child windows

    QSignalMapper *windowMapper; // Signal Mapper

    void readSettings();  // Read Window Settings
    void writeSettings(); // Write window settings


    void initWindow(); // Initialization window

protected:
    void closeEvent(QCloseEvent *event);  // Close Event
};

#endif // MAINWINDOW_H

MainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mdichild.h"
#include <QMdiSubWindow>
#include <QFileDialog>
#include <QSignalMapper>
#include <QMessageBox>
#include <QSettings>
#include <QCloseEvent>
#include <QLabel>
#include <qtextcodec.h>


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    actionSeparator = new QAction(this); // Create Interceptor Action
    actionSeparator->setSeparator(true); // Set the spacer in it
    updateMenus();   // Update Menu
    connect(ui->mdiArea,SIGNAL(subWindowActivated(QMdiSubWindow*)),this,
            SLOT(updateMenus()));  // Update menu when there is an active window

    windowMapper = new QSignalMapper(this); // Create Signal Mapper
    connect(windowMapper, SIGNAL(mapped(QWidget*)), // Mapper Re-transmit Signal
            this, SLOT(setActiveSubWindow(QWidget*))); // Set Active Window

    // Update the window menu, and set the window menu to be updated when it is about to be displayed
    updateWindowMenu();
    connect(ui->menuW,SIGNAL(aboutToShow()),this,SLOT(updateWindowMenu()));


    readSettings(); // Read window settings information at initial window
    initWindow(); // Initialization window
}



QTextCodec *codec = QTextCodec::codecForName("GB2312");
MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_actionNew_triggered()  // New File Menu
{
    MdiChild *child = createMdiChild(); // Create MdiChild
    child->newFile(); // new file
    child->show(); // Show child windows
}

MdiChild * MainWindow::createMdiChild() // Create child widgets
{
    MdiChild *child = new MdiChild; // Create MdiChild Part
    ui->mdiArea->addSubWindow(child); // Add a child window to a multi-document area with child as the central part

    // Set whether the cut-copy action is available based on whether the QTextEdit class can replicate the signal
    connect(child,SIGNAL(copyAvailable(bool)),ui->actionCut,
            SLOT(setEnabled(bool)));
    connect(child,SIGNAL(copyAvailable(bool)),ui->actionCopy,
            SLOT(setEnabled(bool)));

    // Set whether the undo recovery action is available based on whether the QTextDocument class can undo the recovery signal
    connect(child->document(),SIGNAL(undoAvailable(bool)),
            ui->actionUndo,SLOT(setEnabled(bool)));
    connect(child->document(),SIGNAL(redoAvailable(bool)),
            ui->actionRedo,SLOT(setEnabled(bool)));

    // Whenever the cursor position in the editor changes, the row and column numbers are displayed again
    connect(child,SIGNAL(cursorPositionChanged()),this,SLOT(showTextRowAndCol()));

    return child;
}

void MainWindow::updateMenus() // Update Menu
{
    bool hasMdiChild = (activeMdiChild() != 0); // Is there an active window
    ui->actionSave->setEnabled(hasMdiChild);   // Set whether each action is available
    ui->actionSaveAs->setEnabled(hasMdiChild);
    ui->actionPaste->setEnabled(hasMdiChild);
    ui->actionClose->setEnabled(hasMdiChild);
    ui->actionCloseAll->setEnabled(hasMdiChild);
    ui->actionTile->setEnabled(hasMdiChild);
    ui->actionCascade->setEnabled(hasMdiChild);
    ui->actionNext->setEnabled(hasMdiChild);
    ui->actionPrevious->setEnabled(hasMdiChild);
    actionSeparator->setVisible(hasMdiChild); // Set whether the spacer is displayed

    bool hasSelection = (activeMdiChild()
                         && activeMdiChild()->textCursor().hasSelection());

    // Cut-and-copy is only available if there is an active window and selected text
    ui->actionCut->setEnabled(hasSelection);
    ui->actionCopy->setEnabled(hasSelection);

    ui->actionUndo->setEnabled(activeMdiChild() // Has active window and document has undo action
                          && activeMdiChild()->document()->isUndoAvailable());
    ui->actionRedo->setEnabled(activeMdiChild() // Active window and document recovery
                          && activeMdiChild()->document()->isRedoAvailable());
}

MdiChild * MainWindow::activeMdiChild() // Active Window
{
    // If there is an active window, convert the central part inside to the MdiChild type
    if (QMdiSubWindow *activeSubWindow = ui->mdiArea->activeSubWindow())
        return qobject_cast<MdiChild *>(activeSubWindow->widget());
    return 0; // No active window, return 0 directly
}

void MainWindow::on_actionOpen_triggered() // Open File Menu
{
    QString fileName = QFileDialog::getOpenFileName(this); // Get File Path
    if (!fileName.isEmpty()) { // If the path is not empty, check to see if the file is open
        QMdiSubWindow *existing = findMdiChild(fileName);
        if (existing) { // If it already exists, set the corresponding child window as the active window
            ui->mdiArea->setActiveSubWindow(existing);
            return;
        }

        MdiChild *child = createMdiChild(); // If not, create a new subwindow
        if (child->loadFile(fileName)) {
            ui->statusBar->showMessage(codec->toUnicode("Open File Successfully"), 2000);
            child->show();
        } else {
            child->close();
        }
    }
}

QMdiSubWindow * MainWindow::findMdiChild(const QString &fileName) // Find child windows
{

    QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath();

    // Use the foreach statement to iterate through the list of subwindows and return the window if its file path is the same as the path you are looking for
    foreach (QMdiSubWindow *window, ui->mdiArea->subWindowList()) {
        MdiChild *mdiChild = qobject_cast<MdiChild *>(window->widget());
        if (mdiChild->currentFile() == canonicalFilePath)
            return window;
    }
    return 0;
}

void MainWindow::setActiveSubWindow(QWidget *window) // Set Active Subwindow
{
    if (!window) // If a widget is passed, set it as the active window
        return;
    ui->mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(window));
}

void MainWindow::updateWindowMenu() // Update Window Menu
{
    ui->menuW->clear(); // Empty the menu before adding individual menu actions
    ui->menuW->addAction(ui->actionClose);
    ui->menuW->addAction(ui->actionCloseAll);
    ui->menuW->addSeparator();
    ui->menuW->addAction(ui->actionTile);
    ui->menuW->addAction(ui->actionCascade);
    ui->menuW->addSeparator();
    ui->menuW->addAction(ui->actionNext);
    ui->menuW->addAction(ui->actionPrevious);
    ui->menuW->addAction(actionSeparator);

    QList<QMdiSubWindow *> windows = ui->mdiArea->subWindowList();
    actionSeparator->setVisible(!windows.isEmpty());
    // Show spacer if there is an active window
    for (int i = 0; i < windows.size(); ++i) { // Traverse through subwindows
        MdiChild *child = qobject_cast<MdiChild *>(windows.at(i)->widget());

        QString text;
        if (i < 9) { // Number as shortcut if the number of windows is less than 9
            text = tr("&%1 %2").arg(i + 1)
                               .arg(child->userFriendlyCurrentFile());
        } else {
            text = tr("%1 %2").arg(i + 1)
                              .arg(child->userFriendlyCurrentFile());
        }
        QAction *action  = ui->menuW->addAction(text); // Add Action to Menu
        action->setCheckable(true); // Set action to select

        // Set current active window action to selected state
        action ->setChecked(child == activeMdiChild());

        // The trigger signal associated with the action is placed on the map() slot function of the signal mapper, which emits the mapped() signal
        connect(action, SIGNAL(triggered()), windowMapper, SLOT(map()));

        // Map the action to the corresponding widget, which is used as a parameter when the mapped() signal is sent
        windowMapper->setMapping(action, windows.at(i));

    }
}

/********************1.3.3 The following codes are partially omitted in the subsection ****************************************/

void MainWindow::on_actionSave_triggered() // Save Menu
{
    if(activeMdiChild() && activeMdiChild()->save())
        ui->statusBar->showMessage(codec->toUnicode("File saved successfully"),2000);
}

void MainWindow::on_actionSaveAs_triggered()  // Save as Menu
{
    if(activeMdiChild() && activeMdiChild()->saveAs())
        ui->statusBar->showMessage(codec->toUnicode("File saved successfully"),2000);
}

void MainWindow::on_actionUndo_triggered() // Undo Menu
{
    if(activeMdiChild()) activeMdiChild()->undo();
}

void MainWindow::on_actionRedo_triggered() // Recovery Menu
{
    if(activeMdiChild()) activeMdiChild()->redo();
}

void MainWindow::on_actionCut_triggered() // Cut Menu
{
    if(activeMdiChild()) activeMdiChild()->cut();
}

void MainWindow::on_actionCopy_triggered() // Copy Menu
{
    if(activeMdiChild()) activeMdiChild()->copy();
}

void MainWindow::on_actionPaste_triggered() // Paste Menu
{
    if(activeMdiChild()) activeMdiChild()->paste();
}

void MainWindow::on_actionClose_triggered() // Close Menu
{
    ui->mdiArea->closeActiveSubWindow();
}

void MainWindow::on_actionCloseAll_triggered() // Close all window menus
{
    ui->mdiArea->closeAllSubWindows();
}

void MainWindow::on_actionTile_triggered() // Tile menu
{
    ui->mdiArea->tileSubWindows();
}

void MainWindow::on_actionCascade_triggered() // Cascade menu
{
    ui->mdiArea->cascadeSubWindows();
}

void MainWindow::on_actionNext_triggered() // Next Menu
{
    ui->mdiArea->activateNextSubWindow();
}

void MainWindow::on_actionPrevious_triggered() // Previous Menu
{
    ui->mdiArea->activatePreviousSubWindow();
}

void MainWindow::on_actionAbout_triggered() // About Menus
{
    QMessageBox::about(this,codec->toUnicode("About this software"),codec->toUnicode("Welcome to me csdn Home page: https://blog.csdn.net/qq_46424406?spm=1003.2020.3001.5343"));
}

void MainWindow::on_actionAboutQt_triggered() // About Qt Menu
{
    qApp->aboutQt(); // Here, qApp is the global pointer to the QApplication object.
                     // This line of code is equivalent to QApplication::aboutQt();
}



void MainWindow::on_actionExit_triggered() // Exit Menu
{
    qApp->closeAllWindows(); // Equivalent to QApplication::closeAllWindows();
}

void MainWindow::closeEvent(QCloseEvent *event) // Close Event
{
    ui->mdiArea->closeAllSubWindows(); // Perform multi-document area closure first
    if (ui->mdiArea->currentSubWindow()) {
        event->ignore(); // Ignore this event if there are windows left open
    } else {
        writeSettings(); // Write window settings before closing
        event->accept();
    }
}

void MainWindow::writeSettings() // Write window settings
{
    QSettings settings("yafeilinux", "myMdi");
    settings.setValue("pos", pos());   // Write location information
    settings.setValue("size", size()); // Write size information
}

void MainWindow::readSettings() // Read Window Settings
{
    QSettings settings("yafeilinux", "myMdi");
    QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
    QSize size = settings.value("size", QSize(400, 400)).toSize();
    move(pos);
    resize(size);
}

void MainWindow::showTextRowAndCol() // Display line and column numbers for text
{
    // If there is an active window, the location of the cursor is displayed
    if(activeMdiChild()){

        // Because both row and column numbers are obtained from zero, we add 1 here
        int rowNum = activeMdiChild()->textCursor().blockNumber()+1;
        int colNum = activeMdiChild()->textCursor().columnNumber()+1;

        ui->statusBar->showMessage(tr("%1 That's ok %2 column")
                                   .arg(rowNum).arg(colNum),2000);
    }
}

void MainWindow::initWindow() // Initialization window
{
    setWindowTitle(codec->toUnicode("Xiao Yi Multi-document Editor"));

    // You can close the toolbar when you right-click on it
    ui->mainToolBar->setWindowTitle(codec->toUnicode("toolbar"));

    // Scrollbars appear when the contents of a multi-document area exceed the visible area
    ui->mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    ui->mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);

    ui->statusBar->showMessage(codec->toUnicode("Welcome to Xiaoyi Document Editor"));

    QLabel *label = new QLabel(this);
    label->setFrameStyle(QFrame::Box | QFrame::Sunken);
    label->setText(
          tr("<a href=\"https://blog.csdn.net/qq_46424406?spm=1003.2020.3001.5343\">xiaoyi.com</a>"));
    label->setTextFormat(Qt::RichText); // Label text is rich text
    label->setOpenExternalLinks(true);  // Can open external links
    ui->statusBar->addPermanentWidget(label);

    ui->actionNew->setStatusTip(codec->toUnicode("Create a file"));




    ui->actionOpen->setStatusTip(codec->toUnicode("Open an existing file"));
    ui->actionSave->setStatusTip(codec->toUnicode("Save Document to Hard Disk"));
    ui->actionSaveAs->setStatusTip(codec->toUnicode("Save the document with a new name"));
    ui->actionExit->setStatusTip(codec->toUnicode("exit from application program"));
    ui->actionUndo->setStatusTip(codec->toUnicode("Undo previous action"));
    ui->actionRedo->setStatusTip(codec->toUnicode("Restore previous operations"));
    ui->actionCut->setStatusTip(codec->toUnicode("Cut the selection to the clipboard"));
    ui->actionCopy->setStatusTip(codec->toUnicode("Copy the selection to the clipboard"));
    ui->actionPaste->setStatusTip(codec->toUnicode("Paste the contents of the clipboard to the current location"));
    ui->actionClose->setStatusTip(codec->toUnicode("close the active window"));
    ui->actionCloseAll->setStatusTip(codec->toUnicode("Close all windows"));
    ui->actionTile->setStatusTip(codec->toUnicode("Tile all windows"));
    ui->actionCascade->setStatusTip(codec->toUnicode("Cascade all windows"));
    ui->actionNext->setStatusTip(codec->toUnicode("Move focus to next window"));
    ui->actionPrevious->setStatusTip(codec->toUnicode("Move focus to the previous window"));
    ui->actionAbout->setStatusTip(codec->toUnicode("Display an introduction to this software"));



}






1.3 Principal Functions

main.cpp

#include <QtWidgets/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

   MainWindow w;
    w.show();

    return a.exec();
}

That's all the code block.

Successfully running has already achieved a basic Notepad function.

3. Procedure Release

Publishing a QT program requires setting the program icon, which is my shark icon. Just design a.Ico file with the file name set to my.ico and add it in the.pro file.

RC_ICONS = my.ico

Then compile, compile using Release, and after successful compilation, you can find a release file in the project directory, which contains a.Exe file, where I am myMdi.exe

But this file cannot be sent directly to someone else (because there is no running environment) so we need to package and publish it.

You can add it through the Qt command window and enter it in the Qt command

windeployqt Route

  What I've entered here is

windeployqt C:\Users\XiaoYi\Desktop\myapp

There are some files added in the original folder as follows

 

Compression is now ready for publication;

summary

This is all the code that Qt writes for a notebook, with the release file and all the project code in the previous section. Most of this code is based on the source code of "Qt and Qt Quick Development Actual Combat Resolution", but it is only implemented on Qt5. The content may be unreasonable. Please correct.

 

 

 

 

 

Topics: Qt