QT开发:深入掌握 QtGui 和 QtWidgets 窗口管理:QMainWindow、QDialog 和 QWidget 的高级应用

news2024/9/30 17:44:29

目录

引言

1. QMainWindow:高级窗口类

基本结构

菜单栏、工具栏和状态栏

菜单栏

工具栏

状态栏

中心部件和可停靠窗口

中心部件

可停靠窗口

示例代码与详解

2. QDialog:对话框窗口类

模态和非模态对话框

模态对话框

非模态对话框

自定义对话框的创建

示例代码与详解

3. QWidget:基础窗口类

基本窗口功能

自定义控件的创建与布局管理

示例代码与详解

4. 综合示例:结合 QMainWindow、QDialog 和 QWidget 开发一个完整的应用程序

主窗口代码

查找对话框代码

综合示例代码

代码解析

主窗口(MainWindow)

槽函数(Slots)

查找对话框(FindDialog)

查找文本功能

完整示例代码

5. 总结

关键要点


引言

        Qt 是一个功能强大的跨平台 C++ 应用程序开发框架,广泛应用于桌面、移动和嵌入式开发。它提供了丰富的功能模块,其中 QtGui 和 QtWidgets 是核心的图形用户界面模块。本篇技术博客将深入讲解 QtGui 和 QtWidgets 模块中窗口管理的关键类:QMainWindowQDialogQWidget,帮助你掌握这些类的基本概念和高级应用技术,旨在让你在学习后能够轻松开发 Qt 应用。

1. QMainWindow:高级窗口类

QMainWindow 是一个高级的窗口类,提供了一个默认的布局,该布局包含一个中心窗口部件和可选的菜单栏、工具栏、状态栏和停靠窗口。这个类是 Qt 应用程序的主窗口的最佳选择。

基本结构

QMainWindow 由以下主要部分组成:

  • 菜单栏 (QMenuBar)
  • 工具栏 (QToolBar)
  • 状态栏 (QStatusBar)
  • 中心部件(Central Widget)
  • 可停靠窗口 (QDockWidget)

菜单栏、工具栏和状态栏

菜单栏

        菜单栏通常位于窗口顶部,用于组织和管理应用程序的菜单项,如下在Qt中使用QMenuBarQMenuQAction类创建一个菜单栏,并添加一个"File"菜单,以及一个"Exit"动作项。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 创建菜单栏
    QMenuBar *menuBar = new QMenuBar(this);
    setMenuBar(menuBar);

    // 添加"File"菜单
    QMenu *fileMenu = menuBar->addMenu("File");

    // 添加"Exit"动作
    QAction *exitAction = fileMenu->addAction("Exit");
    connect(exitAction, &QAction::triggered, this, &QMainWindow::close);
}


展示如下:

工具栏

工具栏通常包含一组操作按钮,用于快速访问常用功能。

  // 创建工具栏
    QToolBar *toolBar = new QToolBar(this);
    addToolBar(toolBar);

   // 向工具栏添加"Exit"动作
    toolBar->addAction(exitAction);
状态栏

状态栏通常位于窗口底部,用于显示状态信息。

QStatusBar *statusBar = new QStatusBar(this);
setStatusBar(statusBar);
statusBar->showMessage("Ready");

中心部件和可停靠窗口

中心部件

中心部件是 QMainWindow 的核心区域,用于显示主要的应用内容。可以通过 setCentralWidget 方法设置中心部件。

QTextEdit *textEdit = new QTextEdit(this);
setCentralWidget(textEdit);
可停靠窗口

可停靠窗口是 QMainWindow 的可选部分,用户可以将其停靠在主窗口的边缘,也可以浮动。

QDockWidget *dockWidget = new QDockWidget("Dockable", this);
addDockWidget(Qt::LeftDockWidgetArea, dockWidget);

QLabel *label = new QLabel("Dockable content", this);
dockWidget->setWidget(label);

示例代码与详解

以下是一个完整的示例,展示了如何使用 QMainWindow 创建一个带有菜单栏、工具栏、状态栏、中心部件和可停靠窗口的主窗口:

#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
#include <QAction>
#include <QDockWidget>
#include <QTextEdit>

