Make a QLabel blink - c++

I'm using Qt to make a gui application for my beagleboard.
I'm trying to make a QLabel blink with a custom image.
QTimer::connect(timer, SIGNAL(timeout()), this, SLOT(blink()));
timer->start(1000);
I'm thinking to use QTimer to call the blink() function every second, but I do not have a clue what the code should be in blink() function. I hope someone can help, since i have struggle with this problem in a while now.

Create blinking animation in a GIF file.
Create whatever animation you like with tools like GIF Animator.
Show it like below:
auto movie = new QMovie("myblinking.gif");
QLabel blinklabel = new QLabel();
blinklabel->setMovie(movie);
movie->start();

The easiest way is to hide and show it again.
Class::blink()
{
if(label->isHidden())
label->show();
else
label->hide();
}
This approach is good because you don't need to set your image again and again, just show/hide it(set empty pixmap or set image every second is not efficient approach).
If you use layout, then it can really break your layout, so you can use QStackedWidget with imageLabel and empty label and change it every second. I think that it will be still better than set empty pixmap or set image every second. Choose the best for you.
http://qt-project.org/doc/qt-4.8/qstackedwidget.html

Using a bool member isQLabelVisible in your class
Class::blink() {
if(isQLabelVisible) {
doHideQLabel();
isQLabelVisible = false;
} else {
doShowQLabel();
isQLabelVisible = true;
}
}
void Class::doHideQLabel() {
[...]
}
void Class::doShowQLabel() {
[...]
}
You have a starting point for a good solution. Now, to implements do{Hide,Show}QLabel(), read answers from this question and decide which one is the best for your needs.

Related

Why is my QStyledItemDelegate not visible?

I'm trying to create a custom item delegate for a list of objects, but when I run my app the list view is blank. I know my model is populated, and it displays as expected with the standard default delegate. I can also tell that my custom delegate is being rendered in some sense, since space is taken up in the list, and the tooltips and statustips that I set work, but the contents are not visible (the listview appears to be blank white).
My code is based on this example: https://doc.qt.io/archives/qt-5.12/qtwidgets-itemviews-stardelegate-example.html
Qt 5.12 is the version that I'm stuck with, and I'm also stuck using visual studio without the normal Qt debugging tools, do to factors outside of my control.
Anyway, I create the widgets that should be displayed in the constructor, with default values for testing:
EntityListDelegate::EntityListDelegate(QWidget* parent /*= nullptr*/) : QStyledItemDelegate(parent)
{
ui = new QWidget(parent);
ui->setMinimumSize(QSize(200, 40));
QHBoxLayout* hLayout = new QHBoxLayout(ui);
iconLabel = new QLabel(ui);
iconLabel->setMinimumSize(QSize(20, 20));
iconLabel->setMaximumSize(QSize(40, 40));
iconLabel->setPixmap(QPixmap(":/icons/Placeholder.png"));
hLayout->addWidget(iconLabel);
QVBoxLayout* vLayout = new QVBoxLayout(ui);
nameLabel = new QLabel(ui);
nameLabel->setMinimumSize(QSize(150, 20));
nameLabel->setText("Unknown entity");
vLayout->addWidget(nameLabel);
typeLabel = new QLabel(ui);
typeLabel->setMinimumSize(QSize(150, 16));
typeLabel->setText("Unknown type");
vLayout->addWidget(typeLabel);
hLayout->addLayout(vLayout);
ui->setLayout(hLayout);
}
Note that each item should have a thick black border, which is not being rendered. (Edit: I changed the QFrame back to a QWidget)
I also implemented paint, where the real values should get set based on info in the model:
void EntityListDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
nameLabel->setText(index.data(Qt::DisplayRole).toString());
switch (qvariant_cast<int>(index.data(UserRoles::Type)))
{
case EntityType::Foo:
{
iconLabel->setPixmap(QPixmap(":/icons/foo.png"));
typeLabel->setText("Foo");
break;
}
case EntityType::Bar:
{
iconLabel->setPixmap(QPixmap(":/icons/bar.png"));
typeLabel->setText("Bar");
break;
}
case EntityType::Baz:
{
iconLabel->setPixmap(QPixmap(":/icons/baz.png"));
typeLabel->setText("Baz");
break;
}
default:
break;
}
}
The other functions are just stubs, since the user shouldn't be able to edit this data.
Am I missing some step in my setup?
Update: I tried making the pointer to the delegate that gets passed into setItemDelegate() a member of the class that owns the the ListView. I now get one item on the list that renders correctly, in the top position in the list. I can sometimes get it to display another item by clicking where that item should be, but it's still in the same location.
The answer to the question as asked is that if you're trying to alter the default display, not the editor, you have to reimplement paint and basically draw the whole thing manually. This is such a massive PITA as to make QStyledItemDelegate functionally unusable for this use case, IMO. Use QtQuick if you can, but that's not an option in my case.
My actual solution, for the curious, was to use QSortFilterProxyModel and override data() to return "EntityName\nEntityType". That gets me ~80% of what I was trying to achieve, and hopefully I can get a little closer with styling when I get to that part.

