1.类定义
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
protected:
void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;
private slots:
void newFile();
void open();
bool save();
bool saveAs();
void about();
void documentWasModified();
private:
void createActions();
void createMenus();
void createToolBars();
void createStatusBar();
void readSettings();
void writeSettings();
bool maybeSave();
void loadFile(const QString &fileName);
bool saveFile(const QString &fileName);
void setCurrentFile(const QString &fileName);
QString strippedName(const QString &fullFileName);
QPlainTextEdit *textEdit;
QString curFile;
QMenu *fileMenu;
QMenu *editMenu;
QMenu *helpMenu;
QToolBar *fileToolBar;
QToolBar *editToolBar;
QAction *newAct;
QAction *openAct;
QAction *saveAct;
QAction *saveAsAct;
QAction *exitAct;
QAction *cutAct;
QAction *copyAct;MainWindow::MainWindow()
{
textEdit = new QPlainTextEdit;
setCentralWidget(textEdit);
createActions();
createMenus();
createToolBars();
createStatusBar();
readSettings();
connect(textEdit->document(), SIGNAL(contentsChanged()),
this, SLOT(documentWasModified()));
setCurrentFile("");
setUnifiedTitleAndToolBarOnMac(true);
}
QWidget::closeEvent()用于监听用户关闭动作,提醒没有保存修改.
#include
#include "mainwindow.h"
QtWidgets里面包含Qt Core等类,为什么不把QtWidgets包含在mainwindow.h里呢?因为头文件太大了,会影响性能.
MainWindow::MainWindow()
{
textEdit = new QPlainTextEdit;
setCentralWidget(textEdit);
createActions();
createMenus();
createToolBars();
createStatusBar();
readSettings();
connect(textEdit->document(), SIGNAL(contentsChanged()),
this, SLOT(documentWasModified()));
setCurrentFile("");
setUnifiedTitleAndToolBarOnMac(true);
}
QMainWindow::setCentralWidget()用于告诉widget这个控件将占用windows中间区域在tool bars和status bars中间
void MainWindow::closeEvent(QCloseEvent *event)
{
if (maybeSave()) {
writeSettings();
event->accept();
} else {
event->ignore();
}
}
用户尝试关闭窗口的时候,maybesave询问用户是否存储变化.
void MainWindow::newFile()
{
if (maybeSave()) {
textEdit->clear();
setCurrentFile("");
}
}
清空当前的东西,询问是否存储.
void MainWindow::open()
{
if (maybeSave()) {
QString fileName = QFileDialog::getOpenFileName(this);
if (!fileName.isEmpty())
loadFile(fileName);
}
}
这些打开啊实际上就是要一个文件路径.
bool MainWindow::save()
{
if (curFile.isEmpty()) {
return saveAs();
} else {
return saveFile(curFile);
}
}
如果没提供名字,就saveAs()
bool MainWindow::saveAs()
{
QFileDialog dialog(this);
dialog.setWindowModality(Qt::WindowModal);
dialog.setAcceptMode(QFileDialog::AcceptSave);
QStringList files;
if (dialog.exec())
files = dialog.selectedFiles();
else
return false;
return saveFile(files.at(0));
}
Qt::WindowModal 阻塞自己的父辈.点确定得到一个文件路径,点取消返回空,什么都不做.
QMessageBox::about定义了一个静态显示关于的方便函数.使用tr()用于所有可见的地方,是个非常好的习惯,因为可以用工具翻译.
QAction就是一个下拉菜单里的项,是一个动作,可以放在QMenu和QToolBar里面,或者任意实现了QWidget::actionEvent()函数的Widget里面
可以显示为菜单,图标,快捷键,tip,状态栏等方式,点了之后发送Triggered()信号
cutAct->setEnabled(false);
copyAct->setEnabled(false);
connect(textEdit, SIGNAL(copyAvailable(bool)),
cutAct, SLOT(setEnabled(bool)));
connect(textEdit, SIGNAL(copyAvailable(bool)),
copyAct, SLOT(setEnabled(bool)));
创建了Action以后还有一个关键点是添加到Menu或者toolbar上面,用addAction方法就好了!
void MainWindow::readSettings()
{
QSettings settings("QtProject", "Application Example");
QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
QSize size = settings.value("size", QSize(400, 400)).toSize();
resize(size);
move(pos);
}
从QSetting里面读取独立的用户设置,然后用QWidget::resize()在QWidget::move()之前
bool MainWindow::maybeSave()
{
if (textEdit->document()->isModified()) {
QMessageBox::StandardButton ret;
ret = QMessageBox::warning(this, tr("Application"),
tr("The document has been modified.\n"
"Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
if (ret == QMessageBox::Save)
return save();
else if (ret == QMessageBox::Cancel)
return false;
}
return true;
}
如果文档被修改了,就弹出询问对话框,不然就直接返回false
void MainWindow::loadFile(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("Application"),
tr("Cannot read file %1:\n%2.")
.arg(fileName)
.arg(file.errorString()));
return;
}
QTextStream in(&file);
#ifndef QT_NO_CURSOR
QApplication::setOverrideCursor(Qt::WaitCursor);
#endif
textEdit->setPlainText(in.readAll());
#ifndef QT_NO_CURSOR
QApplication::restoreOverrideCursor();
#endif
setCurrentFile(fileName);
statusBar()->showMessage(tr("File loaded"), 2000);
}
对文件的操作都类似,先要通过名字得到文件描述符,然后在标准流来操作文件.
QTextStream 自动地转化8bit数据到Unicode QString,并且支持多种内码,默认支持 Latin-1
因为读取可能要花些时间,把光标弄成等待的形状.
void MainWindow::setCurrentFile(const QString &fileName)
{
curFile = fileName;
textEdit->document()->setModified(false);
setWindowModified(false);
QString shownName = curFile;
if (curFile.isEmpty())
shownName = "untitled.txt";
setWindowFilePath(shownName);
}
setModified用于设置标志,但这个标志是自动的吗?你编辑文本的时候,肯定有一个信号吧,那么槽的话估计也要修改这个标志的.