class MainWindow : public QMainWindow {
public:
    MainWindow() {
        // 设置中心部件
        QTextEdit *textEdit = new QTextEdit(this);
        setCentralWidget(textEdit);

        // 创建菜单栏
        QMenuBar *menuBar = new QMenuBar(this);
        setMenuBar(menuBar);

        // 添加菜单项和动作
        QMenu *fileMenu = menuBar->addMenu("File");
        QAction *exitAction = fileMenu->addAction("Exit");
        connect(exitAction, &QAction::triggered, this, &QMainWindow::close);

        // 创建工具栏
        QToolBar *toolBar = new QToolBar(this);
        addToolBar(toolBar);
        toolBar->addAction(exitAction);

        // 创建状态栏
        QStatusBar *statusBar = new QStatusBar(this);
        setStatusBar(statusBar);
        statusBar->showMessage("Ready");

        // 创建可停靠窗口
        QDockWidget *dockWidget = new QDockWidget("Dockable", this);
        addDockWidget(Qt::LeftDockWidgetArea, dockWidget);

        QLabel *label = new QLabel("Dockable content", this);
        dockWidget->setWidget(label);
    }
};

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

    MainWindow mainWindow;
    mainWindow.show();

    return app.exec();
}

这个示例展示了如何使用 QMainWindow 及其主要组件来创建一个功能齐全的主窗口。

2. QDialog:对话框窗口类

QDialog 是一个用于对话框窗口的基类。对话框可以是模态的(阻塞所有其他窗口)或非模态的(不阻塞其他窗口)。常用于提示信息、用户输入等场景。

模态和非模态对话框

模态对话框

模态对话框在显示期间会阻塞所有其他窗口,用户必须与之交互才能继续使用应用程序。可以通过 exec() 方法执行模态对话框。

CustomDialog dialog;
if (dialog.exec() == QDialog::Accepted) {
    qDebug() << "Dialog accepted";
}
非模态对话框

非模态对话框不会阻塞其他窗口,用户可以自由切换到其他窗口。可以通过 show() 方法显示非模态对话框。

CustomDialog *dialog = new CustomDialog(this);
dialog->show();

自定义对话框的创建

创建自定义对话框通常涉及添加控件(如标签、按钮)并使用布局管理器组织这些控件。

示例代码与详解

以下是一个完整的示例,展示了如何创建一个自定义模态对话框:

#include <QApplication>
#include <QDialog>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>

class CustomDialog : public QDialog {
public:
    CustomDialog(QWidget *parent = nullptr) : QDialog(parent) {
        QVBoxLayout *layout = new QVBoxLayout(this);

        QLabel *label = new QLabel("This is a custom dialog", this);
        layout->addWidget(label);

        QPushButton *okButton = new QPushButton("OK", this);
        layout->addWidget(okButton);

        connect(okButton, &QPushButton::clicked, this, &QDialog::accept);
    }
};

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

    CustomDialog dialog;
    if (dialog.exec() == QDialog::Accepted) {
        qDebug() << "Dialog accepted";
    }

    return app.exec();
}

这个示例展示了如何创建一个简单的模态对话框,包括一个标签和一个按钮。当用户点击按钮时,对话框关闭并返回 Accepted 状态。

3. QWidget:基础窗口类

QWidget 是所有用户界面对象的基类。所有窗口和控件都是 QWidget 的子类。可以直接使用 QWidget 创建自定义窗口或控件。

基本窗口功能

QWidget 提供了基本的窗口功能,如设置大小、标题、布局管理等。

QWidget *widget = new QWidget();
widget->resize(400, 300);
widget->setWindowTitle("Custom Widget");

自定义控件的创建与布局管理

自定义控件通常是通过继承 QWidget 并重写其绘制和事件处理方法来实现的。布局管理器用于组织控件的布局。

示例代码与详解

以下是一个完整的示例,展示了如何创建一个自定义窗口,包括标签和按钮,并使用布局管理器管理它们的布局:

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QPushButton>

class CustomWidget : public QWidget {
public:
    CustomWidget(QWidget *parent = nullptr) : QWidget(parent) {
        QVBoxLayout *layout = new QVBoxLayout(this);

        QLabel *label = new QLabel("This is a custom widget", this);
        layout->addWidget(label);

        QPushButton *button = new QPushButton("Click me", this);
        layout->addWidget(button);

        connect(button, &QPushButton::clicked, this, &CustomWidget::onButtonClicked);
    }

private slots:
    void onButtonClicked() {
        qDebug() << "Button clicked";
    }
};

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

    CustomWidget widget;
    widget.show();

    return app.exec();
}

