当前位置: 首页 > news >正文

C++ QT入门2——记事本功能实现与优化(事件处理+基本控件)

C++ QT入门2——记事本功能优化(事件处理+基本控件)

  • 一、记事本功能优化
    • 编码乱码问题
      • QComboBox下拉控件
      • QString、string、char * 间的数据转化
      • 编码问题解决整合
    • 光标行列值显示
    • 记事本打开窗口标题
    • 关闭按钮优化—弹窗提示
    • 快捷键设计
  • 二、☆ QT事件处理
    • 事件处理过程
    • 重写事件案例
    • 事件自定义按钮
    • 鼠标滚轮实现字体大小缩放
    • 事件过滤器
  • 三、当前行高亮的实现
    • C++模板回顾
    • QList容器介绍及使用
    • 当前行高亮设置
    • ExtraSelection简介
  • 四、记事本项目总结

  本次设计是基于 C++ QT入门1——记事本基础功能实现 的扩展与优化,因此需先参考上文进行基本功能的实现。

一、记事本功能优化

编码乱码问题

  程序设计默认为UTF-8的编码,打开其他编码格式会出现文字乱码的情况,如打开ANSI编码文件则会出现中文乱码的情况,因此需要程序根据文件类型自定义编码格式。

QComboBox下拉控件

1. 在ui文件为Combo Box添加索引项:

2. 绑定信号与槽
  每次对combo Box下拉控件的选项进行选择确实时会发出 currentIndexChanged (当前索引改变)信号,因此在构造函数内通connnect 将该信号与特定的槽函数进行绑定

//绑定信号与槽
connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(on_currentIndexChanged(int)));

记得在对应的.h文件进行声明槽函数

private slots:void on_currentIndexChanged(int);

3. 槽函数的实现
  通过自带的参数 indexcurrentText 方法获取点击的索引下标与内容

void MainWindow::on_currentIndexChanged(int index)
{qDebug() << "index: " << index;qDebug() << "coding: " << ui->comboBox->currentText();
}

实际效果如图下所示:

QString、string、char * 间的数据转化

string str;
QString qstr;
char * cstr;//从QString 到 std::string
str = qstr.toStdString();//从std::string 到QString
qstr = QString::fromStdString(str);//从std::string 到 cstr;
cstr = str.c_str();

编码问题解决整合

  通过以上Combo Box方式可以在保存的时候自定义编码方式,在读取文件的时候设置对应的编码方式
进行加载即可避免乱码问题。
定义成员变量-编码方式:

public:QString code_mode;

绑定信号与槽:

connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(on_currentIndexChanged(int)));

槽函数的实现
  方式1:可以只改变成员变量code_mode,并修改打开与关闭的编码模式,但这种方式代码简单,但只适合下次重新打开生效

void Widget::on_currentIndexChanged(int index)
{//1. 设置系统的编码方式 但只对下次打开文件起作用//记得需要修改打开关闭槽函数的编码方式为code_mode code_mode = ui->comboBox->currentText();qDebug() << "index: " << index;qDebug() << "coding: " << ui->comboBox->currentText();
}

  方式2:但实际应用中应该选择编码方式后应立即重新加载文件,这种方式更符合实际,实现步骤大致为:

  1. 获取新的编码方式
  2. 重新读取文本数据
  3. 将新的数据显示在文本编辑器中
void Widget::on_currentIndexChanged(int index)
{//1. 设置系统的编码方式 但只对下次打开文件起作用//记得需要修改打开关闭槽函数的编码方式为code_mode code_mode = ui->comboBox->currentText();qDebug() << "index: " << index;qDebug() << "coding: " << ui->comboBox->currentText();//2. 在不新打开新文件的情况下,选择编码方式,自动重新设置文件编码方式//重新读取文件数据流ui->textEdit->clear();if(file.isOpen()){//此时文件是打开的情况,文件光标在文件尾部,若要重新读取文件 需要重置光标file.seek(0);QTextStream in(&file);//以新的编码格式重新读取数据in.setCodec((const char*) code_mode.toStdString().c_str());while(!in.atEnd()){QString line = in.readLine();/***************3. 将txt文件内容输出至文本编辑器********************/ui->textEdit->append(line);}}
}

注意: 这种情况下当文件被打开按键打开并遍历一遍时,光标处于文件尾巴,因此需要手动将光标移至文件头部再进行对文件的读取

光标行列值显示

  QTextEdit中的光标改变会产生某个信号,可以进行信号与槽的连接。将光标改变信号和窗口槽函数连接,在槽函数中显示光标的行列位置。
光标变化信号:

void cursorPositionChanged()

获取光标位置:

QTextCursor QTextEdit::textCursor() const

获取光标行列值:

int columnNumber() const
int blockNumber() const

绑定信号与槽:

//文本框绑定光标变化信号和槽函数
connect(ui->textEdit,SIGNAL(cursorPositionChanged()),this,SLOT(on_cursorPositionChanged()));

槽函数实现:

