第三章 创建主窗口

来源:互联网 发布:淘宝网京东商城童装 编辑:程序博客网 时间:2024/05/01 03:19

创建一个主窗口,具有菜单、工具栏、状态栏和对话框之类的界面和功能。实现电子制表软件的主窗口框架。

效果:




mainwindow.h
头文件就不做太多解释,以注释的方式解释函数
#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#include <QAction>#include <QLabel>#include <QFileDialog>#include <QMessageBox>#include <QStatusBar>#include <QToolBar>#include <QMenu>#include <QMenuBar>#include "spreadsheet.h"#include "finddialog.h"class MainWindow : public QMainWindow{    Q_OBJECTpublic:    MainWindow();protected://是Qwidget类中的一个虚函数,当用户关闭这个窗口时会被自动调用诶,可以在里面做自己想做的事情。    void closeEvent(QCloseEvent *event);private slots://声明了很多槽函数,作为窗口的功能菜单项和其中子菜单项 File->New这种的。    //Filevoid newFile();    void open();    bool save();    bool saveAs();    void openRecentFile();//close()//Edit    void find();    void goToCell();//Tools    void sort();//Help    void about();//    void updateStatusBar();    void spreadsheetModified();private:    //私有函数实现菜单功能    void createActions();    void createMenus();    void createContextMenu();    void createToolBars();    void createStatusBar();    void readSettings();    void writeSettings();    bool okToContinue();    bool loadFile(const QString &fileName);    bool saveFile(const QString &fileName);    void setCurrentFile(const QString &fileName);    void updateRecentFileActions();    QString strippedName(const QString &fullFileName);    Spreadsheet *spreadsheet;    FindDialog *findDialog;    QLabel *locationLabel;    QLabel *formulaLabel;    QStringList recentFiles;    QString curFile;    enum { MaxRecentFiles = 5 };    QAction *recentFileActions[MaxRecentFiles];    QAction *separatorAction;    QMenu *fileMenu;    QMenu *editMenu;    QMenu *selectSubMenu;    QMenu *toolsMenu;    QMenu *optionsMenu;    QMenu *helpMenu;    QToolBar *fileToolBar;    QToolBar *editToolBar;    QAction *newAction;    QAction *openAction;    QAction *saveAction;    QAction *saveAsAction;    QAction *exitAction;    QAction *cutAction;    QAction *copyAction;    QAction *pasteAction;    QAction *deleteAction;    QAction *selectRowAction;    QAction *selectColumnAction;    QAction *selectAllAction;    QAction *findAction;    QAction *goToCellAction;    QAction *recalculateAction;    QAction *sortAction;    QAction *showGridAction;    QAction *autoRecalcAction;    QAction *aboutAction;    QAction *aboutQtAction;};#endif