这个示例展示了如何使用 QWidget 创建一个自定义窗口,并通过布局管理器组织控件的布局。

4. 综合示例:结合 QMainWindow、QDialog 和 QWidget 开发一个完整的应用程序

为了更好地展示 QMainWindowQDialogQWidget 的综合应用,我们将开发一个简单的文本编辑器应用程序。这个应用程序包含以下功能:

  • 主窗口(QMainWindow)带有菜单栏、工具栏和状态栏。
  • 文件打开和保存功能。
  • 查找对话框(QDialog)。
  • 自定义控件(QWidget)显示文本统计信息。

主窗口代码

#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QToolBar>
#include <QStatusBar>
#include <QTextEdit>
#include <QAction>
#include <QFileDialog>
#include <QMessageBox>
#include <QDockWidget>
#include <QLabel>

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    MainWindow() {
        // 设置中心部件
        textEdit = new QTextEdit(this);
        setCentralWidget(textEdit);

        // 创建菜单栏
        QMenuBar *menuBar = new QMenuBar(this);
        setMenuBar(menuBar);

        // 添加文件菜单和动作
        QMenu *fileMenu = menuBar->addMenu("File");
        QAction *openAction = fileMenu->addAction("Open");
        QAction *saveAction = fileMenu->addAction("Save");
        QAction *exitAction = fileMenu->addAction("Exit");
        connect(openAction, &QAction::triggered, this, &MainWindow::openFile);
        connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);
        connect(exitAction, &QAction::triggered, this, &QMainWindow::close);

        // 创建工具栏
        QToolBar *toolBar = new QToolBar(this);
        addToolBar(toolBar);
        toolBar->addAction(openAction);
        toolBar->addAction(saveAction);

        // 创建状态栏
        QStatusBar *statusBar = new QStatusBar(this);
        setStatusBar(statusBar);
        statusBar->showMessage("Ready");

        // 创建可停靠窗口
        QDockWidget *dockWidget = new QDockWidget("Statistics", this);
        addDockWidget(Qt::RightDockWidgetArea, dockWidget);

        statsLabel = new QLabel(this);
        dockWidget->setWidget(statsLabel);

        // 更新统计信息
        connect(textEdit, &QTextEdit::textChanged, this, &MainWindow::updateStats);
    }

private slots:
    void openFile() {
        QString fileName = QFileDialog::getOpenFileName(this, "Open File");
        if (!fileName.isEmpty()) {
            QFile file(fileName);
            if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
                textEdit->setPlainText(file.readAll());
                statusBar()->showMessage("File opened", 2000);
            } else {
                QMessageBox::warning(this, "Error", "Cannot open file");
            }
        }
    }

    void saveFile() {
        QString fileName = QFileDialog::getSaveFileName(this, "Save File");
        if (!fileName.isEmpty()) {
            QFile file(fileName);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                file.write(textEdit->toPlainText().toUtf8());
                statusBar()->showMessage("File saved", 2000);
            } else {
                QMessageBox::warning(this, "Error", "Cannot save file");
            }
        }
    }

    void updateStats() {
        int wordCount = textEdit->toPlainText().split(QRegExp("\\s+"), QString::SkipEmptyParts).count();
        int charCount = textEdit->toPlainText().length();
        statsLabel->setText(QString("Words: %1\nCharacters: %2").arg(wordCount).arg(charCount));
    }

private:
    QTextEdit *textEdit;
    QLabel *statsLabel;
};

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

    MainWindow mainWindow;
    mainWindow.show();

    return app.exec();
}

查找对话框代码

#include <QApplication>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QTextEdit>
#include <QMessageBox>

