Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Qt и кроссплатформенное программирование С/С++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 28.01.2012, 02:12   #1
FYBVFPFYBC
Пользователь
 
Регистрация: 19.01.2010
Сообщений: 19
По умолчанию Нужен нетривиальный виджет QT

Здравствуйте.
Виджет, на который транслируется рандомная область (заданного размера) графического изображения с большой частотой обновления (несколько раз в секунду). На виджете связан сигнал-клик со слотом-url.
Какой стандартный виджет лучше взять за шаблон и вообще какими средствами QT это можно реализовать?
FYBVFPFYBC вне форума Ответить с цитированием
Старый 28.01.2012, 18:34   #2
FYBVFPFYBC
Пользователь
 
Регистрация: 19.01.2010
Сообщений: 19
По умолчанию

Вот веб-версия этого виджета.
anm.fm
Рандомная область - это область на плоскости jpg-файла.

Последний раз редактировалось FYBVFPFYBC; 28.01.2012 в 18:48.
FYBVFPFYBC вне форума Ответить с цитированием
Старый 02.02.2012, 06:36   #3
FYBVFPFYBC
Пользователь
 
Регистрация: 19.01.2010
Сообщений: 19
По умолчанию

Вот что получилось:

Код:
//QImage mainimage("...path\\mainimage.jpg"); //800x800px
//QLabel *picturelabel;

//threads.h
...
class ANThread : public QThread
{
     Q_OBJECT

protected:
        
        QImage image;
	QPicture picture;
	QPainter painter;
	
        void run()
	{
		int x = 0; int y = 0;
		srand( (unsigned)time(NULL) );
		while(true)
		{
			x  = rand() % 720;
			y  = rand() % 720;
			mainimage= mainimage.copy( x, y, 80, 80 );
			painter.begin(&picture);
			painter.drawImage(QPoint(0,0), mainimage);
			painter.end();
			picturelabel->setPicture(picture);
			Sleep(10);
		}
	exec();
	}
};

//main.cpp
int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	mainwindow w;
	picturelabel = new QLabel(&w);
	picturelabel->setGeometry( 495,330,80,80 );
	
	ANThread *anthread = new ANThread();
	anthread->start();
	
	w.show();
	return a.exec();
}
Работает недолго. Особенно быстро вылетает при сворачивании/разворачивании окна, переключении между окнами.

Ошибка:

Код:
QIODevice::read: WriteOnly device
QIODevice::read: WriteOnly device
QIODevice::read: WriteOnly device
QIODevice::read: WriteOnly device
QIODevice::read: WriteOnly device
ASSERT: "qint32(s.device()->pos() - strm_pos) == len" in file image\qpicture.cpp, line 940
QWidget::repaint: Recursive repaint detected
main.exe привело в действие точку остановка
З.Ы. Это первый опыт QT и ООП вообще.
FYBVFPFYBC вне форума Ответить с цитированием
Старый 03.02.2012, 14:06   #4
FYBVFPFYBC
Пользователь
 
Регистрация: 19.01.2010
Сообщений: 19
По умолчанию

Подсказали, что QT рисует только в основном потоке. Написала вот что:
Код:
QImage mainimage("...path\\mainimage.jpg");
QPicture pic;
Код:
//worker.h
class Worker : public QObject
{
    Q_OBJECT
private:
    const int maxpix;
        int x,y;
        
        QImage image;
        QPainter painter;
 
public:
    Worker ( QObject *parent = 0 );
 
public slots:
    void getnewpic();
 
signals:
    void newpicSignal();
};
Код:
//worker.cpp
Worker::Worker(QObject *parent) : QObject(parent), pix(720), x(0), y(0)
{
    srand( (unsigned)time(NULL) );
}
void Worker::getnewpic()
{
        x  = rand() % pix;
        y  = rand() % pix;
        image = mainimage.copy( x, y, 80, 80 );
        painter.begin( &pic );
        painter.drawImage( QPoint(0,0), image );
        painter.end();
}
Код:
//label.h
class PicLabel: public QLabel
{
    Q_OBJECT
 
protected:
        QPicture localpic;
 
public:
    PicLabel(QWidget *parent = 0);
 
public slots:
    void picreset( QPicture );
};
Код:
//label.cpp
PicLabel::PicLabel( QWidget *parent )
{
    setGeometry( 495, 330, 80, 80 );
}
void PicLabel::picreset( QPicture localpic )
{
        setPicture( localpic );
}
Код:
//main.cpp
int main(int argc, char *argv[])
{
        QApplication a( argc, argv );
        mainwindow w;
        
        PicLabel label;
        Worker worker;
        QThread thread;
        QTimer timer;
 
        timer.setInterval( 100 );
        timer.start();
        
        QObject::connect( &timer, SIGNAL( timeout() ), &worker, SLOT( getnewpic() ));
        QObject::connect( &worker, SIGNAL( newpicSignal() ), &label, SLOT( picreset( pic ) ));
 
        worker.moveToThread(&thread);
        thread.start();
        
        w.show();
        return a.exec();
}
Object::connect: No such slot PicLabel:icreset( pic )
В чём ошибка?
FYBVFPFYBC вне форума Ответить с цитированием
Старый 05.02.2012, 22:47   #5
FYBVFPFYBC
Пользователь
 
Регистрация: 19.01.2010
Сообщений: 19
По умолчанию

Кажется я немного разобралась с paintEvent и тем недееспособным кодом, что выше. Все, участвующие в этом мучении Qimage и QPicture объявляю глобальными через extern в хедере, дублируя в cpp, т.к... ну вы поняли.
main.cpp запускает таймер, коннектит timeout с расчётом следующей картинки. После расчёта возвращается сигнал, соединённый с repaint().
Код:
//main
{...
        MyLabel label;
        TGetnew Getnew;
        QThread thread;
        QTimer timer;
        timer.setInterval(100);
        timer.start();
        QObject::connect( &timer, SIGNAL( timeout()), &Getnew, SLOT( getnew()));
        QObject::connect( &Getnew, SIGNAL( renew() ), &label, SLOT( reset()));
        Getnew.moveToThread(&thread);
        thread.start();
...}
 
//Расчёт следующей картинки посыл сигнала, связанного с repaint()
void TGetnew::getnew()
{
        x  = rand() % pix;
        y  = rand() % pix;
        image = mainimage.copy( x, y, 80, 80 );
        emit renew();
}
 
//Сам repaint() и paintEvent
void MyLabel::reset()
{
        repaint();
}
void MyLabel::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.begin(this);
    painter.drawImage(QPoint(0,0), image);
    painter.end();
    QLabel::paintEvent(event);
}
Открывается основное окно и... ничего не происходит. Вот ещё раз то, что примерно должно произойти: anm.fm
FYBVFPFYBC вне форума Ответить с цитированием
Старый 06.02.2012, 23:48   #6
FYBVFPFYBC
Пользователь
 
Регистрация: 19.01.2010
Сообщений: 19
По умолчанию

Сделать mainwindow парентом и в paintEvent() не вызывать родительский paintEvent(). Вопрос решён.
FYBVFPFYBC вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Виджет для публичной страницы ВКонтакте Lawilet HTML и CSS 0 16.10.2011 00:54
Виджет AnKor94 Общие вопросы Delphi 2 18.01.2011 20:23
Виджет комментариев vkontakte kpachbiu JavaScript, Ajax 8 17.01.2011 18:04
виджет Calendar Clock syperman96 Помощь студентам 1 01.12.2010 22:45