Возникают ситуации, когда в приложении необходимо реализовать прямой доступ к буферу обмена. Это может потребоваться в программах с особой логикой операций копирования-вставки, или во вспомогательных утилитах, увеличивающих эффективность и простоту работы на компьютере.
В Qt для взаимодействия с буфером обмена удобно использовать класс QClipboard. Он позволяет отслеживать изменения в буфере обмена и добавлять в него произвольную информацию.
Разработаем простое приложение, которое формирует список строк текста, добавленных в буфер обмена за время его работы. А затем позволяет по двойному клику перенести нужный текст из списка в буфер обмена:
Заголовочный файл mainwidget.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#ifndef MAINWIDGET_H #define MAINWIDGET_H #include <QWidget> class QModelIndex; namespace Ui { class MainWidget; } class MainWidget : public QWidget { Q_OBJECT public: explicit MainWidget( QWidget* parent = 0 ); ~MainWidget(); private slots: void onClipboardChanged(); void onListDbClicked( const QModelIndex& index ); private: Ui::MainWidget* ui; }; #endif // MAINWIDGET_ |
Здесь лишь обратим внимание на заготовки двух слотов: onClipboardChanged() — обработчик сигнала, когда в буфер обмена что-либо добавляется; и onListDbClicked() — обработчик сигнала двойного клика на строке списка QListWidget.
Реализация mainwidget.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include "mainwidget.h" #include "ui_mainwidget.h" #include <QClipboard> #include <QMimeData> #include <QDebug> MainWidget::MainWidget( QWidget* parent ) : QWidget( parent ), ui( new Ui::MainWidget ) { ui->setupUi( this ); if( QClipboard* c = QApplication::clipboard() ) { connect( c, SIGNAL( dataChanged() ), SLOT( onClipboardChanged() ) ); } connect( ui->lstHistory, SIGNAL( doubleClicked( QModelIndex ) ), SLOT( onListDbClicked( QModelIndex ) ) ); } MainWidget::~MainWidget() { delete ui; } void MainWidget::onClipboardChanged() { if( QClipboard* c = QApplication::clipboard() ) { if( const QMimeData* m = c->mimeData() ) { if( m->hasText() ) { ui->lstHistory->insertItem( 0, m->text() ); } } } } void MainWidget::onListDbClicked( const QModelIndex& index ) { const QString& text = ui->lstHistory->item( index.row() )->text(); if( QClipboard* c = QApplication::clipboard() ) { c->disconnect( this ); c->setText( text ); connect( c, SIGNAL( dataChanged() ), SLOT( onClipboardChanged() ) ); } } |
Получить экземпляр QClipboard мы можем от класса приложения:
1 |
QClipboard* c = QApplication::clipboard(); |
Чтобы получать уведомления об изменениях в буфере обмена, связываем сигнал dataChanged() с заранее заготовленным обработчиком onClipboardChanged().
Логика чтения содержимого буфера обмена строится на QMimeData. Ранее мы уже сталкивались с этим классом, когда говорили о Drag&Drop в Qt.
Вставка в буфер обмена с помощью QClipboard интуитивно понятна и похожа на этап Drag в процедуре Drag&Drop. Заметим, что перед добавлением строки в буфер обмена мы отключаем обработчик сигнала dataChanged(), а после подключаем его вновь:
1 2 3 4 5 6 7 8 |
void MainWidget::onListDbClicked( const QModelIndex& index ) { const QString& text = ui->lstHistory->item( index.row() )->text(); if( QClipboard* c = QApplication::clipboard() ) { c->disconnect( this ); c->setText( text ); connect( c, SIGNAL( dataChanged() ), SLOT( onClipboardChanged() ) ); } } |
Если бы мы этого не делали, то наше приложение фиксировало изменения в буфере обмена, которые само и спровоцировало.