class FindDialog : public QDialog {
    Q_OBJECT

public:
    FindDialog(QTextEdit *editor, QWidget *parent = nullptr) : QDialog(parent), textEdit(editor) {
        QVBoxLayout *mainLayout = new QVBoxLayout(this);

        QHBoxLayout *findLayout = new QHBoxLayout();
        findLayout->addWidget(new QLabel("Find:", this));
        findLineEdit = new QLineEdit(this);
        findLayout->addWidget(findLineEdit);
        mainLayout->addLayout(findLayout);

        QPushButton *findButton = new QPushButton("Find", this);
        mainLayout->addWidget(findButton);
        connect(findButton, &QPushButton::clicked, this, &FindDialog::findText);

        setWindowTitle("Find");
    }

private slots:
    void findText() {
        QString textToFind = findLineEdit->text();
        if (!textEdit->find(textToFind)) {
            QMessageBox::information(this, "Find", "No more occurrences found.");
        }
    }

private:
    QTextEdit *textEdit;
    QLineEdit *findLineEdit;
};

综合示例代码

以下是完整的应用程序代码,结合了 QMainWindowQDialogQWidget 的所有功能:

#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QToolBar>
#include <QStatusBar>
#include <QTextEdit>
#include <QAction>
#include <QFileDialog>
#include <QMessageBox>
#include <QDockWidget>
#include <QLabel>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QPushButton>

class FindDialog : public QDialog {
    Q_OBJECT

public:
    FindDialog(QTextEdit *editor, QWidget *parent = nullptr) : QDialog(parent), textEdit(editor) {
        QVBoxLayout *mainLayout = new QVBoxLayout(this);

        QHBoxLayout *findLayout = new QHBoxLayout();
        findLayout->addWidget(new QLabel("Find:", this));
        findLineEdit = new QLineEdit(this);
        findLayout->addWidget(findLineEdit);
        mainLayout->addLayout(findLayout);

        QPushButton *findButton = new QPushButton("Find", this);
        mainLayout->addWidget(findButton);
        connect(findButton, &QPushButton::clicked, this, &FindDialog::findText);

        setWindowTitle("Find");
    }

private slots:
    void findText() {
        QString textToFind = findLineEdit->text();
        if (!textEdit->find(textToFind)) {
            QMessageBox::information(this, "Find", "No more occurrences found.");
        }
    }

private:
    QTextEdit *textEdit;
    QLineEdit *findLineEdit;
};

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    MainWindow() {
        // 设置中心部件
        textEdit = new QTextEdit(this);
        setCentralWidget(textEdit);

        // 创建菜单栏
        QMenuBar *menuBar = new QMenuBar(this);
        setMenuBar(menuBar);

        // 添加文件菜单和动作
        QMenu *fileMenu = menuBar->addMenu("File");
        QAction *openAction = fileMenu->addAction("Open");
        QAction *saveAction = fileMenu->addAction("Save");
        QAction *exitAction = fileMenu->addAction("Exit");
        connect(openAction, &QAction::triggered, this, &MainWindow::openFile);
        connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);
        connect(exitAction, &QAction::triggered, this, &QMainWindow::close);

        // 添加编辑菜单和查找动作
        QMenu *editMenu = menuBar->addMenu("Edit");
        QAction *findAction = editMenu->addAction("Find");
        connect(findAction, &QAction::triggered, this, &MainWindow::showFindDialog);

        // 创建工具栏
        QToolBar *toolBar = new QToolBar(this);
        addToolBar(toolBar);
        toolBar->addAction(openAction);
        toolBar->addAction(saveAction);
        toolBar->addAction(findAction);

        // 创建状态栏
        QStatusBar *statusBar = new QStatusBar(this);
        setStatusBar(statusBar);
         statusBar->showMessage("Ready");

        // 创建可停靠窗口
        QDockWidget *dockWidget = new QDockWidget("Statistics", this);
        addDockWidget(Qt::RightDockWidgetArea, dockWidget);

        statsLabel = new QLabel(this);
        dockWidget->setWidget(statsLabel);

        // 更新统计信息
        connect(textEdit, &QTextEdit::textChanged, this, &MainWindow::updateStats);
    }