mainwindow.cpp
1)先来看构造函数
MainWindow::MainWindow(){//先创建一个Spreadsheet表格窗口部件并且设置为中央窗口    spreadsheet = new Spreadsheet;    setCentralWidget(spreadsheet);//相当于初始化窗口,createXXXX创建窗口中的其他部分    createActions();    createMenus();    createContextMenu();    createToolBars();    createStatusBar();        readSettings();    findDialog = 0;    setWindowIcon(QIcon("images/icon.png"));    setCurrentFile("");}

把findDialog初始化为空,在第一次调用find()时再创建该对象;

这里没有采用Qt的资源机制来加载图片;

2)创建菜单和工具栏
void MainWindow::createActions(){//创建File->New    newAction = new QAction(tr("&New"), this);    newAction->setIcon(QIcon("images/new.png"));    newAction->setShortcut(QKeySequence::New);    newAction->setStatusTip(tr("Create a new spreadsheet file"));    connect(newAction, SIGNAL(triggered()), this, SLOT(newFile()));//创建File->OpenopenAction = new QAction(tr("&Open..."), this);    openAction->setIcon(QIcon("images/open.png"));    openAction->setShortcut(QKeySequence::Open);    openAction->setStatusTip(tr("Open an existing spreadsheet file"));    connect(openAction, SIGNAL(triggered()), this, SLOT(open()));//创建File->SavesaveAction = new QAction(tr("&Save"), this);    saveAction->setIcon(QIcon("images/save.png"));    saveAction->setShortcut(QKeySequence::Save);    saveAction->setStatusTip(tr("Save the spreadsheet to disk"));    connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));//创建File->SaveAs    saveAsAction = new QAction(tr("Save &As..."), this);    saveAsAction->setStatusTip(tr("Save the spreadsheet under a new name"));    connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs()));//创建File->recentFileActions 最近打开文件,检测最近最多的五个    for (int i = 0; i < MaxRecentFiles; ++i) {        recentFileActions[i] = new QAction(this);        recentFileActions[i]->setVisible(false);//创建了但是不显示        connect(recentFileActions[i], SIGNAL(triggered()), this, SLOT(openRecentFile()));    }//创建File->ExitexitAction = new QAction(tr("E&xit"), this);    exitAction->setShortcut(tr("Ctrl+Q"));    exitAction->setStatusTip(tr("Exit the application"));    connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));//创建Edit->Cut    cutAction = new QAction(tr("Cu&t"), this);    cutAction->setIcon(QIcon("images/cut.png"));    cutAction->setShortcut(QKeySequence::Cut);    cutAction->setStatusTip(tr("Cut the current selection's contents to the clipboard"));    connect(cutAction, SIGNAL(triggered()), spreadsheet, SLOT(cut()));//创建Edit->CopycopyAction = new QAction(tr("&Copy"), this);    copyAction->setIcon(QIcon("images/copy.png"));    copyAction->setShortcut(QKeySequence::Copy);    copyAction->setStatusTip(tr("Copy the current selection's contents to the clipboard"));    connect(copyAction, SIGNAL(triggered()), spreadsheet, SLOT(copy()));//创建Edit->PastepasteAction = new QAction(tr("&Paste"), this);    pasteAction->setIcon(QIcon("images/paste.png"));    pasteAction->setShortcut(QKeySequence::Paste);    pasteAction->setStatusTip(tr("Paste the clipboard's contents into the current selection"));    connect(pasteAction, SIGNAL(triggered()), spreadsheet, SLOT(paste()));//创建Edit->Delete    deleteAction = new QAction(tr("&Delete"), this);    deleteAction->setShortcut(QKeySequence::Delete);    deleteAction->setStatusTip(tr("Delete the current selection's contents"));    connect(deleteAction, SIGNAL(triggered()), spreadsheet, SLOT(del()));//创建Edit->Select->Row    selectRowAction = new QAction(tr("&Row"), this);    selectRowAction->setStatusTip(tr("Select all the cells in the current row"));    connect(selectRowAction, SIGNAL(triggered()), spreadsheet, SLOT(selectCurrentRow()));//创建Edit->Select->Column    selectColumnAction = new QAction(tr("&Column"), this);    selectColumnAction->setStatusTip(tr("Select all the cells in the current column"));    connect(selectColumnAction, SIGNAL(triggered()), spreadsheet, SLOT(selectCurrentColumn()));//创建Edit->Select->All    selectAllAction = new QAction(tr("&All"), this);    selectAllAction->setShortcut(QKeySequence::SelectAll);    selectAllAction->setStatusTip(tr("Select all the cells in the spreadsheet"));    connect(selectAllAction, SIGNAL(triggered()), spreadsheet, SLOT(selectAll()));//创建Edit->FindfindAction = new QAction(tr("&Find..."), this);    findAction->setIcon(QIcon("images/find.png"));    findAction->setShortcut(QKeySequence::Find);    findAction->setStatusTip(tr("Find a matching cell"));    connect(findAction, SIGNAL(triggered()), this, SLOT(find()));//创建Edit->Go To Cell    goToCellAction = new QAction(tr("&Go to Cell..."), this);    goToCellAction->setIcon(QIcon("images/gotocell.png"));    goToCellAction->setShortcut(tr("Ctrl+G"));    goToCellAction->setStatusTip(tr("Go to the specified cell"));    connect(goToCellAction, SIGNAL(triggered()), this, SLOT(goToCell()));//创建Tools->Recalculate    recalculateAction = new QAction(tr("&Recalculate"), this);    recalculateAction->setShortcut(tr("F9"));    recalculateAction->setStatusTip(tr("Recalculate all the spreadsheet's formulas"));    connect(recalculateAction, SIGNAL(triggered()), spreadsheet, SLOT(recalculate()));//创建Tools->Sort    sortAction = new QAction(tr("&Sort..."), this);    sortAction->setStatusTip(tr("Sort the selected cells or all the cells"));    connect(sortAction, SIGNAL(triggered()), this, SLOT(sort()));//创建Options->Show Grid    showGridAction = new QAction(tr("&Show Grid"), this);    showGridAction->setCheckable(true);    showGridAction->setChecked(spreadsheet->showGrid());    showGridAction->setStatusTip(tr("Show or hide the spreadsheet's grid"));    connect(showGridAction, SIGNAL(toggled(bool)), spreadsheet, SLOT(setShowGrid(bool)));#if QT_VERSION < 0x040102    // workaround for a QTableWidget bug in Qt 4.1.1    connect(showGridAction, SIGNAL(toggled(bool)),            spreadsheet->viewport(), SLOT(update()));#endif//创建Options->Auto-RecalculateautoRecalcAction = new QAction(tr("&Auto-Recalculate"), this);    autoRecalcAction->setCheckable(true);    autoRecalcAction->setChecked(spreadsheet->autoRecalculate());    autoRecalcAction->setStatusTip(tr("Switch auto-recalculation on or off"));    connect(autoRecalcAction, SIGNAL(toggled(bool)), spreadsheet, SLOT(setAutoRecalculate(bool)));//创建Help->AboutaboutAction = new QAction(tr("&About"), this);    aboutAction->setStatusTip(tr("Show the application's About box"));    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));//创建Help->About QtaboutQtAction = new QAction(tr("About &Qt"), this);    aboutQtAction->setStatusTip(tr("Show the Qt library's About box"));    connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));}

就是为了创建菜单
*创建并设置动作; 

    newAction = new QAction(tr("&New"), this);    newAction->setIcon(QIcon(":/images/new.png"));    newAction->setShortcut(QKeySequence::New);    newAction->setStatusTip(tr("Create a new spreadsheet file"));    connect(newAction, SIGNAL(triggered()), this, SLOT(newFile()));

*创建菜单并添加动作到菜单;

    editMenu = menuBar()->addMenu(tr("&Edit"));    editMenu->addAction(cutAction);    editMenu->addAction(copyAction);    editMenu->addAction(pasteAction);    editMenu->addAction(deleteAction);

*创建工具栏并添加动作到工具栏。

    fileToolBar = addToolBar(tr("&File"));    fileToolBar->addAction(newAction);    fileToolBar->addAction(openAction);    fileToolBar->addAction(saveAction);



3)创建一级菜单

