Fixed text inside or adjacent to QProgressBar with scaling font size in Qt - qt

I am new with Qt (using Qt Creator) and the QProgressBar. I am interested in learning how to have a fixed text value (not the value of the progress bar) inside or adjacent to the left of a QProgressBar and have its font size scale according with the size of the progress bar.
For example:
or
I have considered using a QLabel but failed and I could not find any examples online.
Any code sample illustrating the solution for me to understand and learn from will be much appreciated.

If label inside the progressbar will do, then here is an example. This might not be exactly what you want, but it should send you in the right direction. I adjust the font size in the resize event. In this example the font size is calculated based on the size of the label, which is the same size as the progress bar.
#include <QApplication>
#include <QProgressBar>
#include <QWidget>
#include <QLabel>
#include <QLayout>
#include <QTimer>
class Widget : public QWidget
{
Q_OBJECT
QProgressBar progressBar;
QLabel *label;
public:
Widget(QWidget *parent = nullptr) : QWidget(parent)
{
progressBar.setRange(0, 100);
progressBar.setValue(20);
progressBar.setTextVisible(false);
progressBar.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
label = new QLabel(&progressBar);
label->setText("Hello World!");
setLayout(new QHBoxLayout);
layout()->addWidget(&progressBar);
}
protected:
void resizeEvent(QResizeEvent *)
{
label->resize(progressBar.size());
QFontMetrics fm(label->font());
float multiplier_horizontal = (float)label->width() / fm.width(label->text());
float multiplier_vertical = (float)label->height() / fm.height();
QFont font = label->font();
font.setPointSize(font.pointSize() * qMin(multiplier_horizontal, multiplier_vertical));
label->setFont(font);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"

Related

My Qt 5.5 QPushButton Button not showing up in window (Win7)

I'm doing the Udemy C++ Qt tutorial. The idea is to have a QPushButton button in a window.
When I run this, I get an empty window. Using Qt 5.5 in Win7.
Here are my files:
main.cpp
#include<QApplication>
#include"S_S.h"
int main(int argc, char *argv[])
{
QApplication app(argc,argv);
S_S MyTest;
MyTest.show();
return app.exec();
}
S_S.h
#ifndef S_S_H
#define S_S_H
#include<QApplication>
#include<QWidget>
#include<QPushButton>
class S_S : public QWidget
{
public:
S_S();
private:
QPushButton *Button1;
};
#endif // S_S_H
S_S.cpp
#include"s_s.h"
S_S::S_S():QWidget()
{
Button1=new QPushButton;
Button1->setText("Cancel");
connect(Button1,SIGNAL(clicked()),qApp,SLOT(quit()));
}
You probably want to construct the QPushButton and pass in a parent widget:
Button1 = new QPushButton(this);
I assume you want the S_S instance to be the parent.
You might also want to set the size and location of the button:
Button1->setGeometry(QRect(QPoint(100, 100), QSize(200, 50)));
There is an example here of using QPushButton.

Qt making a QPushButton fill layout cell

I need a pushbutton to either fill or not fill the entire space provided by a QGridLayout cell upon the creation of the button (the alignment value is loaded from file). I've simplified my situation with the following code. During run-time, users can set the alignment of the button - either making it fill the entire layout cell or nicely centered. It works so long as the button didn't start off with NULL alignment specified. Yet, I need the ability to start off with a NULL alignment (i.e. the button fills the space of the layout cell). When initially aligning with NULL, what is getting set to make the button lock into a AlignVCenter setting and how can I get the button to return to acting like it was initialized with something other than null alignment?
I'm using Qt 4.8 on Ubuntu 12.04 LTS
#include <QPushButton>
#include <QGridLayout>
#include <QMainWindow>
#include <QApplication>
class MyWidget : public QWidget {
Q_OBJECT
QPushButton* m_pb;
QGridLayout* m_gl;
protected slots:
void pbClicked();
public:
MyWidget(QWidget* parent = 0);
};
MyWidget::MyWidget(QWidget* parent): QWidget(parent)
{
m_pb = new QPushButton(tr("push me"));
connect(m_pb, SIGNAL(clicked()), this, SLOT(pbClicked()));
m_gl = new QGridLayout();
//use (1) to see button expand when button is pressed
//use (2) to show that I can't start off expanded
/*1*/ //m_gl->addWidget(m_pb, 0, 0, Qt::AlignCenter); // creates desired effect
/*2*/ //m_gl->addWidget(m_pb, 0, 0, 0); //does not create desired effect
setLayout(m_gl);
}
void MyWidget::pbClicked(){
//will expand button so long as initial alignment is not NULL
m_gl->setAlignment(m_pb, 0);
}
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyWidget* widget = new MyWidget();
QMainWindow window;
window.setCentralWidget(widget);
window.show();
return app.exec();
}
#include "main.moc"
The "desired" behavior that you see is in fact an error, and I will file a bug report for it. Thanks for spotting it - nice corner case.
You need to set the size policy of the button to expanding in both directions. Buttons normally don't want to expand vertically, so if you tried a variant that toggles the alignment, you'd see that it works only horizontally, and that's correct.
This is a simple demonstration that shows the correct behavior that also fulfills your needs.
#include <QPushButton>
#include <QGridLayout>
#include <QApplication>
class AlignButton : public QPushButton {
Q_OBJECT
Qt::Alignment m_alignment;
Q_SLOT void clicked() {
m_alignment ^= Qt::AlignCenter;
parentWidget()->layout()->setAlignment(this, m_alignment);
label();
}
void label() {
setText(QString("Alignment = %1").arg(m_alignment));
}
public:
AlignButton(Qt::Alignment alignment, QWidget * parent = 0) :
QPushButton(parent),
m_alignment(alignment)
{
connect(this, SIGNAL(clicked()), SLOT(clicked()));
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
label();
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QWidget window;
QGridLayout layout(&window);
layout.addWidget(new AlignButton(0), 0, 0, 0);
layout.addWidget(new AlignButton(Qt::AlignCenter), 1, 0, Qt::AlignCenter);
window.setMinimumSize(500, 200);
window.show();
return app.exec();
}
#include "main.moc"

qlabel centering

I have a qlabel L inside a qwidget W. L is vertically and horizontally aligned.
When I resize W, L doesn't get centered.
Is this expected?
What's a good implementation to have L centered again?
To align text in a QLabel by calling QLabel::setAlignment works like expected for me.
Maybe you miss to add your Label to a Layout (so your label would automatically resized if your widget is resized). See also Layout Management. A minimal example:
#include <QApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QWidget>
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
QLabel* label=new QLabel("Hello World!");
label->setAlignment(Qt::AlignCenter);
QWidget* widget=new QWidget;
// create horizontal layout
QHBoxLayout* layout=new QHBoxLayout;
// and add label to it
layout->addWidget(label);
// set layout to widget
widget->setLayout(layout);
widget->show();
return app.exec();
}

How to add a tick mark to a slider if it cannot inherit QSlider

I have a Qt dialog and there is a slider in it, when the dialog is initialized the slider will be set a value. In order to remind the user what is the default value, I want to add a mark to the slider, just draw a line or a triangle above the handle. Here, the slider should be of QSlider type, that means I can't implement a customized control derived from QSlider. Is there any way to realize it ?
I'm not clear why you can't derive a control from QSlider. You can still treat it like a QSlider, just override the paintEvent method. The example below is pretty cheesy, visually speaking, but you could use the methods from QStyle to make it look more natural:
#include <QtGui>
class DefaultValueSlider : public QSlider {
Q_OBJECT
public:
DefaultValueSlider(Qt::Orientation orientation, QWidget *parent = NULL)
: QSlider(orientation, parent),
default_value_(-1) {
connect(this, SIGNAL(valueChanged(int)), SLOT(VerifyDefaultValue(int)));
}
protected:
void paintEvent(QPaintEvent *ev) {
int position = QStyle::sliderPositionFromValue(minimum(),
maximum(),
default_value_,
width());
QPainter painter(this);
painter.drawLine(position, 0, position, height());
QSlider::paintEvent(ev);
}
private slots:
void VerifyDefaultValue(int value){
if (default_value_ == -1) {
default_value_ = value;
update();
}
}
private:
int default_value_;
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
DefaultValueSlider *slider = new DefaultValueSlider(Qt::Horizontal);
slider->setValue(30);
QWidget *w = new QWidget;
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(slider);
layout->addStretch(1);
w->setLayout(layout);
QMainWindow window;
window.setCentralWidget(w);
window.show();
return app.exec();
}
#include "main.moc"
Easiest way I can think off is:
Add QSlider to QSlider (like you do it with layouts and QFrames). Slider above will be your current slider (clickable one). Slider below will be your "default tick position" value.
#include <QApplication>
#include <QSlider>
#include <QVBoxLayout>
int main(int argc, char * argv[])
{
QApplication app(argc, argv);
QSlider * defaultValueSlider = new QSlider();
QSlider * valueSlider = new QSlider(defaultValueSlider);
QVBoxLayout * lay = new QVBoxLayout(defaultValueSlider);
lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0);
lay->addWidget(valueSlider);
defaultValueSlider->setRange(0, 100);
valueSlider->setRange(0, 100);
defaultValueSlider->setValue(30);
defaultValueSlider->show();
return app.exec();
}
Why do you need to inherit a QSlider to access its public methods?
http://doc.trolltech.com/4.7/qslider.html
You can just call its setTickPosition() in your app.

