PDA

View Full Version : Pixmap updating QLabel



Matt
17th August 2010, 18:09
I am new to Qt as of yesterday, and I was hoping someone would be able to help me with a problem. I am writing a program to act like XKCD (http://www.xkcd.com), but I can't get pixmap to update label. Here is a section, I will attach the full files in case they would help.



int val = 1;
XKCD::XKCD(QWidget *parent)
: QWidget(parent)
{
QString number;
QString png = ".png";
QString pics = "pics/";
number.setNum(val);
number.prepend(pics);
number.append(png);

QPixmap *original=new QPixmap(QString(number));
QPixmap image(original->scaled ( 1300,700, Qt::KeepAspectRatio, Qt::SmoothTransformation ));
QLabel *label = new QLabel(this);
label->setPixmap(image);
int pixwidth = image.width();
int labelwidth = (WIDTH - pixwidth) / 2;
label->setGeometry(labelwidth, SIZEY, pixwidth, 700);
}

void XKCD::OnPrev()
{
val--;
if (val < 1) {val = 0;}
QString number;
QString png = ".png";
QString pics = "pics/";
number = number.setNum(val);
number = number.prepend(pics);
number = number.append(png);
QPixmap *original=new QPixmap(QString(number));
QPixmap image= (original->scaled ( 1300, 600, Qt::KeepAspectRatio, Qt::SmoothTransformation ));
QLabel *label = new QLabel(this);
label->setPixmap(image);
int pixwidth = image.width();
int labelwidth = (WIDTH - pixwidth) / 2;
label->setGeometry(labelwidth, SIZEY, pixwidth, 700);
/* Debugging purposes */ std::cout << "Val is now: "<< val << ". The image path is now: " << number.toStdString() << "." << std::endl;
}

Hopefully someone can help me, I haven't found anything in documentation yet. Thanks for looking at my problem.

Attached are my project files.
5080
5081
5082

Edit: If it would be possible or easier to do using QImage, I am certainly open to that if someone could help me with it. My attempt to switch from QPixmap to QImage gave me a mile long set of errors that I couldn't find a workaround for.

Urthas
17th August 2010, 18:55
If
QLabel *label; in the header file is any indication, I'm fairly certain that you want to change
QLabel *label = new QLabel(this); to
label = new QLabel(this); in your constructor. If this is the case, then you should consider carefully why you are re-instantiating the label variable in onPrev().

Matt
17th August 2010, 19:01
Thanks for the reply.
A constructor is? Like I said, I'm new to Qt. I think it is the parent widget, but I'm not sure about that.
As to re-instantiating the variable in Prev, I thought they only last for a single function. Maybe I'm mistaken here, but isn't the parent widget one function and Prev, next, and random are different functions? Or is C++ just messing me up here?

Making the change doesn't seem to change any functionality though =/

onPrev and onNext still won't change the image when they are clicked. Is there a buffering feature for label?

Urthas
17th August 2010, 19:39
When you declare a variable in a header file, that variable is considered to be an integral part of any object instantiated from your class. Thus, it persists until the object is destroyed. These so-called "instance variables" are generally initialized in the constructor, a method with the same name as your class. When you say "QLabel *label = new QLabel()", you are in fact calling the default constructor (i.e., no parameters) of the QLabel class.

In C++ you can create a variable on the stack or on the heap. When you say "type *var = new type();", you are putting the variable on the heap, and even if you do this inside a method, the variable will persist. On the other hand, if you say "type var;" then you are putting the variable on the stack. If you do this inside a brace-delimited scope (such as a method), the variable will not persist or be visible outside that scope unless you take a pointer to it first. This conforms to the idea of a local variable.

Matt
17th August 2010, 19:44
I see, thanks. With a *, it lasts the whole program. Without, it is just a local variable. So i need to call the *label at some point, but can just call label afterwards.
Do you have any idea why the image wouldn't update though? The debugging line I put in works properly, it is like label(pixmap) is buffered and won't output anything even when I tell it to.
Perhaps making the other variables I am relying on heap variables would help, I'll try that.

Urthas
17th August 2010, 20:25
What do YOU get from running the following code?



label = new QLabel(this);
QPixmap pmap(QString("C:\\path\\to\\file.jpg")); // windows machine, hence escapes
if (pmap.isNull())
label->setText("Null pixmap!");
else
label->setPixmap(pmap);


At first, I got null pixmap, then I remembered the windows directory delimiters and I got my image in the label. Anyways, yeah, you might have a null pixmap for whatever reason.

Matt
17th August 2010, 20:33
When I run that, replacing the image obviously, it displays the image I want it to.

If I had a null pixmap in one of the lower functions (onPrev, etc), would it display a null or just continue to show the same thing. If it continues to show the same thing, that is my problem.

Edit: A little testing with and pixmap.isNull() has determined that my image isn't null in any of my functions. It just refuses to update to the new filepath.

Urthas
17th August 2010, 20:40
If I had a null pixmap in one of the lower functions (onPrev, etc), would it display a null or just continue to show the same thing.

It would display absolutely nothing at all, or in the case of my example code, "Null Pixmap!" (tested). A null pixmap has no content, but QLabel::setPixMap() wipes out the label's previous pixmap.

Matt
17th August 2010, 20:48
QString number;
QString png = ".png";
QString pics = "pics/";
number = number.setNum(val);
number = number.prepend(pics);
number = number.append(png);
QPixmap *original=new QPixmap(QString(number));
QPixmap image= (original->scaled ( 1300, 600, Qt::KeepAspectRatio, Qt::SmoothTransformation ));
label = new QLabel(this);
label->setPixmap(image);

So in this code, label should be cleared and replaced with the new value of image, which is clearly not happening. Could the problem be in QPixmap *original? Removing the * from that variable makes it refuse to compile, but could the * be preventing the value of original from updating? If so, is there a way to get rid of the * safely without giving errors about converting QPixmap* to QPixmap?

Urthas
17th August 2010, 21:03
How about I just show you what worked for me?

First, here is the header file:


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QWidget>

class QLabel;
class QPushButton;

class MainWindow : public QWidget
{
Q_OBJECT

public:
MainWindow(QWidget *parent = 0);
~MainWindow();

public slots:
void updatePixmap();

private:
QPixmap pmap1, pmap2;
QLabel *label;
QPushButton *button;
int numUpdates;
};

#endif // MAINWINDOW_H


Now, here is the .cpp file:



#include "mainwindow.h"
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>

MainWindow::MainWindow(QWidget *parent)
: QWidget(parent), numUpdates(0)
{
pmap1 = QPixmap("C:\\path\\to\\image1.jpg");
pmap2 = QPixmap("C:\\path\\to\\image2.jpg");
label = new QLabel();
label->setPixmap(pmap1);

button = new QPushButton("Update!");
connect(button, SIGNAL(clicked()), this, SLOT(updatePixmap()));

QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(label);
layout->addWidget(button);
layout->setSizeConstraint(QLayout::SetFixedSize);
setLayout(layout);
}

void MainWindow::updatePixmap()
{
++numUpdates % 2 ? label->setPixmap(pmap2) : label->setPixmap(pmap1);
}

MainWindow::~MainWindow()
{

}


update: images now toggle back and forth instead of being a one-shot deal :p

Urthas
17th August 2010, 21:05
label should be cleared and replaced with the new value of image, which is clearly not happening.


But but but you are destroying the previous label entirely...

What happens if you comment out line 9?

Matt
17th August 2010, 21:11
If I comment out line 9, I get an error. But that line is only for resizing the window, it doesn't affect anything else.

I am reading over your first post trying to integrate it into my system.

Edit: Thank you very much, that did it. When I removed the code that destroyed label, it solved the problem. I will definitely remember this in the future.