剪贴板的操作经常和前面所说的拖放技术在一起使用,因此我们现在先来说说剪贴板的相关操作。

大家对剪贴板都很熟悉。我们可以简单的把它理解成一个数据的存储池,可以把外面的数据放置进去,也可以把里面的数据取出来。剪贴板是由操作系统维护的,所以这提供了跨应用程序数据交互的一种方式。Qt 已经为我们封装好很多关于剪贴板的操作,因此我们可以在自己的应用中很容易的实现。下面还是从代码开始:

clipboarddemo.h

  1. #ifndef CLIPBOARDDEMO_H  
  2. #define CLIPBOARDDEMO_H  
  3.  
  4. #include <QtGui/QWidget>  
  5.  
  6. class ClipboardDemo : public QWidget  
  7. {  
  8.     Q_OBJECT  
  9.  
  10. public:  
  11.     ClipboardDemo(QWidget *parent = 0);  
  12.  
  13. private slots:  
  14.     void setClipboard();  
  15.     void getClipboard();  
  16. };  
  17.  
  18. #endif // CLIPBOARDDEMO_H 

clipboarddemo.cpp

  1. #include <QtGui>  
  2. #include "clipboarddemo.h"  
  3.  
  4. ClipboardDemo::ClipboardDemo(QWidget *parent)  
  5.     : QWidget(parent)  
  6. {  
  7.     QVBoxLayout *mainLayout = new QVBoxLayout(this);  
  8.     QHBoxLayout *northLayout = new QHBoxLayout;  
  9.     QHBoxLayout *southLayout = new QHBoxLayout;  
  10.  
  11.     QTextEdit *editor = new QTextEdit;  
  12.     QLabel *label = new QLabel;  
  13.     label->setText("Text Input: ");  
  14.     label->setBuddy(editor);  
  15.     QPushButton *copyButton = new QPushButton;  
  16.     copyButton->setText("Set Clipboard");  
  17.     QPushButton *pasteButton = new QPushButton;  
  18.     pasteButton->setText("Get Clipboard");  
  19.  
  20.     northLayout->addWidget(label);  
  21.     northLayout->addWidget(editor);  
  22.     southLayout->addWidget(copyButton);  
  23.     southLayout->addWidget(pasteButton);  
  24.     mainLayout->addLayout(northLayout);  
  25.     mainLayout->addLayout(southLayout);  
  26.  
  27.     connect(copyButton, SIGNAL(clicked()), this, SLOT(setClipboard()));  
  28.     connect(pasteButton, SIGNAL(clicked()), this, SLOT(getClipboard()));  
  29. }  
  30.  
  31. void ClipboardDemo::setClipboard()  
  32. {  
  33.     QClipboard *board = QApplication::clipboard();  
  34.     board->setText("Text from Qt Application");  
  35. }  
  36.  
  37. void ClipboardDemo::getClipboard()  
  38. {  
  39.     QClipboard *board = QApplication::clipboard();  
  40.     QString str = board->text();  
  41.     QMessageBox::information(NULL, "From clipboard", str);  
  42. }  

main.cpp

  1. #include "clipboarddemo.h"  
  2.  
  3. #include <QtGui>  
  4. #include <QApplication>  
  5.  
  6. int main(int argc, char *argv[])  
  7. {  
  8.     QApplication a(argc, argv);  
  9.     ClipboardDemo w;  
  10.     w.show();  
  11.     return a.exec();  
  12. }  

main() 函数很简单,就是把我们的 ClipboardDemo 类显示了出来。我们重点来看 ClipboardDemo 中的代码。

构造函数同样没什么复杂的内容,我们把一个label。一个 textedit 和两个 button摆放到窗口中。这些代码已经能够很轻易的写出来了;然后进行了信号槽的连接。

  1. void ClipboardDemo::setClipboard()  
  2. {  
  3.     QClipboard *board = QApplication::clipboard();  
  4.     board->setText("Text from Qt Application");  
  5. }  
  6.  
  7. void ClipboardDemo::getClipboard()  
  8. {  
  9.     QClipboard *board = QApplication::clipboard();  
  10.     QString str = board->text();  
  11.     QMessageBox::information(NULL, "From clipboard", str);  

在 slot 函数中,我们使用 QApplication::clipboard() 函数访问到系统剪贴板。这个函数的返回值是 QClipboard 的指针。我们可以从这个类的 API 中看到,通过 setText(),setImage() 或者 setPixmap() 函数可以将数据放置到剪贴板内,也就是通常所说的剪贴或者复制的操作;使用 text(),p_w_picpath() 或者 pixmap() 函数则可以从剪贴板获得数据,也就是粘贴。

另外值得说的是,通过上面的例子可以看出,QTextEdit 默认就是支持 Ctrl+C, Ctrl+V 等快捷键操作的。不仅如此,很多 Qt 的组件都提供了很方便的操作,因此我们需要从文档中获取具体的信息,从而避免自己重新去发明轮子。

QClipboard 提供的数据类型很少,如果需要,我们可以继承 QMimeData 类,通过调用 setMimeData() 函数让剪贴板能够支持我们自己的数据类型。

在 X11 系统中,鼠标中键(一般就是滚轮)可以支持剪贴操作的。为了实现这一功能,我们需要向 QClipboard::text() 函数传递 QClipboard::Selection 参数。例如,我们在鼠标按键释放的事件中进行如下处理:

  1. void MyTextEditor::mouseReleaseEvent(QMouseEvent *event)  
  2. {  
  3.     QClipboard *clipboard = QApplication::clipboard();  
  4.     if (event->button() == Qt::MidButton  
  5.             && clipboard->supportsSelection()) {  
  6.         QString text = clipboard->text(QClipboard::Selection);  
  7.         pasteText(text);  
  8.     }  

这里的 supportsSelection() 在 X11 平台返回 true,其余平台都是返回 false 的。

另外,QClipboard 提供了 dataChanged() 信号,以便监听剪贴板数据变化。