void MainWindow::createMenus(){//创建一级菜单    fileMenu = menuBar()->addMenu(tr("&File"));    fileMenu->addAction(newAction);    fileMenu->addAction(openAction);    fileMenu->addAction(saveAction);    fileMenu->addAction(saveAsAction);    separatorAction = fileMenu->addSeparator();    for (int i = 0; i < MaxRecentFiles; ++i)        fileMenu->addAction(recentFileActions[i]);    fileMenu->addSeparator();    fileMenu->addAction(exitAction);    editMenu = menuBar()->addMenu(tr("&Edit"));    editMenu->addAction(cutAction);    editMenu->addAction(copyAction);    editMenu->addAction(pasteAction);    editMenu->addAction(deleteAction);    selectSubMenu = editMenu->addMenu(tr("&Select"));    selectSubMenu->addAction(selectRowAction);    selectSubMenu->addAction(selectColumnAction);    selectSubMenu->addAction(selectAllAction);    editMenu->addSeparator();    editMenu->addAction(findAction);    editMenu->addAction(goToCellAction);    toolsMenu = menuBar()->addMenu(tr("&Tools"));    toolsMenu->addAction(recalculateAction);    toolsMenu->addAction(sortAction);    optionsMenu = menuBar()->addMenu(tr("&Options"));    optionsMenu->addAction(showGridAction);    optionsMenu->addAction(autoRecalcAction);    menuBar()->addSeparator();    helpMenu = menuBar()->addMenu(tr("&Help"));    helpMenu->addAction(aboutAction);    helpMenu->addAction(aboutQtAction);}


4)

void MainWindow::createToolBars(){//创建工具按钮    fileToolBar = addToolBar(tr("&File"));    fileToolBar->addAction(newAction);    fileToolBar->addAction(openAction);    fileToolBar->addAction(saveAction);    editToolBar = addToolBar(tr("&Edit"));    editToolBar->addAction(cutAction);    editToolBar->addAction(copyAction);    editToolBar->addAction(pasteAction);    editToolBar->addSeparator();    editToolBar->addAction(findAction);    editToolBar->addAction(goToCellAction);}


5)