void Widget::on_cursorPositionChanged()
{QTextCursor cursor = ui->textEdit->textCursor();//qDebug() << cursor.blockNumber()   + 1 << "," <<cursor.columnNumber() + 1 << endl;//将行列数字转为 QString 类型QString lineNum = QString::number(cursor.blockNumber() + 1);QString colNum =  QString::number(cursor.columnNumber() + 1);//行列信息显示于标签const QString msg = "line:" + lineNum + " col:" + colNum;ui->label1->setText(msg);
}

注意: 只有UTF-8的编码格式工程允许在QLabel中显示中文。本工程编码格式为GBK,QLabel无法正常显示中文,后续工程将使用UTF-8编码。

记事本打开窗口标题

在文件未打开、打开、保存、修改后记事本的窗口标题提示应根据实际情况修改,因此需根据不同情况设置窗口的标题
未打开 / 关闭 槽函数

this->setWindowTitle("my notebook");

打开 / 保存 槽函数:

//设置记事本标题
QString qstr = QString::fromStdString(fileName.toStdString().substr(33,-1));
this->setWindowTitle( qstr + "-my noteBook");

关闭按钮优化—弹窗提示

  通过利用帮助手册中QMessageBox的Detailed Description中的案例代码进行修改整合,实现关闭按钮的弹窗检测。

//关闭文件按钮
void Widget::on_pushButton2_clicked()
{int ret = QMessageBox::warning(this, tr("My Application"),tr("The document has been modified.\n""Do you want to save your changes?"),QMessageBox::Save | QMessageBox::Discard| QMessageBox::Cancel,QMessageBox::Save);switch (ret){//保存,调用保存功能case QMessageBox::Save://调用保存按钮槽函数qDebug() << "Save" << endl;on_pushButton3_clicked();if(file.isOpen())file.close();ui->textEdit->clear();this->setWindowTitle("my notebook");break;//丢弃 不保存 清理数据case QMessageBox::Discard:qDebug() << "Discard" << endl;ui->textEdit->clear();if(file.isOpen()){file.close();this->setWindowTitle("my notebook");}break;//误触case QMessageBox::Cancel:qDebug() << "Cancel" << endl;break;default:// should never be reachedbreak;}
}

快捷键设计

  在Qt中实现快捷键功能通常涉及到类的使用。下面是一个简答的代码示例,展示如何在Qt应用程序中为特定功能设置快捷键:

//创建一个快捷键(Ctrl+n)开关连到窗口
QShortcut *shortcut = new QShortcut(QKeySequence("Ctrl+n"),this);
//当快捷键按下,显示一个消息框
QObject::connect(shortcut, &QShortcut::activated,[&](){QMessageBox::information(this, "short activated", "ctrl+N was pressed");
});

在这个示例中,当用户按下 Ctrl+ N时,程序将弹出一个消息框。这是通过创建一个 QShortcut 对象,并将其快捷键序列设量为 "Ctrl+N” 来实现的。然后将 activated 信号连接到一个 Lambda 函数,该函数在快捷键被激活时执行。这种方法非常适用于为特定操作提供快速访问路径。

为记事本打开和保存文件设置快捷键:

//按钮打开快捷键
QShortcut *shortcutOpen = new QShortcut(QKeySequence(tr("Ctrl+o", "File|Open")),this);
connect(shortcutOpen, &QShortcut::activated,[=](){on_pushButton1_clicked();
});//设置保存快捷键
QShortcut *shortcutSave = new QShortcut(QKeySequence(tr("Ctrl+s", "File|Save")),this);
connect(shortcutSave, &QShortcut::activated,[=](){on_pushButton3_clicked();
});

字体大小缩放快捷键实现:

//创建一个快捷键(Ctrl+Shift+=)放大缩小字体
QShortcut *fontSizeIn  = new QShortcut(QKeySequence(tr("Ctrl+Shift+=", "File|Save")),this);
QShortcut *fontSizeOut = new QShortcut(QKeySequence(tr("Ctrl+Shift+-", "File|Save")),this);//字体放大
connect(fontSizeIn,&QShortcut::activated,[=](){qDebug() << "Ctrl+Shift+=" << endl;//获得TextEdit的当前信息QFont font = ui->textEdit->font();//获得当前字体大小int fontSize = font.pointSize();qDebug() << "size= " << fontSize << endl;if(fontSize == -1)  return;//改变字体大小font.setPointSize(++fontSize);ui->textEdit->setFont(font);
});//字体缩小
connect(fontSizeOut,&QShortcut::activated,[=](){//获得TextEdit的当前信息QFont font = ui->textEdit->font();//保存当前字体大小int fontSize = font.pointSize();if(fontSize == -1)  return;//改变字体大小font.setPointSize(--fontSize);ui->textEdit->setFont(font);
});

二、☆ QT事件处理

事件处理过程

  众所周知Q 是一个素于C++的能架,主要用来开发带窗口的应用程序,我们使用的基于窗口的应用程序都是基于事件,其目的主要是用来实现回调。所以在Qt框架内部为我们提供了一系列的事件处理机制,当窗口事件产生之后,事件会经过:事件派发 -> 事件过滤 -> 事件分发 -> 事件处理 几个阶段。Qt窗口中对于产生的一系列事件都有默认的处理动作,如果我们有特殊需求就需要在合适的阶段重写事件的处理 动作,比如信号与槽就是一种
  事件 (event)是由系统或者Qt本身在不同的场景下发出的。当用户按下 / 移动鼠标,敲下键盘,或者是窗口关闭 / 大小发生变化 / 隐藏或显示都会发出一个相应的事件。 一些事件在对用户操作做出响应时发出,如鼠标 / 键盘事件等;另一些事件则是由系统自动发出,如计时器事件。
  每一个Qt应用程序都对应一个唯一的 QApplication 应用程产对象,然后调用这个对象的 exec() 函数。这样Qt框架内部的事件检测就开始了(程序将进入事件循环来监听应用程序的事件)。

int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec(); 
}