QGraphicsItem loses focus after using QComboBox

I am doing a small game in Qt and try to use WASD to move my protagonist(QGraphicsPixmapItem). The map is quite big so I use a QComboBox to change the scale of the scene.
The game looks like this:
The simple game
How I built the protagonist:
protagonist = new MyProtagonist();
protagonist->setFlag(QGraphicsItem::ItemIsFocusable);
protagonist->setFocus();
scene->addItem(protagonist);
How I built the combox:
sceneScaleCombo = new QComboBox;
QStringList scales;
scales << tr("1%")<<tr("10%") << tr("20%") <<tr("50%") << tr("100%") <<tr("200%");
sceneScaleCombo->addItems(scales);
sceneScaleCombo->setCurrentIndex(4);
connect(sceneScaleCombo,SIGNAL(currentIndexChanged(QString)),this,SLOT(sceneScaleChanged(QString)));
void MainWindow::sceneScaleChanged(const QString &scale)
{
double newScale = scale.left(scale.indexOf(tr("%"))).toDouble() / 100;
QMatrix oldMatrix = view->matrix();
view->resetMatrix();
view->translate(oldMatrix.dx(),oldMatrix.dy());
view->scale(newScale,newScale);
protagonist->setFocus();
}
Everything worked well at the beginning. However, after I clicking the combobox, my protagonist cannot be controlled by keyboard any more. I need to click my protagonist to make it focused again.
Is there any way to set it focused automatically?
Thanks a lot.
By clicking QComboBox the QGraphicsView looses the focus. You attempt to return it back by calling setFocus(); on the QGraphicsPixmapItem. This approach doesn't work as you expect, because it sets the focus item inside the view, but the view itself still does not have focus. To fix that in MainWindow::sceneScaleChanged instead of protagonist->setFocus(); write view->setFocus();.

How to set text below the QToolButton in QT not below the icon