void MainWindow::createStatusBar(){//设置状态栏locationLabel = new QLabel(" W999 ");locationLabel->setAlignment(Qt::AlignHCenter);locationLabel->setMinimumSize(locationLabel->sizeHint());formulaLabel = new QLabel;formulaLabel->setIndent(3);statusBar()->addWidget(locationLabel);statusBar()->addWidget(formulaLabel, 1);connect(spreadsheet, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(updateStatusBar()));connect(spreadsheet, SIGNAL(modified()), this, SLOT(spreadsheetModified()));updateStatusBar();}


void MainWindow::updateStatusBar(){//更新单元格指示器,因为SpreadSheet不会一开始就发射改变的消息所以需要spreadsheetModified()    locationLabel->setText(spreadsheet->currentLocation());    formulaLabel->setText(spreadsheet->currentFormula());}void MainWindow::spreadsheetModified(){    setWindowModified(true);    updateStatusBar();}



6)菜单功能的实现

void MainWindow::newFile(){    if (okToContinue()) {        spreadsheet->clear();        setCurrentFile("");    }}void MainWindow::open(){    if (okToContinue()){        QString fileName = QFileDialog::getOpenFileName(this, tr("Open Spreadsheet"), ".", tr("Spreadsheet files (*.sp)"));        if (!fileName.isEmpty())            loadFile(fileName);    }}bool MainWindow::save(){    if (curFile.isEmpty()) {        return saveAs();    } else {        return saveFile(curFile);    }}bool MainWindow::saveAs(){    QString fileName = QFileDialog::getSaveFileName(this,  tr("Save Spreadsheet"), ".", tr("Spreadsheet files (*.sp)"));    if (fileName.isEmpty())        return false;    return saveFile(fileName);}void MainWindow::find(){    if (!findDialog) {        findDialog = new FindDialog(this);        connect(findDialog, SIGNAL(findNext(const QString &,                                            Qt::CaseSensitivity)),                spreadsheet, SLOT(findNext(const QString &,                                           Qt::CaseSensitivity)));        connect(findDialog, SIGNAL(findPrevious(const QString &,                                                Qt::CaseSensitivity)),                spreadsheet, SLOT(findPrevious(const QString &,                                               Qt::CaseSensitivity)));    }    findDialog->show();    findDialog->raise();    findDialog->activateWindow();}void MainWindow::goToCell(){    GoToCellDialog dialog(this);    if (dialog.exec()) {        QString str = dialog.lineEdit->text().toUpper();        spreadsheet->setCurrentCell(str.mid(1).toInt() - 1,                                    str[0].unicode() - 'A');    }}void MainWindow::sort(){    SortDialog dialog(this);    QTableWidgetSelectionRange range = spreadsheet->selectedRange();    dialog.setColumnRange('A' + range.leftColumn(),                          'A' + range.rightColumn());    if (dialog.exec()) {        SpreadsheetCompare compare;        compare.keys[0] =              dialog.primaryColumnCombo->currentIndex();        compare.keys[1] =              dialog.secondaryColumnCombo->currentIndex() - 1;        compare.keys[2] =              dialog.tertiaryColumnCombo->currentIndex() - 1;        compare.ascending[0] =              (dialog.primaryOrderCombo->currentIndex() == 0);        compare.ascending[1] =              (dialog.secondaryOrderCombo->currentIndex() == 0);        compare.ascending[2] =              (dialog.tertiaryOrderCombo->currentIndex() == 0);        spreadsheet->sort(compare);    }}void MainWindow::about(){    QMessageBox::about(this, tr("About Spreadsheet"),            tr("<h2>Spreadsheet 1.1</h2>"               "<p>Copyright &copy; 2008 Software Inc."               "<p>Spreadsheet is a small application that "               "demonstrates QAction, QMainWindow, QMenuBar, "               "QStatusBar, QTableWidget, QToolBar, and many other "               "Qt classes."));}void MainWindow::openRecentFile(){    if (okToContinue()) {        QAction *action = qobject_cast<QAction *>(sender());        if (action)            loadFile(action->data().toString());//打开选中的最近的文件    }}


7)

void MainWindow::createContextMenu(){    spreadsheet->addAction(cutAction);    spreadsheet->addAction(copyAction);    spreadsheet->addAction(pasteAction);    spreadsheet->setContextMenuPolicy(Qt::ActionsContextMenu);}void MainWindow::readSettings(){    QSettings settings("Software Inc.", "Spreadsheet");    restoreGeometry(settings.value("geometry").toByteArray());    recentFiles = settings.value("recentFiles").toStringList();    updateRecentFileActions();    bool showGrid = settings.value("showGrid", true).toBool();    showGridAction->setChecked(showGrid);    bool autoRecalc = settings.value("autoRecalc", true).toBool();    autoRecalcAction->setChecked(autoRecalc);}void MainWindow::writeSettings(){    QSettings settings("Software Inc.", "Spreadsheet");    settings.setValue("geometry", saveGeometry());    settings.setValue("recentFiles", recentFiles);    settings.setValue("showGrid", showGridAction->isChecked());    settings.setValue("autoRecalc", autoRecalcAction->isChecked());}bool MainWindow::okToContinue(){//是否修改过、是否允许保存等判定    if (isWindowModified()) {        int r = QMessageBox::warning(this, tr("Spreadsheet"),                        tr("The document has been modified.\n"                           "Do you want to save your changes?"),                        QMessageBox::Yes | QMessageBox::No                        | QMessageBox::Cancel);        if (r == QMessageBox::Yes) {            return save();        } else if (r == QMessageBox::Cancel) {            return false;        }    }    return true;}bool MainWindow::loadFile(const QString &fileName){    if (!spreadsheet->readFile(fileName)) {        statusBar()->showMessage(tr("Loading canceled"), 2000);        return false;    }    setCurrentFile(fileName);    statusBar()->showMessage(tr("File loaded"), 2000);    return true;}bool MainWindow::saveFile(const QString &fileName){    if (!spreadsheet->writeFile(fileName)) {        statusBar()->showMessage(tr("Saving canceled"), 2000);        return false;    }    setCurrentFile(fileName);    statusBar()->showMessage(tr("File saved"), 2000);    return true;}void MainWindow::setCurrentFile(const QString &fileName){    curFile = fileName;    setWindowModified(false);    QString shownName = tr("Untitled");    if (!curFile.isEmpty()) {        shownName = strippedName(curFile);        recentFiles.removeAll(curFile);        recentFiles.prepend(curFile);        updateRecentFileActions();    }    setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("Spreadsheet")));}void MainWindow::updateRecentFileActions(){    QMutableStringListIterator i(recentFiles);    while (i.hasNext()) {        if (!QFile::exists(i.next()))            i.remove();    }    for (int j = 0; j < MaxRecentFiles; ++j) {        if (j < recentFiles.count()) {            QString text = tr("&%1 %2")                           .arg(j + 1)                           .arg(strippedName(recentFiles[j]));            recentFileActions[j]->setText(text);            recentFileActions[j]->setData(recentFiles[j]);            recentFileActions[j]->setVisible(true);        } else {            recentFileActions[j]->setVisible(false);        }    }    separatorAction->setVisible(!recentFiles.isEmpty());}QString MainWindow::strippedName(const QString &fullFileName){    return QFileInfo(fullFileName).fileName();}
void MainWindow::closeEvent(QCloseEvent *event){    if (okToContinue()) {        writeSettings();        event->accept();    } else {        event->ignore();    }}


8)程序启动界面

就好像PS打开时会有一个图片显示几秒加载一些东西的时候

main.cpp

#include <QApplication>#include <QSplashScreen>#include <QDateTime>#include "mainwindow.h"int main(int argc, char *argv[]){    QApplication app(argc, argv);QSplashScreen *splash = new QSplashScreen;splash->setPixmap(QPixmap("images/qtStart.png"));splash->show();/*使程序在显示启动画面的同时仍能响应鼠标等其他事件*/app.processEvents();Qt::Alignment topRight = Qt::AlignRight | Qt::AlignLeft;splash->showMessage(QObject::tr("正在启动程序..."), topRight, Qt::white);    MainWindow mainWin;splash->showMessage(QObject::tr("发现二次元,正在扫描..."), topRight, Qt::white);//loadModules();splash->showMessage(QObject::tr("最后一步..."), topRight, Qt::white);//establishConnections();QDateTime n = QDateTime::currentDateTime();QDateTime now;do {now = QDateTime::currentDateTime();app.processEvents();} while (n.secsTo(now) <= 2);//5为需要延时的秒数mainWin.show();splash->finish(&mainWin);delete splash;    return app.exec();}


本文还未完,在实现表格后台功能后才行,在下一章继续..