private slots:
    void openFile() {
        QString fileName = QFileDialog::getOpenFileName(this, "Open File");
        if (!fileName.isEmpty()) {
            QFile file(fileName);
            if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
                textEdit->setPlainText(file.readAll());
                statusBar()->showMessage("File opened", 2000);
                updateStats();
            } else {
                QMessageBox::warning(this, "Error", "Cannot open file");
            }
        }
    }

    void saveFile() {
        QString fileName = QFileDialog::getSaveFileName(this, "Save File");
        if (!fileName.isEmpty()) {
            QFile file(fileName);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                file.write(textEdit->toPlainText().toUtf8());
                statusBar()->showMessage("File saved", 2000);
            } else {
                QMessageBox::warning(this, "Error", "Cannot save file");
            }
        }
    }

    void showFindDialog() {
        FindDialog dialog(textEdit, this);
        dialog.exec();
    }

    void updateStats() {
        int wordCount = textEdit->toPlainText().split(QRegExp("\\s+"), QString::SkipEmptyParts).count();
        int charCount = textEdit->toPlainText().length();
        statsLabel->setText(QString("Words: %1\nCharacters: %2").arg(wordCount).arg(charCount));
    }

private:
    QTextEdit *textEdit;
    QLabel *statsLabel;
};

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

    MainWindow mainWindow;
    mainWindow.show();

    return app.exec();
}

代码解析

这个综合示例展示了如何结合使用 QMainWindowQDialogQWidget 来开发一个功能齐全的文本编辑器应用程序。以下是对各个部分的详细解析:

主窗口(MainWindow)
  • QMainWindow 初始化:在构造函数中,我们初始化了 QMainWindow 的各个组件,包括菜单栏、工具栏、状态栏、中心部件和可停靠窗口。
  • 菜单栏:创建了一个菜单栏,并添加了文件菜单和编辑菜单。文件菜单包含打开、保存和退出动作;编辑菜单包含查找动作。
  • 工具栏:创建了一个工具栏,并添加了打开、保存和查找动作。工具栏可以快速访问常用功能。
  • 状态栏:创建了一个状态栏,并在状态栏上显示初始消息“Ready”。
  • 中心部件:设置了一个 QTextEdit 作为中心部件,用于显示和编辑文本内容。
  • 可停靠窗口:创建了一个 QDockWidget 作为可停靠窗口,用于显示文本统计信息(字数和字符数)。
  • 信号槽连接:通过信号槽连接机制,关联了各种用户操作(如打开文件、保存文件、查找文本)和相应的槽函数。
槽函数(Slots)
  • openFile:打开文件对话框,让用户选择要打开的文件,并将文件内容读取到 QTextEdit 中。
  • saveFile:保存文件对话框,让用户选择保存文件的位置,并将 QTextEdit 中的内容写入文件。
  • showFindDialog:显示查找对话框(FindDialog),让用户输入要查找的文本。
  • updateStats:更新文本统计信息,包括字数和字符数,并显示在可停靠窗口的标签中。
查找对话框(FindDialog)
  • QDialog 初始化:在构造函数中,我们初始化了 QDialog 的各个组件,包括标签、文本输入框和查找按钮。
  • 布局管理:使用垂直布局和水平布局组合,组织对话框中的控件。
  • 信号槽连接:通过信号槽连接机制,关联查找按钮的点击操作和 findText 槽函数。
查找文本功能
  • findText:获取用户输入的查找文本,并在 QTextEdit 中查找。如果查找到文本,将其选中并滚动到可视区域;如果未找到更多匹配项,显示提示信息。

完整示例代码

以下是完整的应用程序代码,包括主窗口、查找对话框和所有功能的实现:

#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QToolBar>
#include <QStatusBar>
#include <QTextEdit>
#include <QAction>
#include <QFileDialog>
#include <QMessageBox>
#include <QDockWidget>
#include <QLabel>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QRegExp>

