- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
剪贴板是个啥就不用多介绍了,最直观的功能是实现应用程序之间数据共享。就是咱们常说的“复制”、“粘贴”功能.
在 Qt 中,QClipboard 类提供了相关 API 让应用程序具备读/写剪贴板的能力。数据通过 QMimeData 类包装。该类使用 MIME 类型来标识数据。比如,要包装的数据是纯文本内容,就使用 text/plain;如果是 PNG 图像数据,就用 image/png。当然,自定义类型也是可以的,如 application/xxx.
QMimeData 的核心方法是 setData 和 data。setData 方法用来放入数据,data 方法用来取出数据。setData 方法的签名如下:
void setData( const QString &mimetype, const QByteArray &data);
mimetype 参数为字符串,指定数据的 MIME 类型;data 参数就是数据本尊,类型为字节序列。通过 setData 方法的签名,咱们也能知道,QMimeData 类可以放任意内容。要获取数据时,data 方法需要通过 MIME 类型来检索.
为了便于存取常见的数据——如文本、图像、HTML文本等,QMimeData 类提供一些封装好的方法成员:
文本 | 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 用来显示文本;然后是两个按钮—— 执行“复制”和“粘贴”操作.
后面两个方法 onCopy 和 onPaste 分别与两个按钮的 clicked 信号绑定.
构造函数的实现比较简单,就是调用 _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 类也是一个组件,以网格方式布局各组件。网格的行和列是自动划分的。上面代码中其实用到了三列两行:
1、QLineEdit 在第一列第一行; 。
2、第二列空着,没放东西; 。
3、 QLabel 组件在第三列第一行; 。
4、“复制”按钮在第一列第二行; 。
5、“粘贴”按钮在第二行第二行.
这三行是设定空间比例的.
_layout->setColumnStretch( 0 , 2 ); _layout ->setColumnStretch( 1 , 1 ); _layout ->setColumnStretch( 2 , 2 );
这意思就是,列的总宽平均分为4份,第一列和第三列都占两份,第二列只占一份.
随后是与 clicked 信号绑定的两个私有方法.
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(); }
运行程序,先输入一些文本,点击“复制”;再点击“粘贴”,被复制的文本就会显示出来了.
这个例子用了 QClipboard 类公开的封装方法,不需要操作 QMimeData 类。针对常用的数据格式,可直接用.
1、text、setText:设置或获取文本; 。
2、setImage 和 image:设置或获取图像(QImage类型); 。
3、setPixmap 和 pixmap:设置或获取图像(QPixmap类型).
后面两个是读写图像的.
对于图像数据的复制和粘贴,操作流程差不多,大伙伴有兴趣可以试试.
。
前文提到过,除了常见的数据格式外,QMimeData 允许自定义格式,用 MIME 来标识.
接下来,咱们做个练习,复制和粘贴生日贺卡信息。假设生日贺卡信息包括姓名、生日、祝福语。咱们用自定义的数据格式将其复制,也可以粘贴到应用程序上。MIME 类型为 application/bug.
以下是自定义窗口类的头文件定义.
#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> 元素差不多,即表单.
下面重点说两个 slot 方法.
第一个是 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生动形象地描述出数据的流动方向。注意输入和输出时,数据的顺序必须一致.
QMimeData 类用 setData 方法设置自定义数据时,参数接收的类型是 QByteArray(字节数组)而不是 QDataStream 对象,因此,我们要用 QBuffer 类来中转一下.
1、创建 QByteArray 实例; 。
2、创建 QBuffer 实例,关联 QByteArray 实例; 。
3、创建 QDataStream 实例,关联 QBuffer 实例.
QDataStream 类需要 QIODevice 的派生类来完成读写操作,而 QByteArray 类不是 QIODevice 的子类,故要用 QBuffer 来过渡一下。当然了,老周这里为了让这个思路更清晰一些,所以“中规中矩”地写代码。其实,QDataStream 类有接收 QByteArray 类型的参数的,可以省略 QBuffer 的代码。QDataStream 类内部自动创建 QBuffer 对象.
更正: 上面 onCopy 方法的代码有问题,当数据被“粘贴”(读取)后会引发空指针引用,致使程序崩掉。为了给大伙们提供参考,避免犯同类错误,所以,老周没有删除上面的代码。现在我放出修改后的 onCopy 方法.
void CustWind::onCopy() { …… // 包装数据 QMimeData* packet = new QMimeData; packet -> setData( " application/bug " , data); // 把数据放到剪贴板 QClipboard* cb = QApplication::clipboard(); cb -> setMimeData(packet); …… }
问题出在创建 QMimeData 实例时,我第一次的代码是栈上分配实例的,Qt 无法在后续的事件循环中管理其内存。所以,QMimeData 要用指针类型,以 new 运算符来创建实例.
。
第二个 slot 方法是 onPaste,实现贺卡的粘贴.
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); }
反序列化的原理与序列化是一样的,只是反向操作罢了。注意读写数据的顺序,写的时候是姓名 - 生日 - 祝福语,读的时候也必须按这个顺序.
最后,是 main 函数.
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 )
重点就是三步:
1、声明 CMake 文档支持的版本,应用项目的名称(target).
2、auto moc 一定要打开,否则编译时会挂.
3、添加源代码、链接相关的库.
。
好了,完工了,咱们试试.
先运行一个程序实例,输入相关信息,点复制按钮.
然后,关闭这个程序重新运行,或者再运行一个新程序实例,点粘贴按钮.
这样,就完成了自定义数据的复制和粘贴.
。
最后此篇关于【Qt6】读写剪贴板的文章就讲到这里了,如果你想了解更多关于【Qt6】读写剪贴板的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在使用 Qt 语言学家翻译一个 ui 文件。我使用 lupdate 获取了它的 ts 文件,并翻译了这些单词和短语。现在我想将它添加到我的代码中,但我从它的教程中发现我似乎必须将 tr() 添加到
我想在 Qt Creator 中创建下面的简单控制台应用程序: #include int main(int argc, char* argv[]) { std::cout #include
我想将 libQtGui.so.4 libQtNetwork.so.4 和 libQtCore.so.4 包含在与我的应用程序所在的目录相同的目录中。我如何让 Qt 理解这一点? y 目的是拥有一个使
我有一个充满 QPushButtons 和 QLabels 以及各种其他有趣的 QWidget 的窗口,所有这些都使用各种 QLayout 对象动态布局...而我想做的是偶尔制作一些这些小部件变得不可
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 7 年前。 Improve
我想知道 Qt 是否将下面代码的“版本 1”之类的东西放在堆上?在版本 1 中,Qt 会将 dirStuff 放在堆栈上还是堆上?我问是因为我有一种感觉,Java 将所有数据结构放在堆上......不
这个问题是关于 Qt Installer Framework 2.0 版的。 在这一点上,使用 Qt 安装程序框架的人都知道,如果不进行自定义,您根本无法通过安装程序覆盖现有安装。这样做显然是为了解决
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 8年前关闭。 Improve this q
因为我在我的计算机上安装了 Qt 4.8.4 和 Qt 5.1,所以我遇到了问题。 当只有 Qt 4.8.4 存在时,一切都很好。 当我添加 Qt 5.1 时,这个工作正常,但 Qt 4.8.4 给了
我无法在我的 Ubuntu 12 中安装更多软件包。我尝试了 apt-get install -f ,以及许多其他类似的技巧,但在找到解决方案方面没有进展。 这是属于 Qt 的损坏包: 以下包具有未满
我正在尝试使用 Virtual Box 中的 Ubuntu 机器复制我们目前在物理 Ubuntu 服务器上运行的应用程序。它是一个 QT 应用程序,但在服务器上我们使用 NPM 的 pm2 运行它。安
问题: Qt Creator 是用 Qt Creator 构建的吗? 同样,Qt Designer 是用 Qt Designer 构建的吗? 顺便说一句,为什么有两个 Qt IDE?他们是竞争对手吗?
当我使用 QWidget设计用户界面时,我总是对它的大小属性有点困惑。有size policy , geometry和 hintSize . 我只知道size policy之间的关系和 hintSiz
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我想知道是否有一种很好的方法可以让用户像 LabView 一样创建节点图(有限制)。 像这样的东西: 我见过http://www.pyqtgraph.org/ ,这似乎有类似的东西,我确实打算使用 P
在 Qt 中是否有一种跨平台的方式来获得用户喜欢的固定宽度和比例字体? 例如,在 cocoa 中,有 NSFont *proportional = [NSFont userFontOfSize:12.
我想使用 Qt 和 C++ 制作这样的交互式图表:http://jsxgraph.uni-bayreuth.de/wiki/index.php/Cubic_spline_interpolation 关
我正在编写一个嵌入式设备屏幕的模拟(其中包含主 QWidget 顶部的自定义小部件),虽然屏幕的原始尺寸是 800x600,但我希望能够按比例放大和缩小它拖动窗口的角。如果不使用网格布局和担架(不会向
在下面的示例中,我是否必须从堆中删除对象?如果是的话,怎么办? #include #include #include #include #include int main(int argc,
来自 Web 开发背景,我现在进入 QT 应用程序开发。 使用 QFonts 我已经看到我显然只有两个选择,在 QT 中定义字体大小;按像素大小或点大小。 在制作网页布局时,我习惯于以相对方式定义所有
我是一名优秀的程序员,十分优秀!