QT - Resize QToolbar - qt

i have some concatenate toolbar. For every toolbar i have call:
toolbar->setGeometry(x,y,width,height)
but i have no resize.
I try to call
toolbar->updateGeometry();
but nothing.
My goal is to expand every toolbar with my size definition

There is a good chance you are using this for repositioning your toolbars on init and saving at closing.
Here is a solid way to do that:
What you really need is to use the QMainWindow saveGeometry() and restoreGeometry() functions and save and load the byte array through the QSettings interface.
writeSettings
QSettings s;
s.beginGroup("MainWindow");
this->restoreGeometry(s.value("geometry").toByteArray());
this->restoreState(s.value("windowState").toByteArray());
s.endGroup();
readSettings
QSettings s;
s.beginGroup("MainWindow");
s.setValue("geometry", saveGeometry());
s.setValue("windowState", saveState());
s.endGroup();
Hope that helps.

You can try QWidget::resize( int w, int h ) to resize the toolbar.
toolbar-> resize( 200, 20 );

The toolbar's geometry is either managed by a layout or by the main window.
You'd need to show how is the toolbar used/displayed.

Related

Qt this->update() is not entirely updating the widget

I created a simple widget with a button, a slot for the button, a resize event and a paint event.
I expect when I click on the button it draws an ellipse at a random position and the button disappears.
But I get: the ellipse is drawn and the button is not hidden after this->update.
Even stranger, when I uncomment the button->hide(); every time I click it draws a new eclipse but the old ellipses are still there. Something is wrong with updating and the paint event.
If I resize the window by dragging with the mouse the update of the paint event works as expected. Only the last ellipse stays and the button is hidden.
My Qt version is Qt_5_15_2_MinGW_32_bit
Here is the code of the widget:
PATrackSetter::PATrackSetter(QWidget *parent) : QWidget(parent){
button = new PAButton(this);
connect(button,SIGNAL(clicked(int, QString, QString)),this,SLOT(on_TileClicked(int, QString, QString)));
button->setFixedSize(100, 100);
button->move(0,0);
button->show();
}
void PATrackSetter::paintEvent(QPaintEvent *){
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QPen pen = QPen();
pen.setColor(Qt::yellow);
painter.setPen(pen);
painter.drawEllipse(100,rand() % 500 +10,5,5);
}
void PATrackSetter::resizeEvent(QResizeEvent *)
{
}
void PATrackSetter::on_TileClicked(int buttonID, QString buttonText, QString newButtonStatus){
button->hide();
this->update();
}
Can anyone see what I did wrong?
Edit:
I added more code to the project and I run into the same issue. I added the following lines into the MainWindow class and the updating inside the PATrackSetter widget doesn't work anymore as expected. I really dont understand why. But if I uncomment these lines it works again well.
QPalette paletteBGColor;
QBrush brush;
brush.setColor(Qt::black);
paletteBGColor.setBrush(QPalette::Background, brush);
this->setPalette(paletteBGColor);
Case closed.
If the button is not hidden then slot is not called. I guess you didn't put void on_TileClicked(int, QString, QString) in slots: section in header file, or signal/slot signatures don't match (in which case there must be warning in debug output in runtime).
When you are reimplementing paintEvent you should expect that every update on the QWidget, even manually or by the parent window, will call the paintEvent once. So, it's up to you to handle cleaning the previous state or draw on the previous drawings. The behavior you explained is quite normal.
It seems that you are not calling setGeometry on the PATrackSetter when you are instantiating it. So, in the update hierarchy, its size is not known and you should expect partial redraws and undefined behaviors.

How to display fix banner between QMenubar and QToolBar in QMainWindow

How can I show fixed banner (with some widget like label and button ) in between
QMenuBar and QToolBar ?
Similarly like QStatusBar but in between QMenuBar and QToolBar.
I tried to implement using QToolBar.
// toolbar Banner with lable inside it.
QLabel * bannerLabel = new QLabel(" bannerToobar with label banner.");
bannerLabel->setAlignment( Qt::AlignVCenter );
ui.bannerToobar->addWidget( bannerLabel );
ui.bannerToobar->setAllowedAreas(Qt::ToolBarArea::TopToolBarArea);
ui.bannerToobar->setMovable( false );
QSize banner_sz = ui.bannerToobar->size();
ui.bannerToobar->setFixedHeight( banner_sz.height() * 2 );
QSizePolicy banner_szPolicy( QSizePolicy::Policy::Maximum, QSizePolicy::Policy::Fixed );
banner_szPolicy.setHorizontalStretch(255);
ui.bannerToobar->setSizePolicy( banner_szPolicy );
but i can't prevent user from draging mainToolbar and droping in the same row as my
bannerToolbar
You can force it to wrap initially using QMainWindow::addToolBarBreak, but I don't know a way to prevent it from being put back there later by the user (except for making the toolbars non-moveable).
If there was a QToolbar::dockLocationChanged signal (which seems to have been requsted and resolved in https://bugreports.qt-project.org/browse/QTBUG-1274, but I still don't see the signal anywhere), I suppose you could use insertToolBarBreak to fix it up whenever things have changed. Maybe there's some hackish way you could get notified when the toolbars move.
Or you could use QMainWindow::setMenuWidget to place a widget containing both your QMenuBar and something else into the menu area of the QMainWindow. This could get tricky if you want to support styles (mac/gnome/etc) where the menubar gets lifted out of your window to the top-of-screen and the toolbar gets unified with the window title decorations. But the idea of a banner between menubar and toolbar just naturally has problems in such cases :-)