我件在Qt中产生之后的分发过理是这样的:
1.当事件产生之后,Qt使用应用程序对象调用notify() 函数将事件发送到指定的窗口:

[override virtual] bool QApplication::notify(QObject *receiver, QEvent *e);

2.事件在发送过程中可以通过事件过滤器进行过滤,默认不对任何产生的事件进行过滤。

//需要先给窗口安装过滤器,该事件才会触发
[virtual] bool QObject::eventFilter(QObject *watched, QEvent *event);

3.当事件发送到指定窗口之后,窗口的事件分发器会对收到的事件进行分类:

[override virtual protected] bool QObject::event(QEvent *event);

4.事件分发器会将分类之后的事件(鼠标事件、键盘事件、绘图事件…)分发给对应的事件处理函数进行处理,每个事件处理器函数都有默认的处理动作 (我们也可以重写这些事件处理器函数) ,比如:鼠标事件:

//鼠标按下
[virtual protected] void QWidget::mousePressEvent(QMouseEven *event);
//鼠标释放
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event);
//鼠标移动
[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event);

重写事件案例

  初步重写鼠标进入、离开、滚轮滑动以及关闭窗口的常用事件,并给出相关重写过程与实例程序:

//头文件声明事件重写函数
void enterEvent(QEvent *event) override;
void leaveEvent(QEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void closeEvent(QCloseEvent *event) override;
/**************重写事件函数c文件实现***************/
//鼠标进入事件
void Widget::enterEvent(QEvent *event)
{qDebug() << "mouse enter" << endl;
}
//鼠标离开事件
void Widget::leaveEvent(QEvent *event)
{qDebug() << "mouse leave" << endl;
}
//滚轮事件
void Widget::wheelEvent(QWheelEvent *event)
{qDebug() << event->angleDelta();
}
//窗口关闭事件
void Widget::closeEvent(QCloseEvent *event)
{//创建QMessageBox弹窗int ret = QMessageBox::warning(this, tr("My notebook"),tr("close the windows\n""Do you want toclose the windows?"),QMessageBox::Yes | QMessageBox::No);switch (ret){case QMessageBox::Yes:event->accept();	//接受事件break;case QMessageBox::No:event->ignore();	//忽略事件break;default:// should never be reachedbreak;}
}

事件自定义按钮

  之前通用UI界面已完成按钮的三态设置,按钮的跳转等等,为巩固事件处理,本次通过事件处理来完成的按钮的三态、美化与响应过程:

#include "evnetbutton.h"#include <QPainter>evnetButton::evnetButton(QWidget *parent) : QWidget(parent)
{pic.load(":/icon/file.jpg");//加载图片//setFixedSize(pic.size());   //图片和按钮大小匹配 按钮适应图片大小update();                   //update才能调paintEvent事件
}
void evnetButton::enterEvent(QEvent *event)
{pic.load(":/icon/QQ.jpg");//加载图片update();
}
void evnetButton::mousePressEvent(QMouseEvent *event)
{pic.load(":/icon/QQ.jpg");//加载图片update();
}
void evnetButton::leaveEvent(QEvent *event)
{pic.load(":/icon/file.jpg");//加载图片update();
}
void evnetButton::paintEvent(QPaintEvent *event)
{QPainter painter(this);painter.drawPixmap(rect(),pic);
}

注意: 需要将UI文件内的QWidget 提升为evnetButton类(自定义类)。

为自定义按钮添加信号与槽:
在按钮按下的状态事件下,发送一个自定义信号:

void evnetButton::mousePressEvent(QMouseEvent *event)
{pic.load(":/icon/QQ.jpg");//加载图片update();emit clicked();
}

主widget界面程序绑定自定义信号与槽,响应按键的按下处理:

/*********自定义按钮事件的槽函数**********/
connect(ui->eventBtn,&evnetButton::clicked,[=]()
{qDebug() << "eventButton clicked!";
});

鼠标滚轮实现字体大小缩放

1. 自定义控件MyTextEdit,并使得继承于QTextEdit

class MyTextEdit : public QTextEdit
{
public:MyTextEdit(QWidget *parent);
};
//构造函数 带父对象
MyTextEdit::MyTextEdit(QWidget *parent):QTextEdit(parent)
{
}

2. 捕获按钮按下,松开以及滚轮滑动事件

protected:void wheelEvent(QWheelEvent *e) override;void keyPressEvent(QKeyEvent *e) override;void keyReleaseEvent(QKeyEvent *e) override;
private:bool ctrlPressed = 0;
//鼠标滚轮事件
void MyTextEdit::wheelEvent(QWheelEvent *e)
{qDebug() << e->angleDelta().y();//按下ctrl + 滚轮实现字体缩放if(ctrlPressed == 1){if( e->angleDelta().y() > 0)zoomIn();   //放大elsezoomOut();  //缩小e->accept();}else                //鼠标正常下滑{QTextEdit::wheelEvent(e);}
}//按键按下事件
void MyTextEdit::keyPressEvent(QKeyEvent *e)
{if(e->key() == Qt::Key_Control){ctrlPressed = 1;            //ctrl按下标志//qDebug() << "ctrl pressed!";}QTextEdit::keyPressEvent(e);    //由Press正常执行
}//按键松开事件
void MyTextEdit::keyReleaseEvent(QKeyEvent *e)
{if(e->key() == Qt::Key_Control){ctrlPressed = 0;//qDebug() << "ctrl Release!";}QTextEdit::keyReleaseEvent(e);  //由Release正常执行
}

事件过滤器

  我们通过继承QTextEdit来重写事件实现Ctrl加滚轮的检测,还有一种处理方式,叫做事件过滤器
  在Qt的事件处理过程中,引入事件过滤器 (Event Filter) 可以让你在事件达到目标对象之前进行拦截和处理。这是一种强大的机制,允许你在不同对象间共享事件处理逻辑或在父对象中集中处理待定事件,下面是加入事件过滤器的步聚:

  • 1.定义事件过滤器: 事件过滤器通常是重写了 QObject::eventFilter() 方法的对象。这个方法会在事件传递给目标对象之前被调用。

  • 2. 安装事件过滤器: 使用 QObject::installEventFilter() 方法安装事件过滤器。这个方法告诉Qt在将事件发送给特定对象之前先通过过滤器对象。例如,如果想在父面口中过滤子窗口的事件,需要在父窗口的对象上调用installEventFilter(),并将子窗口作为参数传进。

  • 3.事件过波路逻辑:eventFilter() 方法内部,可以编写自定义逻辑来决定如何处理或忽略事件。如果此方法返回 true,则表示事件已被处理,不应该继续传递;如果返回 false,则事件将正常传递给目标对象。

  • 4.事件分发: 当事件发生时,Qt首先将事件发送到安装了事件过滤器的对象。在这一步,eventFilter() 方法被调用。

  • 5.决定是否传进事件: 根据 eventFilter() 方法的返回值,Qt决定是否继续向目标对象传递事件。如果过滤器返回 true,事件处理到此结束;如果返回 false,事件继续传递到原始目标对象。

  • 6.目标对象处理事件: 如果事件过滤器允许事件继续传递,目标对象将没有事件过滤器存在时那样处理事件。

事件过滤器待别适用于以下情况:

  • 想在不修改子类代码的情况下改变事件的行为。
  • 当多个对象需要共享相同的事件处理逻辑。
  • 当需要在更高的层级上监控或修改应用程序的事件流。

通过使用事件过洗器,Qt应用程序可以获得更大的灵活性和更细粒度的事件处理控制。

滚轮字体的实现:
为文本编辑器安装事件过滤器:

// 构造函数内 给textEdit安装事件过滤器,为滚轮字体做准备
ui->textEdit->installEventFilter(this); 

事件过滤器处理函数:

//事件过滤器
bool Widget::eventFilter(QObject *watched, QEvent *event)
{// 滚轮滑动if(event->type() == QEvent::Wheel){if(QGuiApplication::keyboardModifiers() == Qt::ControlModifier){qDebug() << "control + Wheel";QWheelEvent *wheelEvent = (QWheelEvent *)event;//判断滚轮方向if(wheelEvent->angleDelta().y() > 0){zoomIn();qDebug() << "zoomIn";}else if(wheelEvent->angleDelta().y() < 0){qDebug() << "zoomOut";zoomOut();}}}
}

三、当前行高亮的实现

C++模板回顾

  • 在C++中,模板 (Template) 是一种通用的编程工具,允许程序员编写泛型代码,使得类或函数能够适用于多种不同的数据类型 而不需要重复编写相似的代码
  • C++ 提供了两种主要类型的模板:类模板和函数模板

类模板:
  类模板允许定义通用的类,其中某些类型可以作为参数。这样的类可以处理不同类型的数据,而不需要为每个数据类型编亏单独的类。

Ps:若对模板有一定的了解的可跳过这个

//类模板定义
template <typename T>	//定义一种模板
class PrintData
{
private:T data;public:void show_data(){cout << "data= " << data << endl;}void set_data(T data){this->data = data;}
};int main()
{//实例化模板对象p3, 数据类型为stringPrintData<string> p3;p3.set_data("hello");p3.show_data();return 0;
}

函数模板:
  函数模板允许编写通用的函数,可以处理多种不同类型的数据。

//定义一个函数模板
template <typename T>
T add(T a, T b)
{return a + b;
}int main()
{//测试函数模板int ret1 = add(10,20);cout << "ret1= " << ret1 << endl;double ret2 = add(1.5,2.2);cout << "ret2= " << ret2 << endl;return 0;
}

QList容器介绍及使用

  在Qt 框架中,QList 是一个容器类,它在内部实现上类似于一个数组,但也提供了一些链表的特性。 QList 的设计旨在提供一个在多数情况下既高效又方便的通用列表容器。用于存储元素列表,它提供了丰高的功能,包括添加、 移除、访问元素等。

QList 的内部工作原理:

  • 1.数组式存储: QList 在大多数情况下使用连续内存存储其他元素,类似于数組。这意味着它提供了快速的索引访问(通过下标操作符 [ ] ),以及相应高效的迭代性能
  • 2.动态调整大小:与静态数组不同,QList 可以动态增长和缩减,自动管理内存分配。
  • 3. 链表特性: 虽然 QList 主要基于数组,但它也提供了一些链表的操作,比如在列表的开始或结束处添加和移除元素。这些操作通常比在数组中间插入或删除元素更高效。
  • 4. 复制时共享内存: QList 使用一种称为“隐式共享”,或“写时复制”的技术。这意味者当你复制一个QList时,它不会立即复制所有元奈,而是共享相同的数据,直到你尝试修改其中一个列表,此时才进行实际的复制。这使得复制 QList 变得非常高效。

使用场景:

  • 当你需要快速的随机访问(如通过索引访问元素)时,QList 是一个不错的选择。
  • 如果你的主要操作是在列表的两端添加或移除元素,QList 也表现得很好。

基本用法:
包含头文件: 首先,需要包含 QList 的头文件。

#include <QList>

**创建QList实例:**创建一个QList对象,并指定存储的元素类型

QList<int> list;

添加元素: 使用 appendpush_back() 方法添加元素

list.append(10);
list.append(20);
list.append(30);

访问元素: 可以使用下标操作符或 at() 方法访问元素

int element1 = list[0];
int element2 = list.at(1);

遍历列表: 使用迭代器或范围的 for 循环遍历列表

for(int i = 0; i < list.size(); i++)
{qDebug() << list[i];
}//使用范围的for循环遍历
for(int item : list)
{qDebug() << item ;
}

移除元素: 使用removeAt、removeOne或clear方法移除

list.removeAt(1);		//移除索引为1的元素
list.removeOne(100);	//移除一个值为100的元素
list.clear();			//清空整个列表

当前行高亮设置

  在之前的光标位置改变的槽函数中进行补充设置当前行高亮代码,这些先给出实现高亮的代码,后面再对ExtraSelection做简要介绍。

void Widget::on_cursorPositionChanged()
{/**********光标行列值显示************/QTextCursor cursor = ui->textEdit->textCursor();qDebug() << cursor.blockNumber()   + 1 << "," <<cursor.columnNumber() + 1 << endl;//将行列数字转为 QString 类型QString lineNum = QString::number(cursor.blockNumber() + 1);QString colNum =  QString::number(cursor.columnNumber() + 1);const QString msg = "line:" + lineNum + " col:" + colNum;ui->label1->setText(msg);/*************设置当前行高亮*************///QList及变量定义QList<QTextEdit::ExtraSelection> extraSelections;   //QTextEdit::ExtraSelection 类型的列表集合QTextEdit::ExtraSelection ext1;//1. 获取当前行ext1.cursor = ui->textEdit->textCursor();//2. 设置颜色QBrush qBrush(Qt::yellow);ext1.format.setBackground(qBrush);//配置段落属性:整行显示,没有这行不行ext1.format.setProperty(QTextFormat::FullWidthSelection,true);//3. 设置//将ext1对象加入QList容器列表extraSelections.append(ext1);ui->textEdit->setExtraSelections(extraSelections);
}

ExtraSelection简介

QTextEdit::ExtraSelection 是一个在 QTextEdit 中用来表示额外文本选的和高亮的结构。
如何工作:

  • 1. ExtraSelection结构体QTextEdit::ExtraSelection 是一个结构体,包含了两个主要成员:QTextCursorQTextCharFormat。QTextCursor 表示在文本中的一个位置或区间,而 QTextCharFormat 用于定义这个区间的格式,比如背景颜色、字体等。
  • 2.设置 Extraselection: 通过创建一个或多个 ExtraSelection 对象,为它们设置相应的光标位置和格式,然后通过QTextEdit的 setExtraSelections方法将这些对象应用到文本编辑器中。这样,就可以对文本的特定部分应用特定的格式,而不影响其他文本。
  • 3.高亮当前行: 要高亮显示当前行,需要在cursorPositionChanged() 信号的槽的函数中创建一个 ExtraSelection 对象。使用当前 QTextCursor 对象(通过 textCursor() 方法获取)来确定当前行的位置,并设置背景颜色为选择的一种高亮颜色。

  QTextCharFormat 类是Qt框架中的一部分,用于描述文本字符的格式。这个类提供了 丰富的接口来设置和获取文本字符的各种属性等。QTextCharFormat 通常用于丰富文本处理,可以在像 QTextEdit 和 QTextDocument 这样的类中使用。

QTextCharFormat 常用功能和方法:

1. 设置和获取字体样式:

  • 通过 setFont() 方法设置字体
  • 通过 font() 方法获取当前字体

2. 设置字体属性:

  • setFontWeight():设置字体粗细
  • setFontItalic():设置字体是否倾斜
  • setFontUnderline():设置是否有下划线

3. 设置文本颜色和背景颜色:

  • setBackground():设置文本的背景色
  • setForeground():设置文本字体的颜色

4. 其他文本属性:

  • setToolTip():设置文本的工具提示
  • setAnchor():设置文本是否为超链接
  • setAnchorHref():设置超链接的目标URL

实例代码:
下面是一个简单的示例,展示如何在QTextEdit 中使用QTextCharFormat来设置特定文本的格式:

#include <QApplication>
#include <QTextEdit>
#include <QTextCharFormat>int main(int argc, char *argv[])
{QApplication a(argc, argv);QTextEdit editor;//创建一个QTextCharFormat对象QTextCharFormat format;format.setFontWeight(QFont::Bold);format.setForeground(Qt::blue);format.setBackground(Qt::yellow);//将格式应用到编辑器中的特定文本QTextCursor cursor = editor.textCursor();cursor.movePosition(QTextCursor::Start);cursor.insertText("hello world!",format);editor.show();return a.exec();
}

四、记事本项目总结

类别功能描述
UI设计师基本控件操作QWidget基础的用户单元、用于构建复杂的用户界面
QPushButton用于创建按钮
QHBoxLayout水平布局管理器,用于水平排列控件
QVBoxLayout竖直布局管理器,用于竖直排列控件
QTextEdit多行文本编辑器控件
QStyleSheet使用样式表来控制控件的外观
文件操作类QFile用于读取和写入文件
文件选择对话框类QFileDialog提供一个对话框,允许用户选择文件或目录
QT的信号与槽-用于对象之间的通信机制
消息对话框QMessageBox用于显示信息、警告、错误等对话框
快捷键捕获和处理-用户捕获和键盘快捷键
Ctrl按键信号捕获和处理-专门处理Ctrl按键的信号
鼠标滚轮信号捕获和处理-专门捕获和处理鼠标滚轮动作
事件处理event用于处理不同的事件
文本字符编码检测-用于检测和处理文本的字符编码
字体放大缩小-用于调整字体大小
QT程序开发流程-涉及从设计到部署的整个开发流程

相关文章:

C++ QT入门2——记事本功能实现与优化(事件处理+基本控件)

C QT入门2——记事本功能优化&#xff08;事件处理基本控件&#xff09; 一、记事本功能优化编码乱码问题QComboBox下拉控件QString、string、char * 间的数据转化编码问题解决整合 光标行列值显示记事本打开窗口标题关闭按钮优化—弹窗提示快捷键设计 二、☆ QT事件处理事件处…...

《Lua程序设计》-- 学习10

环境&#xff08;Environment&#xff09; 具有动态名称的全局变量 全局变量的声明 由于Lua语言将全局变量存放在一个普通的表中&#xff0c;所以可以通过元表来发现访问不存在全局变量的情况。 正如前面所提到的&#xff0c;我们不允许值为nil的全局变量&#xff0c;因为值为…...

Linux内核编译-ARM

步骤一、下载源码及交叉编译器后解压 linux kernel官网 ARM GCC交叉编译器 步骤二、安装软件 sudo apt-get install ncurses-dev sudo apt-get install flex sudo apt-get install bison sudo apt install libgtk2.0-dev libglib2.0-dev libglade2-dev sudo apt install libs…...

开源编辑器:ONLYOFFICE文档又更新了!

办公软件 ONLYOFFICE文档最新版本 8.0 现已发布&#xff1a;PDF 表单、RTL、单变量求解、图表向导、插件界面设计等更新。 什么是 ONLYOFFICE 文档 ONLYOFFICE 文档是一套功能强大的文档编辑器&#xff0c;支持编辑处理文本文档、电子表格、演示文稿、可填写的表单、PDF&#…...

第3章 文件类型和目录结构

第3章 文件类型和目录结构 在这这章之前我们先学习一个前面使用过的命令 ls 查看文件ls 命令格式&#xff1a; [rootbogon redhat]# ls --helpUsage: ls [OPTION]... [FILE]...List information about the FILEs (the current directory by default).Sort entries alphabeti…...

前端构建变更:从 webpack 换 vite

现状 这里以一个 op &#xff08;内部运营管理用&#xff09;项目为例&#xff0c;从 webpack 构建改为 vite 构建&#xff0c;提高本地开发效率&#xff0c;顺便也加深对 webpack 、 vite 的了解。 vite 是前端构建工具&#xff0c;使用 一系列预配置进行rollup 打包&#x…...

记录基于Vue.js的移动端Tree树形组件

目录 一、Liquor Tree 入门 : Development Component Options 组件选项 Structure 结构 二、vue-treeselect Introduction 介绍 Getting Started 入门 Vue 树形选择器( Vue tree select )组件在搭建 Vue 的 app 中特别常用,Vue tree select 除了简单的树形结构…...

Vue中嵌入原生HTML页面的方法

在Vue中嵌入原生HTML页面通常可以通过组件或页面的方式来完成。下面将详细说明如何通过组件方式实现这个功能&#xff0c;并提供一个简单的代码示例。 方法说明 创建原生HTML页面&#xff1a;首先&#xff0c;你需要创建一个原生HTML页面&#xff0c;这个页面可以是一个独立的…...

17 # 类型检查机制:类型保护

例子&#xff1a; enum Type {Strong,Week }class Java {helloJava(){console.log(hello Java);} }class JavaScript {helloJavaScript(){console.log(hello JavaScript);} }function getLanguage(type: Type){let lang type Type.Strong ? new Java() : new JavaScript();…...

Vulnhub-RIPPER: 1渗透

文章目录 一、前言1、靶机ip配置2、渗透目标3、渗透概括 开始实战一、信息获取二、rips的使用三、获取密码文件四、日志审查五、提权 一、前言 由于在做靶机的时候&#xff0c;涉及到的渗透思路是非常的广泛&#xff0c;所以在写文章的时候都是挑重点来写&#xff0c;尽量的不饶…...

幻兽帕鲁自建服务器:可以使用香港服务器吗?

随着网络技术的发展&#xff0c;越来越多的游戏爱好者选择通过自建服务器来享受游戏的乐趣。幻兽帕鲁作为一款备受喜爱的游戏&#xff0c;也有不少玩家想要自建服务器进行游戏。而在选择服务器地点时&#xff0c;很多玩家会想到使用香港服务器。那么&#xff0c;是否可以使用香…...

Revisiting image pyramid structure for high resolution salient object detection

accv2022的技术&#xff0c;在我测评的数据集上确实要明显好于basnet&#xff0c;rembg等一众方法。 1.Introduction 使用LR数据集训练的方法通过调整输入尺寸可以在HR图像上产生不错的结果。本文主要关注仅使用LR数据集进行训练以产生高质量的HR预测。HR的有效感受野ERFs和LR…...

中移(苏州)软件技术有限公司面试问题与解答(7)—— kmalloc与vmalloc的区别与联系及使用场景

接前一篇文章&#xff1a;中移&#xff08;苏州&#xff09;软件技术有限公司面试问题与解答&#xff08;0&#xff09;—— 面试感悟与问题记录 本文参考以下文章&#xff1a; kmalloc与vmalloc如何选择 Vmalloc与kmalloc的区别 特此致谢&#xff01; 本文对于中移&#xf…...

微服务-微服务Alibaba-Nacos 源码分析 (源码流程图)

客户端流程 客户端心跳与实例往服务端注册...

后端性能优化的一些总结

目录 1、背景 2、优化实现 2.1查询数据表速度慢 2.2调别人接口速度慢 2.3导入速度慢、 2.4导出速度慢的做出介绍 2.5统计功能速度慢 3、总结 1、背景 系统上线后&#xff0c;被用户反应系统很多功能响应时长很慢。用户页面影响速度有要求&#xff0c;下面针对查询数据表…...

【升级openssl1.1.1t报错libssl.so.1.1: cannot open shared object file】

升级openssl报错&#xff1a; openssl vesion openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory 编译安装openssl1.1.1t当执行openssl version的时候&#xff0c;报上述错误&#xff0c;将编译到的…...

CVE-2024-0352 likeshop v2.5.7文件上传漏洞分析

本次的漏洞研究基于thinkPHP开发开的一款项目..... 漏洞描述 Likeshop是Likeshop开源的一个社交商务策略的完整解决方案&#xff0c;开源免费版基于thinkPHP开发。Likeshop 2.5.7.20210311及之前版本存在代码问题漏洞&#xff0c;该漏洞源于文件server/application/api/contr…...

JAVA处理类似饼状图占比和100%问题,采用最大余额法

前言&#xff1a; 在做数据统计报表的时候&#xff0c;有两种方式解决占比总和达不到100%或者超过100%问题。 第一种方式是前端echart图自带的算分框架。 第二种方式是java后端取处理这个问题。 现存问题&#xff1a; 前端不通过饼状图的方式去展示各个分类的占比累加和为100%问…...

MATLAB矩阵的操作(第一部分)

矩阵的基本知识 矩阵概念 矩阵&#xff08;Matrix&#xff09;在数学中是一个由复数或实数组成的矩形阵列&#xff0c;其元素按照行和列排列。矩阵的定义可以形式化地描述为&#xff1a; 一个 m 行 n 列的矩阵是一个有序的数表&#xff0c;其中包含 m*n 个数&#xff0c;可以…...

全面掌握Django的web框架Django Rest_Framework(一)

文章目录 Django Rest_Framework1. DRF介绍2.DRF特点3.环境安装与配置&#xff08;1&#xff09;DRF需要以下依赖&#xff08;2&#xff09;创建django项目 4.序列化器的使用&#xff08;1&#xff09;创建序列化器 5. 反序列化器使用 Django Rest_Framework 1. DRF介绍 Djan…...

AOP+Redisson 延时队列,实现缓存延时双删策略

一、缓存延时双删 关于缓存和数据库中的数据保持一致有很多种方案&#xff0c;但不管是单独在修改数据库之前&#xff0c;还是之后去删除缓存都会有一定的风险导致数据不一致。而延迟双删是一种相对简单并且收益比较高的实现最终一致性的方式&#xff0c;即在删除缓存之后&…...

Hive中left join 中的where 和 on的区别

目录 一、知识点 二、测试验证 三、引申 一、知识点 left join中关于where和on条件的知识点&#xff1a; 多表left join 是会生成一张临时表。on后面&#xff1a; 一般是对left join 的右表进行条件过滤&#xff0c;会返回左表中的所有行&#xff0c;而右表中没有匹配上的数…...

LaTeX教程(001)-LaTeX文档结构(01)

LaTeX教程(001)- LaTeX \LaTeX LATE​X文档结构(01) 说在前面 这是我本人学习《The LaTeX Companion》第三版的笔记&#xff0c;但并不是翻译。 书籍的第一章对 LaTeX \LaTeX LATE​X及其历史进行了相当长的介绍&#xff0c;这是几乎每一本关于 LaTeX \LaTeX LATE​X的书都会…...

SV-7041T 多媒体教学广播IP网络有源音箱

SV-7041T是深圳锐科达电子有限公司的一款2.0声道壁挂式网络有源音箱&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;可达到功率30W。同时它可以外接一个30W的无源副音箱&#xff0c;用在面积较大的场所。5寸进口全频低音喇…...

Linux文本三剑客awk经典案例

前言&#xff1a; AWK是一种专门用于文本处理的编程语言&#xff0c;它被广泛用于数据提取和报告生成&#xff0c;也是企业笔试面试常考的内容&#xff0c;以下34题是awk的用法案例&#xff0c;希望可以帮到你&#xff01; 1.查看TCP连接状态 [rootnode1 ~]# netstat -nat | a…...

如何使用 Mermaid、GitHub 和 VSCode 用代码创建关系图三

Mermaid 系列 如何使用 Mermaid、GitHub 和 VSCode 用代码创建关系图一如何使用 Mermaid、GitHub 和 VSCode 用代码创建关系图二 1.如何创建甘特图 Gantt 甘特图以条形图的形式用作可视化表示。它有效地展示了项目的时间表&#xff0c;揭示了各个项目组件完成所需的持续时间…...

考研经验总结——政治篇

文章目录 一、前言二、学习情况三、最后 一、前言 不要提前&#xff0c;不要提前&#xff0c;不要提前&#xff0c; 我曾在暑假的时候上了7天左右的政治课&#xff0c;讲真话是很有趣的&#xff0c;并且对于自身的世界观、人生观和价值观的改善也是相当不错的&#xff0c;把我…...

春招秋招,在线测评到底难不难?

现在很多企业在春招的时候&#xff0c;都会有一个在线测评的环节&#xff0c;目的当然就是希望更加了解清楚毕业生的综合能力以及其他方面的素质&#xff0c;好让HR可以根据岗位筛选出能力达标的人才。所以&#xff0c;现在不少即将面对春招的大学毕业生&#xff0c;比较关心的…...

数学建模比赛中,使用大语言模型如chatgpt、文心一言该如何写Prompt(提示)?

在大型语言模型中&#xff0c;"prompt"&#xff08;中文常译为“提示”或“引导”&#xff09;是指提供给模型的输入文本&#xff0c;用于指示或引导模型产生特定的输出。它的作用主要是告诉模型用户想要得到什么样的信息或完成什么样的任务。 例如&#xff0c;在使…...

tcpdump 抓包无法落盘

文章目录 问题背景解决办法 问题背景 在嵌入式设备中(Linux系统)&#xff0c;为了分析两个网络节点的通讯问题&#xff0c;往往需要用到tcpdump&#xff0c;抓一个.pcap的包在PC端进行分析。博主在实际操作中发现&#xff0c;抓包无法实时落盘。 解决办法 # 下面的命令是写在…...