[완료] qt 에서 gif애니메이션을 QMovie로 구현하는 방법에 관해 궁금한게 있습니다.

pogusm의 이미지

사정상
gif파일(또는 리소스)을 QMovie로 직접 로드하는 대신에,
QByteArray 형태로 로드된 gif파일을 QMovie로 실행시키려 하였습니다.

1. 첫번째 시도 (이미지 잠깐 출력후, Segmentation fault 발생하면서 프로그램 다운)

QLabel *Movie = new QLabel(this);
 
QFile f("./image01.gif");
QByteArray b;
if (f.open(QFile::ReadOnly)) {
	b = f.readAll();
	f.close();
}
QBuffer buffer(&b);
 
QMovie *mov = new QMovie(&buffer);
Movie->setMovie(mov);
Movie->setGeometry(20, 20, 392, 225);
mov->start();

2. 두번째 시도 (Segmentation fault가 발생하지는 않지만, 이미지가 정지된 상태로 출력)

QLabel *Movie = new QLabel(this);
 
QFile f("./image01.gif");
QByteArray b;
if (f.open(QFile::ReadOnly)) {
	b = f.readAll();
	f.close();
}
QBuffer *buffer = new QBuffer(&b);
 
QMovie *mov = new QMovie(buffer);
Movie->setMovie(mov);
Movie->setGeometry(20, 20, 392, 225);
mov->start();

3. 세번째 시도 (정상적으로 이미지 출력 + 애니메이션 정상 작동)

QLabel *Movie = new QLabel(this);
 
QFile f("./image01.gif");
QByteArray *b;
if (f.open(QFile::ReadOnly)) {
	b = new QByteArray(f.readAll());
	f.close();
}
QBuffer *buffer = new QBuffer(b);
 
QMovie *mov = new QMovie(buffer);
Movie->setMovie(mov);
Movie->setGeometry(20, 20, 392, 225);
mov->start();

QByteArray b; 로 하느냐, QByteArray *b; 로 하느냐에 따라,
QBuffer buffer; 로 하느냐, QBuffer *buffer; 로 하느냐에 따라 결과가 달라지는데

그 원인은 무엇인가요?

수많은 삽질끝에 원하는 결과를 얻긴 하였지만..
왜 오류가 발생했었는지가 궁금합니다.

굽신굽신

klara의 이미지

코드의 전후가 필요합니다.
pointer를 인자로 받는 함수의 경우, 보통 해당 변수가 끝까지 살아있음이 보장되야 하는경우가 많습니다.
만약에 적으신 코드가 어떤 스코프안에 있어서 해당스코프를 벗어나서도 QMovie객체를 이용할려고 한다면, 스택에 있던 QFile객체나 QBuffer객체는 사라졌을 테니 문제가되겠지요.

pogusm의 이미지

main.cpp

#include <QtGui/QApplication>
#include "widget.h"
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
 
    return a.exec();
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
 
class QLabel;
 
namespace Ui {
    class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
 
	QLabel *Movie;
 
private:
    Ui::Widget *ui;
 
private slots:
	void on_pushButton_reload_clicked();
};
 
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
 
 
#include <QMovie>
#include <QBuffer>
#include <QFile>
#include <QLabel>
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
 
	Movie = new QLabel(this);
}
 
Widget::~Widget()
{
    delete ui;
}
 
 
void Widget::on_pushButton_reload_clicked()
{
 
	// 오류
	QFile f(":/image01.gif");
	QByteArray b;
	if (f.open(QFile::ReadOnly)) {
		b = f.readAll();
		f.close();
 
		QBuffer buffer(&b);
 
		QMovie *mov = new QMovie(&buffer);
		Movie->setMovie(mov);
		Movie->setGeometry(20, 20, 392, 225);
		mov->start();
	}
 
 
//	// 정상작동
//	QFile f(":/image01.gif");
//	QByteArray *b;
//	if (f.open(QFile::ReadOnly)) {
//		b = new QByteArray(f.readAll());
//		f.close();
 
//		QBuffer *buffer = new QBuffer(b);
 
//		QMovie *mov = new QMovie(buffer);
//		Movie->setMovie(mov);
//		Movie->setGeometry(20, 20, 392, 225);
//		mov->start();
//	}
 
}

굽신굽신굽신굽신

댓글 첨부 파일: 
첨부파일 크기
Package icon cachebrowser2.zip1.8 MB
klara의 이미지

이미 말씀드린대로 입니다. 스택에 생성된 QFile이나 QBuffer의 객체들은 해당 스코프안에서만 유효합니다.

pogusm의 이미지

1. new 연산자로 힙영역에 동적 할당된 객체는 해당 스코프가 끝나도? 유지되기때문에 QMovie로 작동될 수 있는건가요?

2. new로 할당된건 따로 delete하지 않으면 해당스코프를 벗어나도 유지된다... 인건가요?

추가--
3. 위의 소스에서 QByteArray *b; 나 QBuffer *buffer는 delete되지 않기 때문에.. on_pushButton_reload_clicked() 를 여러번 실행한다면... 메모리 누수 가능성이 있는건가요?
위 소스코드를 수정한다면... QByteArray *b; 나 QBuffer *buffer 를 Widget클래스의 멤버변수로 선언해주는게 좋은 방법일까요?

답변 정말 감사합니다.

klara의 이미지

1. 네
2. 네
3. 메모리 누수가 될수 있습니다. 멤버변수로 선언하는게 베스트인지 어떤지는 상황에 따라 다르지만 그것도 하나의 해결책이 될수 있습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.