[Qt 6]读写剪贴板

科技资讯 投稿 6200 0 评论

[Qt 6]读写剪贴板

在 Qt 中,QClipboard 类提供了相关 API 让应用程序具备读/写剪贴板的能力。数据通过 QMimeData 类包装。该类使用 MIME 类型来标识数据。比如,要包装的数据是纯文本内容,就使用 text/plain;如果是 PNG 图像数据,就用 image/png。当然,自定义类型也是可以的,如 application/xxx。

void setData(const QString &mimetype, const QByteArray &data;

mimetype 参数为字符串,指定数据的 MIME 类型;data 参数就是数据本尊,类型为字节序列。通过 setData 方法的签名,咱们也能知道,QMimeData 类可以放任意内容。要获取数据时,data 方法需要通过 MIME 类型来检索。

文本 setText 设置普通文本
text 获取普通文本
hasText
判断是否存在文本数据
HTML文本
setHtml
设置 HTML 文本
html
获取HTML文本
hasHtml
判断是否存在 HTML 文本数据
URL
setUrls
设置 URL 列表,参数为 QList<QUrl>
urls 获取 URL 列表
hasUrls
检测是否存在 URL 列表
图像
setImageData
设置图像数据
imageData
获取图像数据
hasImage
判断是否存在图像数据
颜色
setColorData
设置颜色数据
colorData
获取颜色数据
hasColor
是否存在颜色数据

 QClipboard 类不能直接实例化使用,它由 QGuiApplication 类的静态成员 clipboard 公开。该静态成员返回 QClipboard 类的指针,程序代码将通过这个指针来访问 QClipboard 对象。由于 QApplication 类派生自 QGuiApplication,当然也继承了 clipboard 成员。

MyWindow 类的头文件。

class MyWindow : public QWidget { Q_OBJECT public: MyWindow(QWidget* parent = nullptr; ~MyWindow(; private: void _initUi(; // 私有方法 // 下面是私有字段 QLineEdit* _txtInput; QLabel* _lbTxt; QPushButton* _btnCopy; QPushButton* _btnPaste; // 用来布局控件的 QGridLayout* _layout; // 下面成员响应 clicked 信号 void onCopy(; void onPaste(; };

_initUi 方法负责初始化窗口上的东西。这个窗口有四个组件:一个 QLineEdit 用来输入文本;一个 QLabel 用来显示文本;然后是两个按钮—— 执行“复制”和“粘贴”操作。

构造函数的实现比较简单,就是调用  _initUi 方法。

MyWindow::MyWindow(QWidget* parent : QWidget::QWidget(parent { // 初始化UI this -> _initUi(; } MyWindow::~MyWindow( { }

析构函数这里啥也不做。

下面是 _intUi 的实现代码。

void MyWindow::_initUi( { // 设置一下窗口 this->setWindowTitle("复制粘贴文本"; this->setGeometry(560, 480, 320, 150; this->setMinimumSize(300, 150; _txtInput = new QLineEdit(; _lbTxt = new QLabel(; _btnCopy = new QPushButton("复制"; _btnPaste = new QPushButton("粘贴"; _layout = new QGridLayout(this; // 设置空白 _layout->setSpacing(12; // 放置各控件 _layout->addWidget(_txtInput, 0, 0; _layout->addWidget(_btnCopy, 1, 0; _layout->addWidget(_lbTxt, 0, 2; _layout->addWidget(_btnPaste, 1, 2; _layout->setColumnStretch(0, 2; _layout->setColumnStretch(1, 1; _layout->setColumnStretch(2, 2; // 绑定信号和槽 connect(_btnCopy, &QPushButton::clicked, this, &MyWindow::onCopy; connect(_btnPaste, &QPushButton::clicked, this, &MyWindow::onPaste; }

QGridLayout 类也是一个组件,以网格方式布局各组件。网格的行和列是自动划分的。上面代码中其实用到了三列两行:

2、第二列空着,没放东西;

4、“复制”按钮在第一列第二行;

 这三行是设定空间比例的。

_layout->setColumnStretch(0, 2; _layout->setColumnStretch(1, 1; _layout->setColumnStretch(2, 2;

这意思就是,列的总宽平均分为4份,第一列和第三列都占两份,第二列只占一份。

void MyWindow::onCopy(
{
    // 获得 QClipboard 的引用
    QClipboard* clboard = QApplication::clipboard(;
    // 设置文本数据
    clboard -> setText(_txtInput -> text(;
}

void MyWindow::onPaste(
{
    // 过程差不多
    QClipboard* cb = QApplication::clipboard(;
    QString s = cb->text(;
    // 显示粘贴的文本
    _lbTxt->setText(s;
}

最后是 main 函数的代码:

int main(int argc, char** argv { QApplication app(argc, argv; MyWindow win; win.show(; return app.exec(; }

运行程序,先输入一些文本,点击“复制”;再点击“粘贴”,被复制的文本就会显示出来了。

1、text、setText:设置或获取文本;

3、setPixmap 和 pixmap:设置或获取图像(QPixmap类型)。

对于图像数据的复制和粘贴,操作流程差不多,大伙伴有兴趣可以试试。

前文提到过,除了常见的数据格式外,QMimeData 允许自定义格式,用 MIME 来标识。

以下是自定义窗口类的头文件定义。

#ifndef APP_H #define APP_H #include <qwidget.h> #include <qpushbutton.h> #include <qlineedit.h> #include <qdatetimeedit.h> class CustWind : public QWidget { Q_OBJECT public: CustWind(QWidget* parent = nullptr; private: QLineEdit* txtName; QLineEdit* txtWish; QDateEdit* txtDate; QPushButton* btnCopy; QPushButton* btnPaste; // 与 clicked 信号绑定的方法(Slots) void onCopy(; void onPaste(; }; #endif

在包含头文件时,用带 .h 后缀和不用后是一样的,既可以用 <QWidget> 也可以用 <qwidget.h>,只是作兼容之用。

CustWind::CustWind(QWidget *parent
    : QWidget::QWidget(parent
{
    // 初始化组件
    txtName = new QLineEdit(;
    txtWish = new QLineEdit(;
    txtDate = new QDateEdit(;
    // 有效日期范围
    txtDate -> setMinimumDate(QDate(1950, 1, 1;
    txtDate -> setMaximumDate(QDate(2085, 12, 31;
    btnCopy = new QPushButton("复制生日贺卡";
    btnPaste = new QPushButton("粘贴生日贺卡";
    // 布局
    QFormLayout* layout = new QFormLayout(this;
    layout->addRow("姓名:", txtName;
    layout->addRow("生日:", txtDate;
    layout->addRow("祝福语:", txtWish;
    QVBoxLayout *sublayout = new QVBoxLayout(;
    sublayout->addWidget(btnCopy;
    sublayout->addWidget(btnPaste;
    layout ->addRow(sublayout;
    // 连接信号和槽
    connect(btnCopy,&QPushButton::clicked,this,&CustWind::onCopy;
    connect(btnPaste,&QPushButton::clicked,this,&CustWind::onPaste;
}

这个例子咱们用 QFormLayout 来布局界面。其含义和 HTML 中 <form> 元素差不多,即表单。

第一个是 onCopy,由复制按钮的点击触发。

void CustWind::onCopy( { // 获取数据 QString name = txtName->text(; QString wish = txtWish->text(; QDate birthdate = txtDate->date(; if(name.isEmpty( { return; //姓名是空的 } // 开始序列化 QByteArray data; QBuffer buff(&data; // buffer 要先打开 buff.open(QBuffer::WriteOnly; QDataStream output(&buff; // 写入数据 output << name << birthdate << wish; buff.close(; // 包装数据 QMimeData packet; packet.setData("application/bug", data; // 把数据放到剪贴板 QClipboard* cb = QApplication::clipboard(; cb->setMimeData(&packet; QMessageBox::information(this,"恭喜","生日贺卡复制成功",QMessageBox::Ok; }

Qt 里面常用 QDataStream 类来做序列化和反序列化操作。由于它有运算符重载,我们可以使用 C++ 入门时最熟悉的 <<、>> 运算符来输入输出。向 QDataStream 对象写入数据时:

dataStream << a << b << c;

反序列化时:

dataStream >> a >> b >> c;

运算符很TM生动形象地描述出数据的流动方向。注意输入和输出时,数据的顺序必须一致。

1、创建  QByteArray 实例;

3、创建  QDataStream 实例,关联 QBuffer 实例。

 

void CustWind::onPaste(
{
    // 访问剪贴板
    QClipboard* cb=QApplication::clipboard(;
    const QMimeData* dataPack = cb->mimeData(;
    // 判断一下有没有我们要的数据
    if(!dataPack->hasFormat("application/bug"
    {
        return;
    }
    // 取出数据
    QByteArray data = dataPack->data("application/bug";
    // 反序列化
    QBuffer buff(&data;
    // 记得先打开 buffer
    buff.open(QBuffer::ReadOnly;
    QDataStream input(&buff;
    // 注意读的顺序
    QString name;
    QDate birth;
    QString wish;
    input >> name >> birth >> wish;
    // 显示数据
    this->txtName->setText(name;
    this->txtDate->setDate(birth;
    this->txtWish->setText(wish;
}

反序列化的原理与序列化是一样的,只是反向操作罢了。注意读写数据的顺序,写的时候是姓名 - 生日 - 祝福语,读的时候也必须按这个顺序。

int main(int argc, char* argv[]
{
    QApplication myapp(argc, argv;
    CustWind mwindow;
    mwindow.show(;
    return myapp.exec(;
}

CMake 文件(CMakeLists.txt)就按照标准文档上直接抄就行了。

cmake_minimum_required(VERSION 3.20 project(demo LANGUAGES CXX find_package( Qt6 REQUIRED COMPONENTS Core Gui Widgets set(CMAKE_CXX_STANDARD 17 set(CMAKE_CXX_STANDARD_REQUIRED ON set(CMAKE_AUTOMOC ON add_executable(demo app.h app.cpp target_link_libraries( demo PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets

重点就是三步:

2、auto moc 一定要打开,否则编译时会挂。

 

先运行一个程序实例,输入相关信息,点复制按钮。

 

编程笔记 » [Qt 6]读写剪贴板

赞同 (38) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