I'm using QToolButton and I set the icon.
Now I want Text "below the QToolButton", "Not below the icon".
Is there any way to achieve this in C++,QT in Linux ?
I've found myself in the same position a while back ago while I was making an application for an embedded Linux system.
I haven't found a straight forward solution (I was searching for a way to achieve it with CSS).
What I ended up doing, was creating a new QWidget (using the designer). Then placing the button in it with a QLabel under it.
Then added a simple static function
static void wdgCustomButton::create(const QString iconPath, const QString text)
{
// create a new button here, create some modification functions for
// text, image and optionally QStyleSheets.
// Call those here (pass the arguments)
// Then return the button
// pseudo code, (not tested):
wdgCustomButton button = new wdgCustomButton( /* could pass a parent */ );
button->setIcon( iconPath ); // function simply calls the ui->button->setIcon
button->setText( text ); // function simply calls the ui->label->setText
return button;
}
And then add those new QWidgets to your pannel using code (maybe someone knows how to get it in the default toolbar, but I haven't searched for that myself yet since I never needed it).
this->menuButtons[menuBtnsCount] = wdgCustomButton::create( ":/Images/Warning.png", "Delete everything" );
this->menuButtons[menuBtnsCount]->setGeometry( QRect( /* size and position here */ ) );
this->menuButtons[menuBtnsCount]->show();
I hope this might give you an idea to fix it in an easy way!
Edit:
I'm sorry, I forgot to add something about the click event. The click event was mainly why I made a QWidget out of it!
I just used the connect function [I belive on the whole button like: connect(this->menuButtons[0], ...]

take screenshot without one specific program window

I need to take a regular screenshot but i need for a way to disregard an open application. In the screenshot must appear the regular background as if the application/window wasn't open.
In other words, i need one screenshot without an window/aplication (which is presemnt) but appearing what is behind of this window/aplication, disregarding the window/ap.
For get screenshot i have the folowing code in QT/c++:
(...)
QScreen *screen = QGuiApplication::primaryScreen();
QPixmap qPImage = screen->grabWindow(0);
QImage qImg = qPImage.toImage();//convert to qImage
(...)
It is possible do what i need?
Regards
Alex
May be not the perfect solution, but this is what I did in the exact same situation:
void MainWindow::onUpdateClicked()
{
hide();
QTimer::singleShot(45, this, SLOT(updateScreenshotPicture()));
}
void MainWindow::updateScreenshotPicture()
{
screenshotBorders->setPic(QPixmap::grabWindow(QApplication::desktop()->winId()));
show();
}

setCentralWidget() causing the QMainWindow to crash.. Why?

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
this->setupUi(this);
this->setupActions();
this->setWindowTitle(tr("CuteEdit"));
label = new QLabel(tr("No Open Files"));
this->setCentralWidget(label);
label->setAlignment(Qt::AlignCenter);
}
By above code, I get a GUI like this(Its a screenshot of whole screen, Only observe the window displayed in middle of page of ebook). (I used QT Designer)
Now, i want user to select File->Open.. A Dialog appears and file gets selected.. Its contents are to be displayed in *textEdit widget..
Function for that is below..
void MainWindow::loadFile()
{
QString filename = QFileDialog::getOpenFileName(this);
QFile file(filename);
if (file.open(QIODevice::ReadOnly|QIODevice::Text))
{
label->hide();
textEdit->setPlainText(file.readAll());
mFilePath = filename;
QMainWindow::statusBar()->showMessage(tr("File successfully loaded."), 3000);
}
}
The window crashes at line:-
textEdit->setPlainText(file.readAll());
But if i comment the line:-
this->setCentralWidget(label);
i mean i remove label as being the central widget, the program runs as expected.. Why?
And also, I am not clear about the concept of CentralWidget. Pls guide.
JimDaniel is right in his last edit. Take a look at the source code of setCentralWidget():
void QMainWindow::setCentralWidget(QWidget *widget)
{
Q_D(QMainWindow);
if (d->layout->centralWidget() && d->layout->centralWidget() != widget) {
d->layout->centralWidget()->hide();
d->layout->centralWidget()->deleteLater();
}
d->layout->setCentralWidget(widget);
}
Do you see that if your MainWindow already had centralWidget() Qt schedules this object for deletion by deleteLater()?
And centralWidget() is the root widget for all layouts and other widgets in QMainWindow. Not the widget which is centered on window. So each QMainWindow produced by master in Qt Creator already has this root widget. (Take a look at your ui_mainwindow.h as JimDaniel proposed and you will see).
And you schedule this root widget for deletion in your window constructor! Nonsense! =)
I think for you it's a good idea to start new year by reading some book on Qt. =)
Happy New Year!
Are you sure it's not label->hide() that's crashing the app? Perhaps Qt doesn't like you hiding the central widget. I use Qt but I don't mess with QMainWindow that often.
EDIT: I compiled your code. I can help you a bit. Not sure what the ultimate reason is as I don't use the form generator, but you probably shouldn't be resetting the central widget to your label, as it's also set by the designer, if you open the ui_mainwindow.h file and look in setupGui() you can see that it has a widget called centralWidget that's already set. Since you have used the designer for your GUI, I would use it all the way and put the label widget in there as well. That will likely fix your problems. Maybe someone else can be of more help...
I'm not sure I understood your problem, neither what the guys above said (which I guess are valid information) and it seems to be an old topic.
However, I think I had a problem that looks like this and solved it, so I want to contribute my solution in case it helps anyone.
I was trying to "reset" central widget using QLabels. I had three different ones, switch from first to second, then to third and failed to switch back to the first one.
This is my solution that worked:
Header file
QLabel *imageLabel;
Constructor
imageLabel = new QLabel("<img src='/folder/etc.jpg' />");
this->setCentralWidget(imageLabel);
Reset
imageLabel = NULL;
imageLabel = new QLabel("<img src='/folder/etc.jpg' />");
this->setCentralWidget(imageLabel);
Hope that helps
Aris