Чтение онлайн

ЖАНРЫ

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

01 ImageWindow::ImageWindow

02 {

03 imageLabel = new QLabel;

04 imageLabel->setBackgroundRole(QPalette::Dark);

05 imageLabel->setAutoFillBackground(true);

06 imageLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);

07 setCentralWidget(imageLabel);

08 createActions;

09 createMenus;

10 statusBar->showMessage(tr("Ready"), 2000);

11 connect(&thread, SIGNAL(transactionStarted(const QString &)),

12 statusBar, SLOT(showMessage(const QString &)));

13 connect(&thread, SIGNAL(finished),

14 this, SLOT(allTransactionsDone));

15 setCurrentFile("");

16 }

Интересной

частью конструктора ImageWindow являются два соединения сигнал—слот. В обоих случаях сигнал генерируется объектом TransactionThread, который мы вскоре рассмотрим.

01 void ImageWindow::flipHorizontally

02 {

03 addTransaction(new FlipTransaction(Qt::Horizontal));

04 }

Слот flipHorizontally создает транзакцию зеркального отражения и регистрирует ее при помощи закрытой функции addTransaction. Функции flipVertically, resizeImage, convertTo32Bit, convertTo8Bit и convertTo1Bit реализуются аналогично.

01 void ImageWindow::addTransaction(Transaction *transact)

02 {

03 thread.addTransaction(transact);

04 openAction->setEnabled(false);

05 saveAction->setEnabled(false);

06 saveAsAction->setEnabled(false);

07 }

Функция addTransaction добавляет транзакцию в очередь транзакций вторичного потока и отключает команды Open, Save и Save As на время обработки транзакций.

01 void ImageWindow::allTransactionsDone

02 {

03 openAction->setEnabled(true);

04 saveAction->setEnabled(true);

05 saveAsAction->setEnabled(true);

06 imageLabel->setPixmap(QPixmap::fromImage(thread.image));

07 setWindowModified(true);

08 statusBar->showMessage(tr("Ready"), 2000);

09 }

Слот allTransactionsDone вызывается, когда очередь транзакций TransactionThread становится пустой.

Теперь давайте рассмотрим класс TransactionThread:

01 class TransactionThread : public QThread

02 {

03 Q_OBJECT

04 public:

05 void addTransaction(Transaction *transact);

06 void setImage(const QImage &image);

07 QImage image;

08 signals:

09 void transactionStarted(const QString &message);

10 protected:

11 void run;

12 private:

13 QMutex mutex;

14 QImage currentImage;

15 QQueue<Transaction *> transactions;

16 };

Класс TransactionThread содержит

список обрабатываемых транзакций, которые выполняются по очереди в фоновом режиме.

01 void TransactionThread::addTransaction(Transaction *transact)

02 {

03 QMutexLocker locker(&mutex);

04 transactions.enqueue(transact);

05 if (!isRunning)

06 start;

07 }

Функция addTransaction добавляет транзакцию в очередь транзакций и запускает поток транзакции, если он еще не выполняется. Доступ к переменной—члену transactions защищается мьютексом, потому что главный поток мог бы ее модифицировать функцией addTransaction во время прохода по транзакциям transactions вторичного потока.

01 void TransactionThread::setImage(const QImage &image)

02 {

03 QMutexLocker locker(&mutex);

04 currentImage = image;

05 }

06 QImage TransactionThread::image

07 {

08 QMutexLocker locker(&mutex);

09 return currentImage;

10 }

Функции setImage и image позволяют главному потоку установить изображение, для которого будут выполняться транзакции, и получить обработанное изображение после завершения всех транзакций. И вновь мы защищаем доступ к переменной—члену при помощи мьютекса.

01 void TransactionThread::run

02 {

03 Transaction *transact;

04 forever {

05 mutex.lock;

06 if (transactions.isEmpty) {

07 mutex.unlock;

08 break;

09 }

10 QImage oldImage = currentImage;

11 transact = transactions.dequeue;

12 mutex.unlock;

13 emit transactionStarted(transact->message);

14 QImage newImage = transact->apply(oldImage);

15 delete transact;

16 mutex.lock;

17 currentImage = newImage;

18 mutex.unlock;

19 }

20 }

Функция run просматривает очередь транзакций и по очереди выполняет все транзакции путем вызова для них функции apply.

После старта транзакции мы генерируем сигнал transactionStarted с сообщением, выводимым в строке состояния приложения. Когда обработка всех транзакций завершается, функция run возвращает управление и QThread генерирует сигнал finished.

Поделиться с друзьями: