添加主窗口菜单
新建Qt Gui应用,项目名称为myMainWindow,基类选择为QMainWindow,类名为MainWindow
进入ui设计模式,双击“在这里输入”,将其更改为“文件(&F)”,然后按下回车键,&F表明将菜单的快捷键设置为了Alt+ F
在文件菜单中添加“新建(&N)”子菜单
当一个菜单没有子菜单时,就被看作是一个Action,在Action编辑器中可以查看所有Action
双击Action编辑器中的新建Action,点击一下快捷键后面的行编辑器,然后按下键盘上的Ctrl + N,这样就可以将该Action的快捷键设置为Ctrl + N(“新建(N)”中的N可以被称为加速键,就是只有当文件菜单处于激活(显示)状态时,按下N键才会执行新建菜单的功能)
可以将动作编辑器中的动作拖动到工具栏中作为快捷图标使用,还可以在工具栏上点击鼠标右键来添加分隔符
添加资源文件
Qt中可以使用资源文件将各种类型的文件添加到最终生成的可执行文件中,这样就可以避免使用外部文件可能出现的一些问题。而且,在编译时Qt还会将资源文件进行压缩,我们可能发现生成的可执行文件比我们添加到其中的资源文件还要小
向项目中添加新文件,选择Qt资源文件,名称设置为myResources
创建完后会自动打开该资源文件,这里需要先在下面添加前缀。点击添加按钮,然后选择前缀,默认的前缀是“/new/prefix1”,这个可以随意修改(不要出现中文字符),我们修改为/myImages,然后再按下添加按钮来添加文件。这里最好将所有要用到的图片放到项目目录中,在项目目录中新建了一个images文件夹,然后将需要的图片文件粘贴进去
添加完资源后,一定要按下Ctrl + S来保存资源文件,不然在后面可能无法显示已经添加的资源
返回设计模式,双击新建Action,添加图标。在打开的选择资源对话框中,第一次可能无法显示已经存在的资源,可以按下左上角的绿箭头来更新显示
用写字板打卡myResources.qrc,发现它其实就是一个XML文档:
<RCC>
<qresourceprefix="/myImages">
<file>images/filenew.png</file>
<file>images/fileopen.png</file>
<file>images/filesave.png</file>
<file>images/filesaveas.png</file>
<file>images/find.png</file>
</qresource>
</RCC>
mainwindow.cpp
// 创建新的动作
QAction *openAction = new QAction(tr("&打开"), this);
// 添加图标
QIcon icon(":/myImages/images/fileopen.png");
openAction->setIcon(icon);
// 设置快捷键
openAction->setShortcut(QKeySequence(tr("Ctrl+O")));
// 在文件菜单中设置新的打开动作
ui->menu_F->addAction(openAction);
使用资源文件,需要在最开始使用冒号,然后添加前缀,后面是文件的路径
在本机测试的时候,一直出现如下报错:
process_begin: CreateProcess(NULL, bin\rcc.exe -name myResources ..\myMainWindow\myResources.qrc -o debug\qrc_myResources.cpp, ...) failed.
make (e=2): 系统找不到指定的文件。
mingw32-make.exe[1]: *** [debug/qrc_myResources.cpp] Error 2
mingw32-make.exe: *** [debug] Error 2
17:59:13: 进程"C:\Qt\qtcreator-2.4.1\mingw\bin\mingw32-make.exe"退出,退出代码 2 。
找不到资源文件的位置,无法生成对应的cpp文件,暂时没有解决方案,先搁置,估计跟环境有关
布局管理器
拖入三个按钮到Vertical Layout(垂直布局管理器)上,发现无论怎么改变布局管理器的大小,按钮总是水平方向变化
选中垂直布局管理器,选择工具栏中的“打破布局”移除垂直布局
选中三个按钮,再选择工具栏中的“使用分裂器垂直布局”,可以发现,使用分裂器按钮纵向是可以变大的,这就是分裂器和布局管理器的重要区别
布局管理器还有个重要用途,就是使部件随着窗口的大小变化而变化,选中一个按钮,右击,选择布局→栅格布局,这时按钮部件就会填充中央区域。可以发现,无论怎样拉伸窗口,文本编辑器总是填充整个中央区域
demo:文本编辑器
目标
实现新建Windows记事本,保存,和另存为三个功能
实现打开、关闭、退出、撤销、复制、剪切、粘贴等功能
实现查找菜单的功能
添加状态栏(编辑器下方)提示
实现
当新建文件时,要考虑是否保存正在编辑的文件,如果需要保存,还要根据该文件以前是否保存过来进行保存或者另存为操作
打开时要考虑文件类型,正在编辑的文件的处理,关闭和退出也要考虑是否需要保存
撤销、复制、剪切、粘贴等功能相对简单,QTextEdit已经实现了,直接调用即可
查找用一个对话框实现,状态栏调用statusBar控件设置
main.cpp
#include "mainwindow.h"
#include <QtGui/QApplication>
#include <QTextCodec>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QCloseEvent>
#include <QMessageBox>
#include <QPushButton>
#include <QFileDialog>
#include <QTextStream>
#include <QLineEdit>
#include <QDialog>
#include <QLabel>
//class QLineEdit;
//class QDialog;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void newFile();
bool maybeSave();
bool save();
bool saveAs();
bool saveFile(const QString &fileName);
bool loadFile(const QString &fileName);
protected:
void closeEvent(QCloseEvent *event);
private slots:
void on_action_New_triggered();
void on_action_Save_triggered();
void on_action_SaveAs_triggered();
void on_action_Open_triggered();
void on_action_Close_triggered();
void on_action_Exit_triggered();
void on_action_Undo_triggered();
void on_action_Cut_triggered();
void on_action_Copy_triggered();
void on_action_Paste_triggered();
void showFindText();
void on_action_Find_triggered();
private:
Ui::MainWindow *ui;
// 为真表示文件没有保存过,为假表示文件已经被保存过了
bool isNotSaved;
// 保存当前文件的路径
QString curFile;
QLineEdit *findLineEdit;
QDialog *findDlg;
QLabel *statusLabel;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
isNotSaved = true;
curFile = tr("未命名.txt");
setWindowTitle(curFile);
findDlg = new QDialog(this);
findDlg->setWindowTitle(tr("查找"));
findLineEdit = new QLineEdit(findDlg);
QPushButton *btn = new QPushButton(tr("查找下一个"), findDlg);
QVBoxLayout *layout = new QVBoxLayout(findDlg);
layout->addWidget(findLineEdit);
layout->addWidget(btn);
connect(btn, SIGNAL(clicked()), this, SLOT(showFindText()));
//ui->statusBar->showMessage(tr("欢迎访问gaoyifei.blog.csdn.net!"), 2000);
statusLabel = new QLabel;
statusLabel->setMinimumSize(150, 20);
statusLabel->setFrameShape(QFrame::WinPanel);
statusLabel->setFrameShadow(QFrame::Sunken);
ui->statusBar->addWidget(statusLabel);
statusLabel->setText(tr("欢迎访问gaoyifei.blog.csdn.net!"));
QLabel *permanent = new QLabel(this);
permanent->setFrameStyle(QFrame::Box | QFrame::Sunken);
permanent->setText(tr("<a href=\"http://gaoyifei.blog.csdn.net\">gaoyifei.blog.csdn.net</a>"));
permanent->setTextFormat(Qt::RichText);
permanent->setOpenExternalLinks(true);
ui->statusBar->addPermanentWidget(permanent);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::newFile()
{
if(maybeSave())
{
isNotSaved = true;
curFile = tr("未命名.txt");
setWindowTitle(curFile);
ui->textEdit->clear();
ui->textEdit->setVisible(true);
}
}
bool MainWindow::maybeSave()
{
if(ui->textEdit->document()->isModified())
{
QMessageBox box;
box.setWindowTitle(tr("警告"));
box.setIcon(QMessageBox::Warning);
box.setText(curFile + tr("尚未保存,是否保存?"));
QPushButton *yesBtn = box.addButton(tr("是(&Y)"),
QMessageBox::YesRole);
box.addButton(tr("否(&N)"), QMessageBox::NoRole);
QPushButton *cancelBtn = box.addButton(tr("取消"),
QMessageBox::RejectRole);
box.exec();
if(box.clickedButton() == yesBtn)
return save();
else if(box.clickedButton() == cancelBtn)
return false;
}
return true;
}
bool MainWindow::save()
{
if(isNotSaved)
{
return saveAs();
}
else
{
return saveFile(curFile);
}
}
bool MainWindow::saveAs()
{
QString fileName = QFileDialog::getSaveFileName(this, tr("另存为"), curFile);
if(fileName.isEmpty())
{
return false;
}
return saveFile(fileName);
}
bool MainWindow::saveFile(const QString &fileName)
{
QFile file(fileName);
if(!file.open(QFile::WriteOnly | QFile::Text))
{
QMessageBox::warning(this, tr("多文档编辑器"),
tr("无法写入文件 %1: /n %2")
.arg(fileName).arg(file.errorString()));
return false;
}
QTextStream out(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
out << ui->textEdit->toPlainText();
QApplication::restoreOverrideCursor();
isNotSaved = false;
curFile = QFileInfo(fileName).canonicalFilePath();
setWindowTitle(curFile);
return true;
}
bool MainWindow::loadFile(const QString &fileName)
{
QFile file(fileName);
if(!file.open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::warning(this, tr("多文档编辑器"),
tr("无法读取文件 %1:\n%2.")
.arg(fileName).arg(file.errorString()));
return false;
}
QTextStream in(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
ui->textEdit->setPlainText(in.readAll());
QApplication::restoreOverrideCursor();
curFile = QFileInfo(fileName).canonicalFilePath();
setWindowTitle(curFile);
return true;
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if(maybeSave())
{
event->accept();
}
else
{
event->ignore();
}
}
void MainWindow::on_action_New_triggered()
{
newFile();
}
void MainWindow::on_action_Save_triggered()
{
save();
}
void MainWindow::on_action_SaveAs_triggered()
{
saveAs();
}
void MainWindow::on_action_Open_triggered()
{
if(maybeSave())
{
QString fileName = QFileDialog::getOpenFileName(this);
if(!fileName.isEmpty())
{
loadFile(fileName);
ui->textEdit->setVisible(true);
}
}
}
void MainWindow::on_action_Close_triggered()
{
if(maybeSave())
{
ui->textEdit->setVisible(false);
}
}
void MainWindow::on_action_Exit_triggered()
{
on_action_Close_triggered();
qApp->quit();
}
void MainWindow::on_action_Undo_triggered()
{
ui->textEdit->undo();
}
void MainWindow::on_action_Cut_triggered()
{
ui->textEdit->cut();
}
void MainWindow::on_action_Copy_triggered()
{
ui->textEdit->copy();
}
void MainWindow::on_action_Paste_triggered()
{
ui->textEdit->paste();
}
void MainWindow::showFindText()
{
QString str = findLineEdit->text();
if(!ui->textEdit->find(str, QTextDocument::FindBackward))
{
QMessageBox::warning(this, tr("查找"),
tr("找不到%1").arg(str));
}
}
void MainWindow::on_action_Find_triggered()
{
findDlg->show();
}