'Magical' QTextEdit size

Here is an equivalent extracted code:
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QTextBrowser>
#include <QTextEdit>
class ChatMessageEdit : public QTextEdit {
public:
ChatMessageEdit(QWidget* parent) : QTextEdit(parent) { }
virtual QSize sizeHint() const { return QSize(0, 25); }
};
int main(int argc, char** argv) {
QApplication app(argc, argv);
QWidget* widget = new QWidget;
QVBoxLayout* layout = new QVBoxLayout;
QTextBrowser* log = new QTextBrowser(widget);
layout->addWidget(log, 1);
ChatMessageEdit* editor = new ChatMessageEdit(widget);
editor->setMinimumHeight(editor->sizeHint().height()); // empty
layout->addWidget(editor);
widget->setLayout(layout);
widget->show();
return app.exec();
}
The minimum size for editor is 25px, and so is it's minimal size. But by some strange reason it is created with a size about 100px that is always preferred to my size hint. Everything other is working as expected: expanding (size hint isn't really fixed in my application), shrinking etc. I tried changing size policy, but with abolutely no result.
This was the minumumSizeHint() method. I overloaded it to return sizeHint(), and everything is working as expected now.
You are also overlooking how layouts work. Please read up here on why your sizes are not being respected in a layout.

Resources