class FindDialog : public QDialog {
    Q_OBJECT

public:
    FindDialog(QTextEdit *editor, QWidget *parent = nullptr) : QDialog(parent), textEdit(editor) {
        QVBoxLayout *mainLayout = new QVBoxLayout(this);

        QHBoxLayout *findLayout = new QHBoxLayout();
        findLayout->addWidget(new QLabel("Find:", this));
        findLineEdit = new QLineEdit(this);
        findLayout->addWidget(findLineEdit);
        mainLayout->addLayout(findLayout);

        QPushButton *findButton = new QPushButton("Find", this);
        mainLayout->addWidget(findButton);
        connect(findButton, &QPushButton::clicked, this, &FindDialog::findText);

        setWindowTitle("Find");
    }

private slots:
    void findText() {
        QString textToFind = findLineEdit->text();
        if (!textEdit->find(textToFind)) {
            QMessageBox::information(this, "Find", "No more occurrences found.");
        }
    }

private:
    QTextEdit *textEdit;
    QLineEdit *findLineEdit;
};

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    MainWindow() {
        // 设置中心部件
        textEdit = new QTextEdit(this);
        setCentralWidget(textEdit);

        // 创建菜单栏
        QMenuBar *menuBar = new QMenuBar(this);
        setMenuBar(menuBar);

        // 添加文件菜单和动作
        QMenu *fileMenu = menuBar->addMenu("File");
        QAction *openAction = fileMenu->addAction("Open");
        QAction *saveAction = fileMenu->addAction("Save");
        QAction *exitAction = fileMenu->addAction("Exit");
        connect(openAction, &QAction::triggered, this, &MainWindow::openFile);
        connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);
        connect(exitAction, &QAction::triggered, this, &QMainWindow::close);

        // 添加编辑菜单和查找动作
        QMenu *editMenu = menuBar->addMenu("Edit");
        QAction *findAction = editMenu->addAction("Find");
        connect(findAction, &QAction::triggered, this, &MainWindow::showFindDialog);

        // 创建工具栏
        QToolBar *toolBar = new QToolBar(this);
        addToolBar(toolBar);
        toolBar->addAction(openAction);
        toolBar->addAction(saveAction);
        toolBar->addAction(findAction);

        // 创建状态栏
        QStatusBar *statusBar = new QStatusBar(this);
        setStatusBar(statusBar);
        statusBar->showMessage("Ready");

        // 创建可停靠窗口
        QDockWidget *dockWidget = new QDockWidget("Statistics", this);
        addDockWidget(Qt::RightDockWidgetArea, dockWidget);

        statsLabel = new QLabel(this);
        dockWidget->setWidget(statsLabel);

        // 更新统计信息
        connect(textEdit, &QTextEdit::textChanged, this, &MainWindow::updateStats);
    }

private slots:
    void openFile() {
        QString fileName = QFileDialog::getOpenFileName(this, "Open File");
        if (!fileName.isEmpty()) {
            QFile file(fileName);
            if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
                textEdit->setPlainText(file.readAll());
                statusBar()->showMessage("File opened", 2000);
                updateStats();
            } else {
                QMessageBox::warning(this, "Error", "Cannot open file");
            }
        }
    }

    void saveFile() {
        QString fileName = QFileDialog::getSaveFileName(this, "Save File");
        if (!fileName.isEmpty()) {
            QFile file(fileName);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                file.write(textEdit->toPlainText().toUtf8());
                statusBar()->showMessage("File saved", 2000);
            } else {
                QMessageBox::warning(this, "Error", "Cannot save file");
            }
        }
    }

    void showFindDialog() {
        FindDialog dialog(textEdit, this);
        dialog.exec();
    }

    void updateStats() {
        int wordCount = textEdit->toPlainText().split(QRegExp("\\s+"), QString::SkipEmptyParts).count();
        int charCount = textEdit->toPlainText().length();
        statsLabel->setText(QString("Words: %1\nCharacters: %2").arg(wordCount).arg(charCount));
    }

private:
    QTextEdit *textEdit;
    QLabel *statsLabel;
};

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

    MainWindow mainWindow;
    mainWindow.show();

    return app.exec();
}

通过这个完整的示例代码,我们展示了如何结合使用 QMainWindowQDialogQWidget 来开发一个功能齐全的文本编辑器应用程序。希望这个示例能够帮助你更好地理解 Qt 的窗口管理和控件使用技巧。

5. 总结

本篇技术博客详细介绍了 QtGui 和 QtWidgets 模块中 QMainWindowQDialogQWidget 的基本概念和高级应用技术。通过详细解析和完整的示例代码,我们展示了如何创建功能齐全的主窗口、模态和非模态对话框,以及自定义控件。希望这篇文章能够帮助你在学习后轻松掌握 Qt 的窗口管理技术,并应用于实际开发中。

