I'm trying to program my own progressbar and this I already got working. Each time the percent value changes the bar changes too, so that the bar displays the right progress.
Now my problem is, that the bar always (of course) jumps to the next state and there is no smooth transition between it. Now my question is, how can I make a smooth transition between the stages?
Informations:
I know the fpscount of the game and the position + scale of the bar. And I'm programming in java (I think this information is unnecessary :P)
A general answer, not language specific.
Instead of directly setting the width, you could increase each frame the width until its the desired width/percentage.
Let's assume you have the function bar.setWidth(val) to set the width of your progress bar.
Let this be your update loop (ran at 60FPS):
update {
...
...
double percentageLoaded; // this is your parameter probably
static const int incrementStep = 1; // increase this for faster animation
// Get the width of the bar for the current percentage
int desiredWidth = percentageLoaded * bar.totalWidth;
if(bar.currentWidth < desiredWidth) {
bar.currentWidth += incrementStep;
}
}
There are still a few things you have to check if your incrementStep is larger than 1. (eg: don't set the bar width larger than 100%)
Here is a small drawing, maybe it helps you understand better. In this example the increment step is 1px, the bar width is 4px and the loading was set to be 50% complete, this means that your bar should be 2px in width.
Related
i have an application in qt that loads an image. The user can set a cross by moving the slider with setPixel(). If he decrements the slider, the cross should become smaller and the original pixel should be displayed.
But unfortunately nothing happens when I decrement the slider. The cross keeps its maximum size.
The function, that sets the Pixel
void ImageViewer::applyExampleAlgorithm(int kreuzBreite)
{
if(image!=NULL)
{
for(int i=0;i<((kreuzBreite*std::min(image->width(), image->height())/ 100) / 2);i++)
{
image->setPixelColor(image->width()/2+i,image->height()/2,QColor(255,0,0,0));
image->setPixelColor(image->width()/2-i,image->height()/2,QColor(255,0,0,0));
image->setPixelColor(image->width()/2,image->height()/2+i,QColor(255,0,0,0));
image->setPixelColor(image->width()/2,image->height()/2-i,QColor(255,0,0,0));
}
}
updateImageDisplay();
renewLogging();
}
My Slider
QSlider *slider1 = new QSlider(Qt::Horizontal,0);
slider1->setRange(0,100);
connect(slider1, SIGNAL(valueChanged(int)),this, SLOT(applyExampleAlgorithm(int)));
As you can see, the value changes, but my cross does not.
I think I have to save the original pixel and rewrite it, as soon as the red cross disappears at this point. But I dont really know how.
When the slider value decreases, your function only "draw" a smaller red cross in the bigger one that was drawn before. You can store the original image in a different variable. Then, before drawing the red cross, restore to the original image.
I'm using QSlider object in my Qt application and I want to get the position of the slider bar upon moving it. I tried using pos() function, but it always returns QPoint() with the same values of x and y (i suppose it returns position of top left corner of slider):
ui->horizontalSlider->pos();
Then I tried dividing the slider width by 100 and adding that value multiplicated by slider value() to most-left position:
SliderStep = ui->horizontalSlider->width()/100;
(ui->horizontalSlider->value()) * SliderStep + ui->horisontalSlider->geometry().x();
It kind of works for me, but values are not very accurate since SliderStep has to be double and coordinates are integer values. I always noticed that I can get slider values by either using value() or sliderPosition() functions since they always return the same value for me:
qDebug()<<ui->horizontalSlider->sliderPosition();
qDebug()<<ui->horizontalSlider->value();
So my question is, is there a more convinient or "right" way to get coordinates of a slider bar? What's the difference between those two functions? Any help is appreciated.
I could use a label to do it, but I was wondering if there was a simpler way.
I already make the color of the progress bar red when it exceeds 100% of the value I'm comparing it to and green again when the value is below that, but the bar itself won't show any number larger than 100%.
For example if a is 40 and b is 80, b is 200% of a, so the progress bar should display the number 200%.
Change the number format from percent of total to a value, leaving the '%' as a suffix:
QProgressBar *progressBar = new QProgressBar;
progressBar->setRange(0, 200);
progressBar->setFormat("%v%");
progressBar->setValue(150);
This should display "150%" next to the progress bar.
So, this is my problem: I have this very big image, and I want to show only a specific part of it. After the user pressing a specific key I want the image to move, showing another part of it. The transition from one part of the image to another have to be smooth, animated.
I tried using a QLabel to show the image but it always shows the center of the image, and I do not really know how to make the animation. What would you guys suggest?
Interesting question. Here is something I just tested and seems to work.
Add a QGraphicsView with dimensions the dimensions of the part of the image you want to display, eg 100x100. Create a QGraphicsScene and add it to the view:
QGraphicsScene* pScene = new QGraphicsScene(this);
ui->graphicsView->setScene(pScene);
Now add your image into the scene. In my case I has an image in my resource file. The trick is to set the sceneRect to the position you want to display. I wanted to display an 100x100 part of the image starting from 0,300 :
pItem = pScene->addPixmap(QPixmap::fromImage(QImage(":/photos/image")));
pScene->setSceneRect(0,300,100,100);
In order to test the smooth moving I added a button which when clicked is triggering a slot called move. This slot simply updates the sceneRect. In my simple example I just move the image 100 pixels right. In a real world scenario you could also move it diagonally or vertically and check the image limits.
void move()
{
for (unsigned i=currentX; i<currentX + 100; i++)
{
ui->graphicsView->scene()->setSceneRect(i,300,100,100);
qApp->processEvents();
}
currentX += 100;
}
Notice the currentX variable. It is nothing more than the last image position. Also we must call the processEvents in order to "see" the image moving smoothly.
You could use QPixmap::copy( int x, int y, int width, int height ) to copy a region of the image and display that.
Few options:
Try using a Q3CanvasSprite (within in a Q3Canvas). It is designed more for splitting one image into multiple ones but not for animating between them. You could try abusing it and declaring (say) 100 frames (10 per digit, which would be used as animation steps) or just use the move() method.
Try QGraphicsPixmapItem::setOffset() (within a QGraphicsScene). This might be overkill as QGraphicsScene is made for large number of images).
I'm not sure, but maybe this can be done with QStateMachine and QAbstractAnimation.
I have created my own class by extending QGraphicsItem and I want to make it so that when someone does a wheel even while over this item, it scales.
This way, i can have multiple items in a scene, and scale each of them in and out as I please.
The problem is, I want the item to scale under the mouse cursor, much like google maps does. That is, a move forward will keep panning the image and scaling it, so taht the area in the vicinity around my mouse pointer is always in view.
void ImagePixmapItem::wheelEvent ( QGraphicsSceneWheelEvent * event ){
update();
qreal factor = 1.2;
if (event->delta() < 0)
factor = 1.0 / factor;
scale(factor, factor);
scaleFactor *=factor;
this->scene()->setSceneRect(0,0,this->boundingRect().width(), this->boundingRect().height());
}
This is the code I am using to do the scale. The problem is, it always seems to be scaling from the top left corner. Well, this is undesirable, beacuse if I scale in or out too much, eventually my area of interest around the mouse pointer has moved off the screen, and I have to either scroll manually or pan to the location, zoom, pan, etc, until i get to the desired level.
I tried to use the QGraphicsItem::setTransformOriginPoint, but no matter what values I put in there, it still seems to scale and such from the top left.
What can I add to that code I posted to get the desired effect?
I have achieved similar functionality in my Image-Manipulation application (scaling the view and having the area under my mouse stay in place and visible) but I scale the whole graphics-view not a specific item, so I don't know if this code can solve your problem.
Anyway, this is what I do in the constructor of my subclassed QGraphicsView (after I set the scene):
setTransformationAnchor(AnchorUnderMouse);
setResizeAnchor(AnchorViewCenter);
I also use the above functions, after each call to:
MyGraphicsView->setTransform(transform);
I'm not sure if this can help you, but I hope so.