IT Notes

QClipboard: Использование буфера обмена в Qt

Возникают ситуации, когда в приложении необходимо реализовать прямой доступ к буферу обмена. Это может потребоваться в программах с особой логикой операций копирования-вставки, или во вспомогательных утилитах, увеличивающих эффективность и простоту работы на компьютере.

В Qt для взаимодействия с буфером обмена удобно использовать класс QClipboard. Он позволяет отслеживать изменения в буфере обмена и добавлять в него произвольную информацию.

Разработаем простое приложение, которое формирует список строк текста, добавленных в буфер обмена за время его работы. А затем позволяет по двойному клику перенести нужный текст из списка в буфер обмена:

qclipboard-demo-sample

Заголовочный файл 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

Похожие публикации

Комментарии

хотелось бы увидеть как сделать тоже самое для 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.

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), для которого соответствующее ограничение не упоминается. С другой стороны, я допускаю, что это лишь неточность или просто неоднозначность в документации, поэтому без проверки выводы делать не могу.