关键要点

  • QMainWindow:提供了菜单栏、工具栏、状态栏、中心部件和可停靠窗口的支持,是主窗口的最佳选择。
  • QDialog:用于创建模态和非模态对话框,常用于提示信息和用户输入。
  • QWidget:所有用户界面对象的基类,可以用于创建自定义窗口和控件。
  • 综合应用:通过结合使用 QMainWindowQDialog 和 QWidget,可以开发出功能丰富且用户友好的应用程序。

通过掌握这些关键类和技术,你可以轻松开发复杂的 Qt 应用程序,并自信地应对各种用户界面需求。希望这篇文章对你的 Qt 开发之旅有所帮助!zhanshizhan'shi

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「Java开发指南」如何用MyEclipse为iPhone搭建Spring应用程序?

本教程将引导您完成在iPhone上使用的软件组件生成&#xff0c;这就产生了一个完全实现的可运行iPhone应用程序&#xff0c;可以立即用于验证和测试生成的iPhone组件。在本教程中&#xff0c;您将学习如何&#xff1a; 从数据库表搭建到现有项目部署应用程序 MyEclipse v2024.…

点云配准ICP算法笔记

参考&#xff1a;【PCL】—— 点云配准ICP(Iterative Closest Point)算法_icp点云配准-CSDN博客 点云配准 计算出两个点云簇之间的变换矩阵&#xff0c;从而计算出位姿等信息&#xff0c;学习点云配准的目的是想要计算相邻两帧物体的点云之间的变换位姿&#xff0c;从而得到物…

企业合规新动力:天锐股份助力等保制度落地实施

等保是指对网络&#xff08;含信息系统、数据&#xff09;实施分等级保护、分等级监管&#xff0c;对网络中使用的网络安全产品实行按等级管理&#xff0c;对网络中发生的安全事件分等级响应、处置。 【地址&#xff1a;点击了解天锐股份数据安全产品】 等保的必要性 频发的网…

选择国企eHR人事管理系统的时候,应该注意什么?

近年来&#xff0c;中国正步入高速发展的黄金时期&#xff0c;国有企业&#xff08;国企&#xff09;在追求效率和管理水平提升方面迈出了重要步伐。为了进一步实现数字化、流程化和科学化管理&#xff0c;越来越多的国企选择引进eHR&#xff08;电子人力资源管理&#xff09;系…

Java-IO模型

所谓I/O就是计算机内存与外部设备之间拷贝数据的过程。由于CPU访问内存的速度远远高于外部设备&#xff0c;因此CPU是先把外部设备的数据读到内存里&#xff0c;然后再进行处理。对于一个网络I/O通信过程&#xff0c;比如网络数据读取&#xff0c;会涉及两个对象&#xff0c;一…

VMware复制Ubuntu虚拟机后网卡失效的问题

为了在个人电脑上搭建集群&#xff0c;我使用了多台VMware虚拟机来模拟集群主机。之前虚拟机的操作系统是Redhat时&#xff0c;我复制虚拟机后网卡功能没有问题&#xff0c;但这次换成Ubuntu操作系统&#xff0c;我复制了虚拟机后同时启动这两台虚拟机&#xff0c;其中一台虚拟…

软件测试谣言二三事,认真你就输了

软件测试在近几年关注度日益升高,这得益于行业快速发展,以及很多公司和国际接轨后,对质量要求的增高。 在网上相关的讨论中,有许多观点并不符合我在这个行业的感知,针对一些观点,在这里结合我自己多年的从事经验,给大家辟辟谣。 谣言一:软件测试入门容易,会点点点就…

vue结合element-ui实现列表拖拽变化位置,点击拖动图标拖动整个列表元素,使用tsx格式编写

先来看下需要实现的效果 当鼠标放在左侧图标上时&#xff0c;可以拖动整个列表元素&#xff0c;调整顺序 思路介绍 使用draggable可以设置元素可拖动&#xff0c;然后分别设置三个事件处理函数&#xff0c;监听onDragstart、onDragover、onDragend三个事件 注意&#xff1a…

基于STM32的智能温度监控系统

目录 引言项目背景环境准备 硬件准备软件安装与配置系统设计 系统架构关键技术代码示例 传感器数据采集与处理温度监控与报警显示功能应用场景结论 1. 引言 温度监控系统在许多应用场景中具有重要作用&#xff0c;例如工业、农业以及家居生活。通过使用STM32微控制器、温度传…

