背景:
昨天一天都在编写QT文本编辑器程序,编写的过程中发现了很多问题,但是在编写的时候都比较难以实现,在网上搜索的消息也比较零散。这里总结一下QT文本编辑器的思路以及一些编写过程。
思路:
文本编辑器编写思路:
文本编辑器首先是基于一个QMainWindow的框架,个框架的主题结构是
菜单栏(Menu Bar)、工具栏(Toolbars)、停靠窗口(Dock Widgets)、状态栏(Status Bar)和中央窗口(Central Widget)
这五个窗口共同组成窗口,其中停靠窗口不能算是QMianWindow里面的窗口,但是剩下的四个窗口都是一些主窗口的组成部分,在主窗口中直接加入就可以了。
对于一个QT程序的思路:
首先要找到他们的构成部件,这里就是这些窗口的部件以及组成他们的一些控件。可以把这些组成部分写进private成员函数里面。对于一些不常用的空间就可以直接在写cpp文件的时候new出来就可以了,不用在private成员里面写指针。
另外一个就是要写好他们的槽函数,对于一个按钮,又或者是动作的实现(跟按钮差不多),都应该要写一个对应的槽函数。或者事件机制,就可以直接有一个对应的事件类来激发他。这里槽函数可以先列出来,然后再到我们的cpp文件里面去实现他。
最后就是对应的别的界面的实现,在除了主要界面的实现,还要写一些对应链接的实现或者是其他窗口的实现。
界面实现效果:
废话不多说!(注意:图片的路径记得改一下哦~)
上代码:
aboutwidget.h(插入界面):
#ifndef ABOUTWIDGET_H
#define ABOUTWIDGET_H
#include <QWidget>
#include <QLabel>
namespace Ui {
class AboutWidget;
}
class AboutWidget : public QWidget
{
Q_OBJECT
public:
explicit AboutWidget(QWidget *parent = nullptr);
void resizeEvent(QResizeEvent *event);
~AboutWidget();
private:
QLabel *a;
QPixmap *Pixmap;
Ui::AboutWidget *ui;
};
#endif // ABOUTWIDGET_H
aboutwidget.cpp(插入界面):
#include "aboutwidget.h"
#include "ui_aboutwidget.h"
#include <QPixmap>
#include <QLabel>
#include <QResizeEvent>
AboutWidget::AboutWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::AboutWidget)
{
ui->setupUi(this);
setWindowTitle("about you!");
a=new QLabel(this);
a->setPixmap(QPixmap("./release/imageformats/12.jpg"));
a->setScaledContents(true);
}
void AboutWidget::resizeEvent(QResizeEvent *event)
{
this->resize(500,850);
a->resize(this->size());
}
AboutWidget::~AboutWidget()
{
delete ui;
}
mainwindow.h(主界面):
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QDockWidget>
#include <QListWidget>
#include <QTextEdit>
#include <QFileDialog>
#include <QFontDialog>
#include <QColorDialog>//这些对话框可以实现较为基础的选择选项
#include <QFile>
#include <QTextCodec>
#include <QMessageBox>
#include <QTextStream>
#include <QDesktopServices>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
QString saveCurrentData(QString path);
void setCurrentFileName(const QString &fileName);
QString showFileDialog(QFileDialog::AcceptMode mode);
MainWindow(QWidget *parent = nullptr);
// 设置光标的选区,使格式作用于选区内的字符
void mergeFormat(QTextCharFormat fmt);
~MainWindow();
private:
QString m_fileName;
QTextEdit *textEdit;
QListWidget *textList;//铆接部分文本区域
QMenuBar *menuBar;//菜单栏
QToolBar *toolBar;//工具栏
Ui::MainWindow *ui;
QFont font;
QColor color;
public slots:
void on_actionexit_triggered();//退出操作
void on_actionopenfile_triggered();//打开文件操作
void on_ServeFile_triggered();//保存文件操作
void on_actionne_triggered();//创建新文件操作
void on_actionundo_triggered();//撤回操作
void on_actionredo_triggered();//恢复文件
void on_actioncut_triggered();//剪切文件
void on_actioncopy_triggered();//复制文件
void on_actionpatse_triggered();//粘贴文件
void on_actionTextUnderLine_triggered();
void on_actionTextItalic_triggered();
void on_actionTextBold_triggered();
//对齐
void on_actionLift_triggered();
void on_actionCenter_triggered();
void on_actionRight_triggered();
void on_actioncolor_triggered();//颜色操作
void on_actionfont_triggered();
void on_kidding();
void on_about();
};
#endif // MAINWINDOW_H
mainwindow.cpp(主界面):
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "aboutwidget.h"
#include <QToolBar>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
/**************************************************菜单栏**********************************/
this->setWindowTitle("myWindow");//设置窗口标题
this->resize(1100,700);//重设窗口大小
//创建菜单栏
menuBar = new QMenuBar(this);
//添加菜单栏到主窗口中
this->setMenuBar(menuBar);
QMenu *menu1 = new QMenu("文件",this);
QMenu *menu2 = new QMenu("编辑",this);
QMenu *menu3 = new QMenu("样式",this);
QMenu *menu7 = new QMenu("这个键你点不了",this);
QMenu *menu8 = new QMenu("帮助",this);
//添加多个菜单到菜单栏
menuBar->addMenu(menu1);
menuBar->addMenu(menu2);
menuBar->addMenu(menu3);
menuBar->addMenu(menu7);
menuBar->addMenu(menu8);
QAction *action1 = new QAction(QIcon("./release/imageformats/1.png"),"新建文件或项目",this);//有图标
QAction *action2 = new QAction(QIcon("./release/imageformats/2.png"),"打开文件或项目",this);//有图标
QAction *action3 = new QAction("退出",this);
QAction *action15 = new QAction("复制",this);//复制动作
QAction *action16 = new QAction("粘贴",this);//粘贴动作
QAction *action17 = new QAction("撤销",this);//撤销动作
QAction *action18 = new QAction("恢复",this);//恢复动作
QAction *action19 =new QAction("字体",this);//字体
QAction *action20 =new QAction("颜色",this);//颜色
QAction *action21 =new QAction("about",this);//帮助
QAction *action22 =new QAction("about you!",this);//搞怪
menu1->addAction(action1);
menu1->addAction(action2);//菜单添加标签
menu1->addSeparator();//插入分割线
QMenu *menu9 = new QMenu("最近访问的文件",this);
menu1->addMenu(menu9);//添加二级菜单
menu2->addAction(action15);
menu2->addAction(action16);
menu2->addAction(action17);
menu2->addAction(action18);
menu3->addAction(action19);
menu3->addAction(action20);
menu9->addAction(new QAction("暂无最近打开项目",this));//二级菜单添加菜单项
menu1->addAction(action3);
menu7->addAction(action22);
menu8->addAction(action21);
action1->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));//快捷键ctrl+N
action2->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_O));//快捷键ctrl+O
connect(action1, SIGNAL(triggered(bool)), this, SLOT(on_actionne_triggered()));//创建文件连接信号槽
connect(action2, SIGNAL(triggered(bool)), this, SLOT(on_actionopenfile_triggered()));//打开文件连接信号槽
connect(action3, SIGNAL(triggered(bool)), this, SLOT(on_actionexit_triggered()));
connect(action19, SIGNAL(triggered(bool)), this, SLOT(on_actionfont_triggered()));
connect(action20, SIGNAL(triggered(bool)), this, SLOT(on_actioncolor_triggered()));
connect(action21, SIGNAL(triggered(bool)), this, SLOT(on_about()));
connect(action22, SIGNAL(triggered(bool)), this, SLOT(on_kidding()));
/************************************工具栏********************************************/
//创建工具栏
toolBar = new QToolBar(this);
//主窗口添加工具栏
this->addToolBar(Qt::TopToolBarArea,toolBar);//设置工具栏默认停靠在左边
toolBar->setFloatable(false);//设置不允许浮动
toolBar->setMovable(false);//设置不允许移动
toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);//设置工具项为图片在文字上方
QString str[20]={tr("./release/imageformats/1.png"),tr("./release/imageformats/2.png"),tr("./release/imageformats/3.png"),
tr("./release/imageformats/11.png"),tr("./release/imageformats/4.png"),tr("./release/imageformats/5.png"),
tr("./release/imageformats/6.png"),tr("./release/imageformats/7.png"),tr("./release/imageformats/8.png"),
tr("./release/imageformats/9.png"),tr("./release/imageformats/10.png")};
//创建工具项
QAction *action4 = new QAction(QIcon(str[0]),"文件",this);
QAction *action5 = new QAction(QIcon(str[1]),"保存",this);
QAction *action6 = new QAction(QIcon(str[2]),"撤回",this);
QAction *action7 = new QAction(QIcon(str[3]),"恢复",this);
QAction *action8 = new QAction(QIcon(str[4]),"剪切",this);
QAction *action9 = new QAction(QIcon(str[5]),"粗体",this);
QAction *action10 = new QAction(QIcon(str[6]),"斜体",this);
QAction *action11 = new QAction(QIcon(str[7]),"下划线",this);
QAction *action12 = new QAction(QIcon(str[8]),"左对齐",this);
QAction *action13 = new QAction(QIcon(str[9]),"中对齐",this);
QAction *action14 = new QAction(QIcon(str[10]),"右对齐",this);
action15->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C));//快捷键ctrl+C
action16->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_V));//快捷键ctrl+V
// action6->setEnabled(false);//设置不能使用
//工具栏添加工具项
toolBar->addAction(action4);
toolBar->addSeparator();//添加分割线
toolBar->addAction(action5);
toolBar->addSeparator();//添加分割线
toolBar->addAction(action6);
toolBar->addSeparator();//添加分割线
toolBar->addAction(action7);
toolBar->addSeparator();//添加分割线
toolBar->addAction(action8);
action8->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_X));//快捷键ctrl+X
toolBar->addSeparator();//添加分割线
toolBar->addAction(action9);
toolBar->addSeparator();//添加分割线
toolBar->addAction(action10);
toolBar->addSeparator();//添加分割线
toolBar->addAction(action11);
toolBar->addSeparator();//添加分割线
toolBar->addAction(action12);
toolBar->addSeparator();//添加分割线
toolBar->addAction(action13);
toolBar->addSeparator();//添加分割线
toolBar->addAction(action14);
toolBar->addSeparator();//添加分割线
/*********************************************************状态栏*****************************/
//创建状态栏
QStatusBar *status = new QStatusBar(this);
status->setObjectName("状态栏");
status->setStyleSheet("QStatusBar::item{border: 0px}"); //设置不显示label的边框
//主窗口添加状态栏
this->setStatusBar(status);
//创建标签
QLabel *statusLabel = new QLabel("我是状态栏", this);
//状态栏添加信息
status->showMessage("欢迎使用文本编辑器", 3000);//显示在左侧,并且3秒后自动消失
status->addPermanentWidget(statusLabel);//添加右侧标签(永久性)
/****************************创建铆接部分**********************************/
//创建铆接部件
QDockWidget *dockWidget = new QDockWidget(this);
dockWidget->setFeatures(QDockWidget::NoDockWidgetFeatures);//设置铆接部件不可移动、不可关闭、不可浮动
dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);//设置允许左右停靠
QLabel *titleLabel = new QLabel("行数");
titleLabel->setAlignment(Qt::AlignCenter);//设置中心对齐
dockWidget->setTitleBarWidget(titleLabel);//设置标题栏
//主窗口添加铆接部件
this->addDockWidget(Qt::LeftDockWidgetArea,dockWidget);//设置铆接部件停靠在左侧(浮动窗口)
//创建ListWidget
QListWidget *textList = new QListWidget(this);
for(int i=1; i<=50; i++)
{
QListWidgetItem *item = new QListWidgetItem(QString("%1").arg(i));
textList->addItem(item);
item->setTextAlignment(Qt::AlignRight);
}
textList->setFixedWidth(30);
textList->setObjectName("文本列表");
//设置没有水平以及垂直滑动条
textList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
textList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
//铆接部件添加内容主体
dockWidget->setWidget(textList);
//从这里可以看出来铆接部分不是主窗口的一个必要部分
/**************************************主要部分***************************************/
//设置中心部件
//创建文本编辑框 显示文本
textEdit = new QTextEdit(this);
textEdit->setText("我是文本编辑框");
textEdit->setObjectName("文本编辑框");
connect(textEdit, SIGNAL(textChanged()), this, SLOT(createFile()));//连接信号槽
QFont font = QFont("宋体",18,QFont::Normal,true);
//主窗口设置文本编辑框为中心部件
this->setCentralWidget(textEdit);
//都大学生了为什么还有作业要做!
/*********************************槽函数与信号的链接*******************************/
connect(action4, SIGNAL(triggered(bool)), this, SLOT(on_actionopenfile_triggered()));
connect(action5, SIGNAL(triggered(bool)), this, SLOT(on_ServeFile_triggered()));
connect(action6, SIGNAL(triggered(bool)), this, SLOT(on_actionundo_triggered()));
connect(action7, SIGNAL(triggered(bool)), this, SLOT(on_actionredo_triggered()));
connect(action17, SIGNAL(triggered(bool)), this, SLOT(on_actionundo_triggered()));
connect(action18, SIGNAL(triggered(bool)), this, SLOT(on_actionredo_triggered()));
connect(action8, SIGNAL(triggered(bool)), this, SLOT(on_actioncut_triggered()));
connect(action15, SIGNAL(triggered(bool)), this, SLOT(on_actioncopy_triggered()));
connect(action16, SIGNAL(triggered(bool)), this, SLOT(on_actionpatse_triggered()));
connect(action9, SIGNAL(triggered(bool)), this, SLOT(on_actionTextBold_triggered()));
connect(action10, SIGNAL(triggered(bool)), this, SLOT(on_actionTextItalic_triggered()));
connect(action11, SIGNAL(triggered(bool)), this, SLOT(on_actionTextUnderLine_triggered()));
connect(action12, SIGNAL(triggered(bool)), this, SLOT(on_actionLift_triggered()));
connect(action13, SIGNAL(triggered(bool)), this, SLOT(on_actionCenter_triggered()));
connect(action14, SIGNAL(triggered(bool)), this, SLOT(on_actionRight_triggered()));
}
MainWindow::~MainWindow()
{
delete ui;
}
/****************************************槽函数的实现*******************************/
//关闭主窗口
void MainWindow::on_actionexit_triggered()
{
close();
}
//字体改变
QString MainWindow::showFileDialog(QFileDialog::AcceptMode mode)
{
//这个函数可以实现对于文件的打开以及保存
QString ret = "";
QFileDialog fd(this);
QStringList filters;
filters.append("Text Files (*.txt)");
filters.append("All Files (*)");
fd.setWindowTitle("文件");//对话框标题
fd.setAcceptMode(mode);
// fd.setFilter();
if( mode == QFileDialog::AcceptOpen )//是打开文件还是保存文件
{
fd.setFileMode(QFileDialog::ExistingFile);//设置可选单个已存在的文件
}
if( fd.exec() == QFileDialog::Accepted )
{
ret = fd.selectedFiles()[0];//函数返回装有选中的文件的绝对路径的链表
}
return ret;
}
/*******************对文件进行操作*********************/
//打开文件!!
void MainWindow::setCurrentFileName(const QString &fileName)
{
m_fileName = fileName;
textEdit->document()->setModified(false);
QString shownName;
if (fileName.isEmpty())
shownName = "untitled.txt";
else
shownName = QFileInfo(fileName).fileName();
setWindowModified(false);
}
void MainWindow ::on_actionopenfile_triggered()
{
QString path = showFileDialog(QFileDialog::AcceptOpen);
setCurrentFileName(path);
if( path != "" )
{
QFile file(path);
if( file.open(QIODevice::ReadOnly | QIODevice::Text) )
{
textEdit->setPlainText(QString(file.readAll()));//读取文件的所有数据并导入到编辑组件
file.close();
setWindowTitle("NotePad - [ " + path + " ]");
}
else
{
//showErrorMessage(QString("Open file error! \n\n") + "\"" + path + "\"");//自定义的一个错误提示对话框
}
}
}
//创建文件
void MainWindow::on_actionne_triggered()
{
QMessageBox::StandardButton ok=QMessageBox::warning(this,tr("Warning"),
tr("创建新文件?"),
QMessageBox::Yes | QMessageBox::Default,
QMessageBox::No);//通过QMessagebox里面的东西来
m_fileName.clear();
textEdit->setText(QString());
if( m_fileName == ""&& ok==QMessageBox::StandardButton::Yes)
m_fileName = showFileDialog(QFileDialog::AcceptSave);
}
//保存文件
QString MainWindow::saveCurrentData(QString path)
{
QString ret = path;
if( ret == "" )
ret = showFileDialog(QFileDialog::AcceptSave);
if( ret != "" )
{
QFile file(ret);
if( file.open(QIODevice::WriteOnly | QIODevice::Text) )
{
QTextStream out(&file);
out << textEdit->toPlainText();
file.close();
setWindowTitle("NotePad - [ " + ret + " ]");
}
else
{
// showErrorMessage(QString("Save file error! \n\n") + "\"" + ret + "\"");
ret = "";
}
}
return ret;
}
void MainWindow::on_ServeFile_triggered()
{
QString path = saveCurrentData(m_fileName);
if( path != "" )
{
m_fileName = path;
}
}
/*******************对文件进行操作*********************/
/********************************撤销与恢复****************************/
void MainWindow::on_actionundo_triggered()
{
textEdit->undo();
}
void MainWindow::on_actionredo_triggered()
{
textEdit->redo();
}
/********************************撤销与恢复****************************/
/************剪切******************/
void MainWindow::on_actioncut_triggered()
{
textEdit->cut();
}
void MainWindow::on_actioncopy_triggered()
{
textEdit->copy();
}
void MainWindow::on_actionpatse_triggered()
{
textEdit->paste();
}
/************剪切******************/
/************粗体,斜体,下划线*************************/
// 设置光标的选区,使格式作用于选区内的字符
void MainWindow::mergeFormat(QTextCharFormat fmt)
{
QTextCursor cursor = textEdit->textCursor();
if (!cursor.hasSelection()) {
cursor.select(QTextCursor::WordUnderCursor);
}
cursor.mergeCharFormat(fmt);
}
//加粗
void MainWindow::on_actionTextBold_triggered()
{
bool boldcheck=true;
QTextCharFormat fmt;
fmt.setFontWeight(boldcheck ? QFont::Bold : QFont::Normal);
mergeFormat(fmt);
boldcheck = !boldcheck;
}
//倾斜
void MainWindow::on_actionTextItalic_triggered()
{
bool Italiccheck=true;
QTextCharFormat fmt;
fmt.setFontItalic(Italiccheck ? true : false);
mergeFormat(fmt);
Italiccheck = !Italiccheck;
}
//下划线
void MainWindow::on_actionTextUnderLine_triggered()
{
bool UnderLinecheck=true;
QTextCharFormat fmt;
fmt.setFontUnderline(UnderLinecheck ? true : false);
mergeFormat(fmt);
UnderLinecheck = !UnderLinecheck;
}
/************粗体,斜体,下划线*************************/
/*******************对齐********************/
//左对齐
void MainWindow::on_actionLift_triggered()
{
textEdit->setAlignment(Qt::AlignLeft);
}
//居中对齐
void MainWindow::on_actionCenter_triggered()
{
textEdit->setAlignment(Qt::AlignCenter);
}
//右对齐
void MainWindow::on_actionRight_triggered()
{
textEdit->setAlignment(Qt::AlignRight);
}
/*******************对齐********************/
/********************颜色,字体******************************/
void MainWindow::on_actioncolor_triggered()
{
QColor c = QColorDialog::getColor(color,this,"颜色选择框");
if(c.isValid()){
color = c;
// 设置文本框的文本颜色
// 1. 从光标开始新输入的文本颜色被设置
// 2. 鼠标选中的文本颜色设置
textEdit->setTextColor(c);
}
}
void MainWindow::on_actionfont_triggered()
{
bool ok; // 用户字体对话框保存是否选择了字体的结构
// 第一个参数是判断用户是否选择了字体,第二个是字体对话框的初始值
QFont f = QFontDialog::getFont(&ok,font,this,"选择文本框要设置的字体");//基础的用户字体对话框
if(ok){
font = f;
// 1. 从当前光标开始
// 2. 鼠标选中的文本的字体
textEdit->setCurrentFont(f);
}
}
/********************颜色,字体******************************/
/*************kidding,about*******************************/
void MainWindow::on_kidding()
{
static AboutWidget about;
about.show();
}
void MainWindow::on_about()
{
QDesktopServices::openUrl(QUrl(QLatin1String("https://www.qt.io/zh-cn/")));
}
/*************kidding,about*******************************/
main.cpp(主函数):
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
最后:
帅哥美女们,你们嫌麻烦吗,不嫌的话。
就麻烦给UU个赞吧!