How to set animated icon to QPushButton in Qt5?

QPushButton can have icon, but I need to set animated icon to it. How to do this?
I created new class implemented from QPushButton but how to replace icon from QIcon to QMovie?
This can be accomplished without subclassing QPushButton by simply using the signal / slot mechanism of Qt. Connect the frameChanged signal of QMovie to a custom slot in the class that contains this QPushButton. This function will apply the current frame of the QMovie as the icon of the QPushButton. It should look something like this:
// member function that catches the frameChanged signal of the QMovie
void MyWidget::setButtonIcon(int frame)
{
myPushButton->setIcon(QIcon(myMovie->currentPixmap()));
}
And when allocating your QMovie and QPushButton members ...
myPushButton = new QPushButton();
myMovie = new QMovie("someAnimation.gif");
connect(myMovie,SIGNAL(frameChanged(int)),this,SLOT(setButtonIcon(int)));
// if movie doesn't loop forever, force it to.
if (myMovie->loopCount() != -1)
connect(myMovie,SIGNAL(finished()),myMovie,SLOT(start()));
myMovie->start();
Since I had to solve this problem for a project of mine today, I just wanted to drop the solution I found for future people, because this question has lots of views and I considered the solution quite elegant. The solution was posted here. It sets the icon of the pushButton every time, the frame of the QMovie changes:
auto movie = new QMovie(this);
movie->setFileName(":/sample.gif");
connect(movie, &QMovie::frameChanged, [=]{
pushButton->setIcon(movie->currentPixmap());
});
movie->start();
This also has the advantage, that the icon will not appear, until the QMovie was started. Here is also the python solution, I derived for my project:
#'hide' the icon on the pushButton
pushButton.setIcon(QIcon())
animated_spinner = QtGui.QMovie(":/icons/images/loader.gif")
animated_spinner.frameChanged.connect(updateSpinnerAniamation)
def updateSpinnerAniamation(self):
#'hide' the text of the button
pushButton.setText("")
pushButton.setIcon(QtGui.QIcon(animated_spinner.currentPixmap()))
Once you want to show the spinner, just start the QMovie:
animated_spinner.start()
If the spinner should disappear again, then stop the animation and 'hide' the spinner again. Once the animation is stopped, the frameChanged slot won't update the button anymore.
animated_spinner.stop()
pushButton.setIcon(QtGui.QIcon())

screenshot of a qt application from inside the application

I am trying to capture a screenshot of my application within the application. Its a Qt-based application. Is anyone aware of how to do this? Any suggestions are very welcome.
CV
You can tell any QWidget (including your QMainWindow) to render itself off-screen:
http://developer.qt.nokia.com/doc/qt-4.8/qwidget.html#render
Technically this is not a screenshot as it renders the widget explicitely for this purpose instead of capturing what is seen on-screen. For almost any purpose it doesn't matter.
If you have a GL widget, you can/must instead use grabFramebuffer() which has the advantage of capturing what is seen on the screen.
With this example you could get all your widget screen.
You could attach this method to any key press or signal, as you prefer, to get successive screenshot.
MyClass::screenshot()
{
QWidget *w = QApplication::activeWindow();
if(w) {
static int count = 0;
QPixmap p = QPixmap::grabWidget(w);
p.save(QString("/your/path/screenshot%1.png").arg(count));
count++;
}
}
QPixmap lets you do a window grab if you have the ID. My references are for PyQt but I'm sure you can make the adjustments:
How to get RGB values of QPixmap or QImage pixel - Qt, PyQt
http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qpixmap.html#grabWindow
In modern QT 5+ it can be done like that:
void MainWindow::takeScreenshot(const QString screenshotFileName)
{
if(isActiveWindow())
{
auto grabbedScreenshot = QWidget::grab();
grabbedScreenshot.save(screenshotFileName);
}
}

Display window full screen on secondary monitor using Qt

Seems to be possible with native controls (see here and here) so now I'm looking for some Qt code to do it.
I use this code for the second display in full screen successfully on both Windows & Linux
QRect screenres = QApplication::desktop()->screenGeometry(1/*screenNumber*/);
SecondDisplay secondDisplay = new SecondDisplay(); // Use your QWidget
secondDisplay->move(QPoint(screenres.x(), screenres.y()));
secondDisplay->resize(screenres.width(), screenres.height());
secondDisplay->showFullScreen();
One way of doing it in Qt5 is to use QWindow::setScreen to set the screen on which the window should be shown. QWidget has a windowHandle() that returns the pointer to the QWindow.
Here is how to show your widget on second screen in full-screen mode :
QWidget * widget = new QWidget();
widget->show();
widget->windowHandle()->setScreen(qApp->screens()[1]);
widget->showFullScreen();
My take on this:
auto const desktop(QApplication::desktop());
setGeometry(desktop->screenGeometry(1));
#ifndef Q_OS_WIN
setWindowState(Qt::WindowState(Qt::WindowFullScreen | windowState()));
#endif // Q_OS_WIN
showFullScreen first, then setGeometry.
Qt5 tested OK
This problem got solved while using window->showFullScreen() instead of window->show().

Resources