Excel:常用函数

一、DAYS&#xff08;返回两个日期之间的天数&#xff09; 以下演示是在windows操作系统环境&#xff0c;office软件进行操作的 1.1 单元格设置日期格式 1.2 设置Days函数 公式&#xff1a;DAYS(C2,B2) 全部天数 二、SUM&#xff08;求和&#xff09; 公式&#xff1a;SUM(…

第二届两岸新经济产业发展研讨会闭幕,爱迪斯通董事长发表演讲

9月29日&#xff0c;第二届两岸新经济产业发展研讨会在福州高新区圆满落幕。此次研讨会由清华大学两岸发展研究院主办&#xff0c;福州市招商行动领导小组办公室、福州高新区承办&#xff0c;汇聚了两岸的专家学者及企业家代表近200人&#xff0c;共同探讨新质生产力的发展与两…

宠物医院微信小程序源码

文章目录 前言研究背景研究内容一、主要技术&#xff1f;二、项目内容1.整体介绍&#xff08;示范&#xff09;2.系统分析3.数据表信息4.运行截图5.部分代码介绍 总结 前言 随着当代社会科技的迅速发展&#xff0c;计算机网络时代正式拉来帷幕&#xff0c;它颠覆性的影响着社会…

【回眸】Tessy 单元测试软件使用指南(四)常见报错及解决方案与批量初始化的经验

前言 分析时Tessy的报错 1.fatal error: Tricore/Compilers/Compilers.h: No such file or directory 2.error: #error "Compiler unsupported" 3.warning: invalid suffix on literal;C11 requires a space between literal and string macro 4.error: unknown…

YOLOv7改进:Unified-loU,用于高品质目标检测的统一loU ,2024年8月最新IoU

💡💡💡现有IoU问题点:IoU (Intersection over Union)作为模型训练的关键,极大地显示了当前预测框与Ground Truth框之间的差异。后续研究者不断在IoU中加入更多的考虑因素,如中心距离、纵横比等。然而,仅仅提炼几何差异是有上限的;而且新的对价指数与借据本身存在潜在…

优化Mysql

目录 Mysql优化就四种&#xff1a;定位慢查询/sql执行计划/索引/Sql优化经验... 2 1Mysql如何定位慢查询&#xff1f;... 2 2Sql语句执行很慢&#xff0c;如何分析呢&#xff1f;... 3 2.1那这个SQL语句执行很慢,如何分析呢?. 3 3&#xff0e;了解过索引吗?(什么是索引)…

DC00018基于java swing+MySQL花卉信息管理系统

1、项目功能演示 DC00018基于java swingMySQL花卉信息管理系统java项目信息管理系统 2、项目功能描述 基于java swingMySQL花卉信息管理系统 系统包括用户信息管理以及花卉信息管理等功能。 3、项目运行截图 4、项目核心代码 4.1 日期格式化 package utils;import java.t…

C++ STL容器(四) —— vector底层剖析

这篇讲解vector&#xff0c;不说废话&#xff0c;直接开始&#xff01; 文章目录 原理UML类图代码实现构造函数插入元素删除元素清空容器析构函数赋值运算符 案例分析 原理 这里简单说一下 vector 的大致思想&#xff0c;动态数组&#xff0c;即它的长度会随着我们插入元素而产…

【YOLO目标检测二维码数据集】共3112张、已标注txt格式、有训练好的yolov5的模型

目录 说明图片示例 说明 数据集格式&#xff1a;YOLO格式 图片数量&#xff1a;3112 标注数量(txt文件个数)&#xff1a;3112 标注类别数&#xff1a;1 标注类别名称&#xff1a;qrcode 数据集下载&#xff1a;二维码数据集 图片示例 数据集图片&#xff1a; 数据集…

【开源免费】基于SpringBoot+Vue.JS微服务在线教育系统(JAVA毕业设计)

本文项目编号 T 060 &#xff0c;文末自助获取源码 \color{red}{T060&#xff0c;文末自助获取源码} T060&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

【hot100-java】【合并两个有序链表】

记忆中&#xff0c;两个指针合并即可。 建立哨兵节点dum /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { t…