Название: Glass (эффект "затемнения" виджета при длительной операции)
Отправлено: yaroslav429 от Декабрь 29, 2010, 03:22
Возникла необходимость отображать пользователю статус работы приложения при длительных расчетах, да так, что бы виджет, в котором обновляется информация был недоступен. Написал небольшой класс (пример использования во вложении), который с горем-пополам выполняет данную задачу: указанный виджет затемняется с возможностью отображения текста и прогрессбара (по надобности). Сильно не пинайте, а лучше, по возможности, укажите грубые ошибки, подскажите как улучшить. Надеюсь, что кому-то пригодится ;) Небольшое описание публичных методов : Glass(QString message = "", int stepCount = 0) - если message пустая, текста не будет; если stepCount пустая - прогрессбара. void init(QWidget *parent) - установка затемнения на виджет parent void hideAndDelete() - скрытие и удаление затемнения void infinitely(QString text) - "бесконечное" прокручивание прогрессбара, если количество итераций зарание не известно. void setAnimationDuration(int duration) - длительность анимации появления и скрытия (по умолчанию 300) void setMessage(QString message) - установка текста void setStepCount(int stepCount) - установка максимума в прогрессбаре Ну и собственно : Glass.h#ifndef GLASS_H #define GLASS_H
#include <QObject> #include <QEvent> #include <QLabel> #include <QProgressBar> #include <QDebug> #include <QColor> #include <QPropertyAnimation>
class Glass : public QObject { Q_OBJECT public: Glass(QString message = "", int stepCount = 0); ~Glass(); void setMessage(QString message); void setStepCount(int stepCount); void setAnimationDuration(int duration); void init(QWidget *parent); void hideAndDelete(); void infinitely(QString text);
protected: QLabel *glass; QLabel *infoText; QProgressBar *progressBar; bool eventFilter(QObject *object, QEvent *event);
private: bool _haveMessage, _haveProgress; int _stepCount, _animationDuration; void createControls(); void positioning(); QWidget *_parent;
signals: void initailized(int);
private slots: void afterInit();
public slots: void nextStep(QString text);
};
#endif // GLASS_H
Glass.cpp#include "glass.h" #include <QApplication>
Glass::Glass(QString message, int stepCount) { _haveMessage = ((!message.isEmpty()) ? true : false); _haveProgress = ((stepCount > 0) ? true : false); createControls(); if(_haveMessage) setMessage(message); if(_haveProgress) setStepCount(stepCount); }
void Glass::createControls() { glass = new QLabel(); glass->hide(); if(_haveMessage) { infoText = new QLabel(0); infoText->hide(); infoText->setAlignment(Qt::AlignCenter); infoText->setWordWrap(true); infoText->setStyleSheet("color:#fff;"); } if(_haveProgress) { progressBar = new QProgressBar(0); progressBar->hide(); progressBar->setObjectName(QString::fromUtf8("progressBar")); progressBar->setValue(0); progressBar->setMaximum(0); progressBar->setAlignment(Qt::AlignCenter); progressBar->setTextVisible(true); progressBar->setOrientation(Qt::Horizontal); progressBar->setInvertedAppearance(false); progressBar->setTextDirection(QProgressBar::TopToBottom); progressBar->setFormat("%p% (%v/%m)"); } _animationDuration = 300; }
void Glass::setMessage(QString message) { if(_haveMessage) infoText->setText(message); }
void Glass::setStepCount(int stepCount) { if(_haveProgress) progressBar->setMaximum(stepCount); }
void Glass::setAnimationDuration(int duration) { _animationDuration = duration; }
Glass::~Glass() { glass->setMaximumSize(0, 0); glass->hide(); glass->deleteLater(); }
void Glass::hideAndDelete() { if(_haveMessage) infoText->hide(); if(_haveProgress) progressBar->hide(); if(_haveMessage) infoText->deleteLater(); if(_haveProgress) progressBar->deleteLater(); QPropertyAnimation *animation = new QPropertyAnimation(glass, "geometry"); animation->setDuration(_animationDuration); animation->setEasingCurve(QEasingCurve::InCubic); animation->setStartValue(glass->geometry()); animation->setEndValue(QRect((glass->geometry().x()+glass->geometry().width())/2, (glass->geometry().y()+glass->geometry().height())/2, 0, 0)); animation->start(); connect(animation, SIGNAL(finished()), this, SLOT(deleteLater())); }
bool Glass::eventFilter(QObject *object, QEvent* event) { if(object != this && object != _parent) return false; if(event->type() == QEvent::Resize) { glass->resize(glass->parentWidget()->size()); glass->move(0, 0); positioning(); return true; } glass->setFocus(); return false; }
void Glass::init(QWidget *parent) { _parent = parent; qApp->installEventFilter(this); glass->setStyleSheet("background-color: rgba(90, 90, 90, 127);"); glass->setParent(parent); glass->show(); qApp->installEventFilter(this); QPropertyAnimation *animation = new QPropertyAnimation(glass, "geometry"); animation->setDuration(_animationDuration); animation->setEasingCurve(QEasingCurve::InCubic); animation->setStartValue(QRect(parent->geometry().width()/2, parent->geometry().height()/2, 0, 0)); animation->setEndValue(QRect(0, 0, parent->geometry().width(), parent->geometry().height())); animation->start(); connect(animation, SIGNAL(finished()), this, SLOT(afterInit())); }
void Glass::afterInit() { _stepCount = 0; if(_haveMessage) { infoText->setParent(_parent); infoText->show(); } if(_haveProgress) { _stepCount = progressBar->maximum(); progressBar->setParent(_parent); progressBar->show(); } positioning(); emit initailized(_stepCount); }
void Glass::positioning() { int pww = glass->parentWidget()->geometry().width(), pwh = glass->parentWidget()->geometry().height(); if(_haveProgress) { progressBar->setGeometry(pww/4, pwh/2-10, pww/2, 21); qDebug() << progressBar->parentWidget() << progressBar->geometry(); } if(_haveMessage) infoText->setGeometry(20, pwh/2-31, pww-40, 21); qDebug() << "positioning" << _haveProgress << _haveMessage; }
void Glass::nextStep(QString text) { if(_haveProgress) progressBar->setValue(progressBar->value()+1); if(_haveMessage) setMessage(text); qApp->processEvents(); }
void Glass::infinitely(QString text) { qDebug() << _haveProgress << _haveMessage; if(!_haveProgress) { progressBar = new QProgressBar(0); progressBar->hide(); progressBar->setObjectName(QString::fromUtf8("progressBar")); progressBar->setValue(0); progressBar->setMaximum(0); progressBar->setAlignment(Qt::AlignCenter); progressBar->setTextVisible(false); progressBar->setOrientation(Qt::Horizontal); progressBar->setInvertedAppearance(false); progressBar->setParent(_parent); } progressBar->setMinimum(0); progressBar->setMaximum(0); progressBar->startTimer(0); if(!_haveMessage) { infoText = new QLabel(0); infoText->hide(); infoText->setAlignment(Qt::AlignCenter); infoText->setWordWrap(true); infoText->setStyleSheet("color:#fff;"); infoText->setParent(_parent); } infoText->setText(text); infoText->show(); progressBar->show(); _haveProgress = true; _haveMessage = true; positioning(); }
Пример использования : // например, в слоте для QPushButton::clicked() ... Glass *glass = new Glass("Step #1", 152); glass->setAnimationDuration(200); connect(glass, SIGNAL(initailized(int)), this, SLOT(steps(int))); glass->init(qobject_cast<QWidget *>(sender()->parent())); ...
void MainWindow::steps(int steps) { Glass *glass = qobject_cast<Glass *>(sender()); if(steps > 0) { QTime time; time.start(); for(int i=0; i<steps; ) { if(time.elapsed() > 20) { time.start(); ++i; glass->nextStep(QString("Step #%1").arg(i+1)); } } } else { QTime time; time.start(); glass->infinitely("loading..."); while(time.elapsed() < 5000) { qApp->processEvents(); } } glass->hideAndDelete(); }
Название: Re: Glass (эффект "затемнения" виджета при длительной операции)
Отправлено: navrocky от Январь 07, 2011, 15:57
Идея хорошая, мне нравится :)
Код немного кривоват, надо бы рихтануть, но у меня к сожалению сейчас нет времени :( Может кто другой поможет?
ЗЫЖ Я вот тут подумал, а не сорганизовать ла нам свою либу по дополнениям к Qt по аналогии с libqxt?
Основное требование к ней, чтобы она была легковесной и с возможностью выдирать определенные классы для своего проекта (то бишь минимум внутренних зависимостей)...
Разместить ее на каком-нить гуглокоде или житхабе...
Название: Re: Glass (эффект "затемнения" виджета при длительной операции)
Отправлено: _govorilka от Январь 14, 2011, 09:59
ЗЫЖ Я вот тут подумал, а не сорганизовать ла нам свою либу по дополнениям к Qt по аналогии с libqxt?
Основное требование к ней, чтобы она была легковесной и с возможностью выдирать определенные классы для своего проекта (то бишь минимум внутренних зависимостей)...
Разместить ее на каком-нить гуглокоде или житхабе...
Начал делать небольшую либу: http://code.google.com/p/fireworks/ (http://code.google.com/p/fireworks/) Буду выкладывать сюда общие куски из проекта, которые делаю на работе.
Название: Re: Glass (эффект "затемнения" виджета при длительной операции)
Отправлено: GreatSnake от Январь 14, 2011, 10:31
2 yaroslav429 Не мешало бы все аргументы "QString" поменять на "const QString&" и делать так всю оставшуюся жизнь)
Название: Re: Glass (эффект "затемнения" виджета при длительной операции)
Отправлено: navrocky от Январь 17, 2011, 20:26
Начал делать небольшую либу: http://code.google.com/p/fireworks/ (http://code.google.com/p/fireworks/)
Буду выкладывать сюда общие куски из проекта, которые делаю на работе.
Ну это замечательно, но либа немного не в тему: >> Framework for creating GUI for embedded system based on Qt library >> This framework based on QtCore library, but not used QtGui Embedded это не общее направление. И название Fireworks ни о чем не говорящее.. Кстати зачем делать свой Embedded когда есть Qt Embedded?
Название: Re: Glass (эффект "затемнения" виджета при длительной операции)
Отправлено: _govorilka от Январь 19, 2011, 12:07
Кстати зачем делать свой Embedded когда есть Qt Embedded?
В Qt Embedded не хватает гибкости. Проект Lighthouse еще пока живет только в лаборатории и не является частью "официального" Qt. Но это тема для отдельной ветки на форуме. Тему сейчас подниму, возможно кому-то будет интересно...
|