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程序开发流程-涉及从设计到部署的整个开发流程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/662987.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flutter GridView控件实践

gridView顶部自带padding问题 如图所示&#xff1a; 顶部有一个比较大的padding。 如何处理&#xff1a;给gridView设置&#xff1a;padding: EdgeInsets.zero,

关于torch_xla.core.xla_model无法导入的问题

直接使用pip install或github中的代码发现仍然无法成功导入torch_xla.core.xla_model&#xff0c; 在conda中conda list发现存在torch_xla为1.0版本&#xff0c;尝试更新发现只有该版本。发现conda_xla库内除了__init__.py以外&#xff0c;没有任何文件。在__init__.py中提示包…

Java 正则匹配sql

文章目录 正则匹配sql表名称insert intoupdate 正则表达式什么时候要加^$ 在线正则校验 正则匹配sql表名称 insert into insert into PING_TABLE (CODE, NAME) VALUES(0, 待提交),(1, 审核中),(2, 审核通过),(3, 已驳回); regex -> insert\sinto\s(\w)\s*\(?update upda…

架构整洁之道-组件构建原则

5 组件构建原则 大型软件系统的架构过程与建筑物修建很类似&#xff0c;都是由一个个小组件组成的。所以&#xff0c;如果说SOLID原则是用于指导我们如何将砖块砌成墙与房间的&#xff0c;那么组件构建原则就是用来指导我们如何将这些房间组合成房子的。 5.1 组件 组件是软件的…

想好新年去哪了吗?合合信息扫描全能王用AI“留住”年味

还有不到十天&#xff0c;除夕就要到了。近几年春节假期中&#xff0c;有人第一次带着孩子直击海面冰风&#xff0c;坐船回老家&#xff1b;也有人选择“漫游”国内外&#xff0c;在旅行中迎接新春的朝气。合合信息旗下扫描全能王APP通过AI扫描技术&#xff0c;提供了一种全新的…

Acwing---798.差分矩阵

差分矩阵 1.题目2.基本思想3.代码实现 1.题目 输入一个 n n n 行 m m m列的整数矩阵&#xff0c;再输入 q q q 个操作&#xff0c;每个操作包含五个整数 x 1 , y 1 , x 2 , y 2 , c x1,y1,x2,y2,c x1,y1,x2,y2,c&#xff0c;其中 ( x 1 , y 1 ) (x1,y1) (x1,y1) 和 ( x …

创新大赛专访丨移步到岗荣膺2023年度人力资源服务质量卓越品牌:“人财税法”综合解决方案专家

日前&#xff0c;2023第三届全国人力资源创新大赛颁奖典礼暨成果展圆满举行。自2023年10月份启动以来&#xff0c;大赛共吸引了457个案例报名参赛&#xff0c;经组委会专家团队评审严格审核&#xff0c;企业赛道共有103个案例获奖、72家企业、13位个人、7个产业园斩获荣誉。 广…

RocketMQ消息队列(一)—— 基本概念和消息类型

RocketMQ是一个来自阿里巴巴的分布式消息中间件&#xff0c;于2012年开源&#xff0c;并在2017年正式成为Apache顶级项目。据了解&#xff0c;包括阿里云上的消息产品以及收购的子公司在内&#xff0c;阿里集团的消息产品全线都运行在RocketMQ上&#xff0c;并且最近几年的双十…

mybatis的一级缓存和二级缓存

一、介绍 1、mybatis缓存&#xff1a; mybatis包含一个非常强大的查询缓存特性&#xff0c;可以非常方便的定制和配置缓存&#xff0c;通过缓存减少Java Application与数据库的交互次数&#xff0c;从而提升程序的运行效率。 2、mybatis一二级缓存 mybatis的缓存分为一级缓存…

Docker中配置MySql环境

目录 一、简单安装 1. 首先从Docker Hub中拉取镜像 2. 启动尝试创建MySQL容器&#xff0c;并设置挂载卷。 3. 查看mysql8这个容器是否启动成功 4. 如果已经成功启动&#xff0c;进入容器中简单测试 4.1 进入容器 4.2 登录mysql中 4.3 进行简单添加查找测试 二、主从复…

MySQL-----初识

一 SQL的基本概述 基本概述 ▶SQL全称: Structured Query Language&#xff0c;是结构化查询语言&#xff0c;用于访问和处理数据库的标准的计算机语言。SQL语言1974年由Boyce和Chamberlin提出&#xff0c;并首先在IBM公司研制的关系数据库系统SystemR上实现。 ▶美国国家标…

MySQL亿级数据的查询优化-历史表该如何建

前端时间在知乎上看到一个问题&#xff0c;今天有空整理并测试了一下&#xff1a; 这个问题很具体&#xff0c;所以还是可以去尝试优化一下&#xff0c;我们基于InnoDB并使用自增主键来讲。 比较简单的做法是将历史数据存放到另一个表中&#xff0c;与最近的数据分开。那是不是…

如何使用Linux Archcraft结合内网穿透实现SSH远程连接

&#x1f4d1;前言 本文主要是使用Linux Archcraft结合内网穿透实现SSH远程连接的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#…

go gin 响应数据

go gin 响应数据 package mainimport ("fmt""github.com/gin-gonic/gin" )type UserInfo struct {UserName string json:"user_name"Age int json:"age"Password string json:"-" }func JsonTest(ctx *gin.Context…

黑马Java——常见API

一、游戏打包exe 游戏打包exe要考虑的因素&#xff1a; 游戏打包exe核心步骤&#xff1a; 详见《打包exe文档》 二、Math &#xff08;一&#xff09; Math类的常用方法 1、代码实现 2、小结

JVM 笔记

JVM HotSpot Java二进制字节码的运行环境 好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;具有垃圾回收功能数组下标越界检查多态&#xff08;虚方法表&#xff09; JVM组成 类加载子系统&#xff08;Java代码转换为字节码&#xff09;运行时数据…

【JavaEE进阶】 图书管理系统开发日记——贰

文章目录 &#x1f332;前言&#x1f384;设计数据库&#x1f343;引⼊MyBatis和MySQL驱动依赖&#x1f333;Model创建&#x1f38d;约定前后端交互接口&#x1f340;服务器代码&#x1f6a9;控制层&#x1f6a9;业务层&#x1f6a9;数据层 &#x1f334;效果展示⭕总结 &#…

01- k8s基础网络知识 之 underlay与overlay网络

前言&#xff1a; 我们在学习k8s网络之前&#xff0c;必须要了解k8s网络相关的一些基础知识&#xff0c;比如什么是underlay网络、overlay网络等&#xff0c;只有把基础知识掌握之后&#xff0c;后续学习k8s网络的时候&#xff0c;一些知识点就不会再云里雾里了。 1 underlay与…

协作办公开源神器:ONLYOFFICE

目录 前言ONLYOFFICE为什么选择ONLYOFFICE强大的文档编辑功能多种协作方式多人在线协同支持跨端多平台连接器安全性极高本地部署 ONLYOFFICE 8.0版本震撼来袭可填写的 PDF 表单显示协作用户头像更新插件界面设计更快更强大 总结 前言 近几年来&#xff0c;随着互联网技术的不断…

如何解决 docker registry x509 证书不信任问题?

最近想尝试一下极狐GitLab&#xff08;可以理解为 GitLab 在中国的发行版&#xff09;内置的容器镜像仓库&#xff0c;这样就不用自己安装 Harbor 之类的了。于是找了个服务器安装了一个极狐GitLab 的私有化部署版本&#xff0c;安装过程可以参考过往的技术文章使用Omnibus 安装…