Возникают ситуации, когда в приложении необходимо реализовать прямой доступ к буферу обмена. Это может потребоваться в программах с особой логикой операций копирования-вставки, или во вспомогательных утилитах, увеличивающих эффективность и простоту работы на компьютере.
В Qt для взаимодействия с буфером обмена удобно использовать класс QClipboard
. Он позволяет отслеживать изменения в буфере обмена и добавлять в него произвольную информацию.
Разработаем простое приложение, которое формирует список строк текста, добавленных в буфер обмена за время его работы. А затем позволяет по двойному клику перенести нужный текст из списка в буфер обмена:
Заголовочный файл mainwidget.h
:
#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_H
Здесь лишь обратим внимание на заготовки двух слотов: onClipboardChanged()
- обработчик сигнала, когда в буфер обмена что-либо добавляется; и onListDbClicked()
- обработчик сигнала двойного клика на строке списка QListWidget.
Реализация mainwidget.cpp
:
#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
мы можем от класса приложения:
QClipboard* c = QApplication::clipboard();
Чтобы получать уведомления об изменениях в буфере обмена, связываем сигнал dataChanged()
с заранее заготовленным обработчиком onClipboardChanged()
.
Логика чтения содержимого буфера обмена строится на QMimeData
. Ранее мы уже сталкивались с этим классом, когда говорили о Drag&Drop в Qt.
Вставка в буфер обмена с помощью QClipboard
интуитивно понятна и похожа на этап Drag в процедуре Drag&Drop. Заметим, что перед добавлением строки в буфер обмена мы отключаем обработчик сигнала dataChanged()
, а после подключаем его вновь:
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() ) );
}
}
Если бы мы этого не делали, то наше приложение фиксировало изменения в буфере обмена, которые само и спровоцировало.
Скачать пример работы с буфером обмена в Qt с помощью QClipboard
Anonymous:
хотелось бы увидеть как сделать тоже самое для MacOS, так как dataChanged() там не работает.
> On macOS and with Qt version 4.3 or higher, clipboard changes made by other applications will only be detected when the application is activated.
Здравствуйте. К сожалению, у меня нет возможности тестирования под Mac OS X. Однако в документации упоминается сигнал QClipboard::changed(QClipboard::Mode mode), для которого соответствующее ограничение не упоминается. С другой стороны, я допускаю, что это лишь неточность или просто неоднозначность в документации, поэтому без проверки выводы делать не могу.
Anonymous
хотелось бы увидеть как сделать тоже самое для MacOS, так как dataChanged() там не работает.
> On macOS and with Qt version 4.3 or higher, clipboard changes made by other applications will only be detected when the application is activated.