In Qt, how to perform hide operation in smoother way? - qt

In Qt, whenever a widget is set to hide, I want to perform the action in smooth way.
Is there any standard function for that?

Heres example for show and hide button:
void MainWindow::hideButton(){
QGraphicsOpacityEffect* fade_effect = new QGraphicsOpacityEffect(this);
ui->pushButton->setGraphicsEffect(fade_effect);
QPropertyAnimation *animation = new QPropertyAnimation(fade_effect, "opacity");
animation->setEasingCurve(QEasingCurve::InOutQuad);
animation->setDuration(5000);
animation->setStartValue(1);
animation->setEndValue(0.01);
animation->start(QPropertyAnimation::DeleteWhenStopped);
}
void MainWindow::showButton(){
QGraphicsOpacityEffect* fade_effect = new QGraphicsOpacityEffect(this);
ui->pushButton->setGraphicsEffect(fade_effect);
QPropertyAnimation *animation = new QPropertyAnimation(fade_effect, "opacity");
animation->setEasingCurve(QEasingCurve::InOutQuad);
animation->setDuration(5000);
animation->setStartValue(0.01);
animation->setEndValue(1.0);
animation->start(QPropertyAnimation::DeleteWhenStopped);
}

Use the animation framework and set the geometry to 0,0 for the height and width, when you restore it just set it back to the previous height and width value. There's various easing effects in there for you to use as you do it, and a few code examples.

Related

gif image in QLabel

I want to add a gif animated image in QLabel that add into the QGraphicsScene.
My code is here:
QLabel *lbl = new QLabel;
QMovie *mv = new QMovie(":/Images/sun.gif");
mv->start();
lbl->setWindowFlags(Qt::FramelessWindowHint);
lbl->setMask((new QPixmap(":/Images/sun.gif"))->mask()); // for create transparent for QLabel image
lbl->setMovie(mv);
lbl->setGeometry(10,10,10,10);
scene.addWidget(lbl);
but when I run that it will transparent with first frame of that gif and when the gif is running the photo will not show completely and it will run with transparented area in the first frame.
How can I solve that?
Thanks
The problem is that QLabel has window background by default. You're trying to remove it by do it incorrectly:
FramelessWindowHint doesn't make sense here, since it's only used for top level widgets, and a widget added to scene is technically hidden and doesn't have system window frame. This line should be removed.
setMask does exactly what you describe it does. Since QPixmap is not animated, its mask is the alpha mask of the first frame of animation. And you permanently apply this mask to the label. It's not surpising that it works, but obviously it's not what you want. This line should also be removed.
setGeometry line is incorrect. It prevents picture from being visible for me. Label has good size by default and there is no need for setGeometry. If you want to scale or move the item on the scene, you can do it after addWidget as for any other QGraphicsItem. E.g. addWidget(lbl)->setPos(10, 10).
The magic bullet you need is WA_NoSystemBackground. It disables background painting for QLabel completely. So, the full code would be:
QLabel *lbl = new QLabel;
QMovie *mv = new QMovie("c:/tmp/sun.gif");
mv->start();
lbl->setAttribute(Qt::WA_NoSystemBackground);
lbl->setMovie(mv);
scene.addWidget(lbl);
It works fine for me. However I consider it over-complicated. You should not use proxy widgets in scene unless necessary. You can easily add a movie using QMovie and QGraphicsPixmapItem and switching pixmaps as movie frames change. I wrote a convenient class for this:
Header:
class GraphicsMovieItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
public:
GraphicsMovieItem(QGraphicsItem* parent = 0);
void setMovie(QMovie* movie);
private:
QMovie* m_movie;
private slots:
void frameChanged();
};
Source:
GraphicsMovieItem::GraphicsMovieItem(QGraphicsItem *parent)
: QGraphicsPixmapItem(parent), m_movie(0) {
}
void GraphicsMovieItem::setMovie(QMovie *movie) {
if (m_movie) {
disconnect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frameChanged()));
}
m_movie = movie;
if (m_movie) {
connect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frameChanged()));
}
frameChanged();
}
void GraphicsMovieItem::frameChanged() {
if (!m_movie) { return; }
setPixmap(m_movie->currentPixmap());
}
Usage:
QMovie *mv = new QMovie("c:/tmp/sun.gif");
GraphicsMovieItem* item = new GraphicsMovieItem();
item->setMovie(mv);
scene.addItem(item);

Equivalent of BufferedImage (java awt) on JavaFx

I'm working with JavaFx and i'm looking for an equivalent of the AWT BufferedImage. I saw that I can used SwingFXUtils to used an awt BufferedImage with JavaFx but I don't want to used awt.
In fact I'm looking for a structure to display a table of pixel witch is associated to a ColorModel.
Does anybody know some equivalent with JavaFx ?
Thanks a lot.
The closest you get to a BufferedImage in JavaFX is javafx.scene.image.WritableImage. It is a subclass of javafx.scene.image.Image, and was introduced in JavaFX 2.2.
Depending on your use case, javafx.scene.canvas.Canvas and javafx.scene.canvas.GraphicsContext (similar to a Graphics2D Java2D) might be a better fit.
To paint on a Canvas node and get the contents in a WritableImage, use (adapted from the Canvas JavaDoc):
// Create canvas
Canvas canvas = new Canvas(250, 250);
GraphicsContext gc = canvas.getGraphicsContext2D();
// Paint on it
gc.setFill(Color.BLUE);
gc.fillRect(75, 75, 100, 100);
// NOTE: The canvas must be part of a Scene for the following to work properly, omitted for brevity
// Obtain a snapshot of the canvas
WritableImage image = canvas.snapshot(null, null);
See Working with Canvas from he JavaFX tutorials for more information.

Changing grid column's/row's width/height by storyboard animation in Windows Store App

I'm looking for some method to change grid column's width (or row's height) by animtion defined in Storyboard. I have already found some solutions for WPF apps, but they are all useless in case of Windows Store programming, eg.:
Grid Column changing Width when animating
how to change the height of a grid row in wpf using storyboard
http://www.codeproject.com/Articles/18379/WPF-Tutorial-Part-2-Writing-a-custom-animation-cla
Is such result obtainable by creating a custom class, inheriting from Timeline? If so, which components should be overrode for proper implementation?
You should be able to use a simple DoubleAnimation. Make sure to set EnableDependentAnimation=True, as outline here.
One thing to realize when trying things out is that ColumnDefinitions are a GridLength struct. You can find more information on them here. You will need to have the animation set the Value property.
Here is a sample method to animate a Grid ColumnDefinition MaxWidth.
private void Animate(ColumnDefinition column)
{
Storyboard storyboard = new Storyboard();
Duration duration = new Duration(TimeSpan.FromMilliseconds(500));
CubicEase ease = new CubicEase { EasingMode = EasingMode.EaseOut };
DoubleAnimation animation = new DoubleAnimation();
animation.EasingFunction = ease;
animation.Duration = duration;
storyboard.Children.Add(animation);
animation.From = 1000;
animation.To = 0;
animation.EnableDependentAnimation = true;
Storyboard.SetTarget(animation, column);
Storyboard.SetTargetProperty(animation, "(ColumnDefinition.MaxWidth)");
storyboard.Begin();
}

Qt QLabel fails to resize

I implemented QLabel much like Qt's ImageViewer example, except I use QGridLayout for positioning my widgets. I also implemented similar lines for scaling my QLabel using QScrollBar, but QLabel just doesn't scale like it should inside the QScrollArea. I am not sure if it is related to some kind of GridLayout management issue or something else. I have been reading everywhere and trying different things for 3 days now. Below I list the relevant portion of my code.
In my Viewer class constructor:
{
imageLabel1 = new QLabel;
imageLabel1->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
imageLabel1->setScaledContents(true);
scrollArea1 = new QScrollArea;
scrollArea1->setWidget(imageLabel1);
scrollArea1->setWidgetResizable(true);
....
QGridLayout *centralLayout = new QGridLayout;
centralLayout->addWidget(scrollArea1, 0, 0);
...}
and my scaleImage method:
void Viewer::scaleImage1(int factor)
{
Q_ASSERT(imageLabel1->pixmap());
scaleFactor *= (1 + factor);
//imageLabel1->resize(scaleFactor* imageLabel1->pixmap()->size());
imageLabel1->pixmap()->toImage().scaled(scaleFactor* imageLabel1->pixmap()->size(), Qt::KeepAspectRatio, Qt::FastTransformation);
imageLabel1->adjustSize();
adjustScrollBar(scrollArea1->horizontalScrollBar(), factor);
adjustScrollBar(scrollArea1->verticalScrollBar(), factor);
imageLabel1->update();
}
My scaleImage1 function is a public slot, and it receives signal from a scrollbar that goes between 0 and 2 so that, into the scaleFactor, the imageLabel1 is designed to be capable of being zoomed in up to 3 times its original size. But when I run the code, I don’t observe the imageLabel becoming enlarged inside the QScrollArea, which I saw in the imageViewer demo. The imageLabel1 simply retains the original size as it is loaded and does not respond to the valueChange() of scrollbar.
I'd appreciate your advice/tips very much.
I think is because you set QSizePolicy::Minimum to the imageLabel, try with MinimumExpanding or other that better fit your needs.

add uicomponent inside a sprite

i want to add UIComponent inside a spite. here is the code:
private function make() : void {
var circle : Sprite = new Sprite();
circle.graphics.beginFill(0xFF0000, 0.2);
circle.graphics.drawCircle(0, 0, 20);
var button : Button = new Button();
button.label = "testing...";
var wrapper : UIComponent = new UIComponent();
circle.addChild( button );
wrapper.addChild( circle );
addChild( wrapper );
}
the problem is that button is added, but is not displayed. if i do reversed - add sprite to uicomponent - everything works fine, but this way it doesn't work. i tried to use invalidate functions for button etc... even tried making "circle" as UIMovieClip, but no luck - button is still invisible. also if i simply do "addChild( button );" - it is shown, what the... please help, what i am doing wrong? how can i add a button inside a sprite?
Short answer, you can't. What you CAN do is instead of using Sprite, you use UIComponent for your circle.
The reason for this is that UIComponent has A LOT of code that changes how it behaves, including how to add and layout children. You could essentially take the same code to a Sprite since UIComponent does extend it, however that would be VERY redundant. This works great for me:
private function make() : void {
var circle : UIComponent= new UIComponent();
circle.graphics.beginFill(0xFF0000, 0.2);
circle.graphics.drawCircle(0, 0, 20);
var button : Button = new Button();
button.label = "testing...";
var wrapper : UIComponent = new UIComponent();
circle.addChild( button );
wrapper.addChild( circle );
addChild( wrapper );
}
Unfortunately, in order to use Sprite the way you are trying to do it, you would have to extend Sprite and implement IUIComponent.
Taken from the Flex 3 Language Reference:
Note: While the child argument to the
method is specified as of type
DisplayObject, the argument must
implement the IUIComponent interface
to be added as a child of a container.
All Flex components implement this
interface.
Sprite does not implement IUIComponent, so you are experiencing a pretty typical issue. UIComponent's don't typically have speed issues when compared to Sprites, so I would recommend just drawing on your UIComponent.
As stated before, you /could/ extend Sprite to implement IUIComponent, but it's a pain.
Hope this helps!

Resources