How to avoid periodic flicker/drag effect during slideshow with QPropertyAnimation - qt

QPropertyAnimation produces periodic flicker/drag effect during animation of longer duration of about 1 second or two. For small duration animation (about 500 ms or less) the QPropertyAnimation produces smooth animation without that specific flicker/drag effect. That flicker/drag like effect appears round about every 500ms. And i need to come across some solution as soon as possible. I have attached the minimal compilable example reproducing the problem. Please have a look and help.
I am using Qt5.5 in Windows10, i use both MinGW and Visual Studio 2013 compilers, Core i5 Laptop.
#include <QCoreApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QPropertyAnimation>
#include <QApplication>
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget *parent = 0) : QWidget(parent) {
QVBoxLayout *l = new QVBoxLayout(this);
placeholder = new QWidget;
placeholder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
l->addWidget(placeholder);
QPushButton *b = new QPushButton;
l->addWidget(b);
b->setText("click");
connect(b, SIGNAL(clicked()), this, SLOT(nextPage()));
current = 0;
}
public slots:
void nextPage() {
QWidget *newPage = new QLabel("page");
newPage->setAutoFillBackground(true);
QStringList c = QColor::colorNames();
QPalette p = newPage->palette();
p.setColor(QPalette::Window, QColor(c.at(qrand() % c.size())));
newPage->setPalette(p);
newPage->setParent(placeholder);
QPropertyAnimation *anim = new QPropertyAnimation(newPage, "geometry", newPage);
QRect start = placeholder->rect();
start.setTopLeft(start.topRight());
newPage->setGeometry(start);
anim->setStartValue(start);
anim->setEndValue(placeholder->rect());
anim->setDuration(4000);
anim->start();
if(current) {
QPropertyAnimation *anim = new QPropertyAnimation(current, "geometry", current);
anim->setStartValue(placeholder->rect());
QRect r = placeholder->rect();
r.translate(-r.width(), 0);
anim->setEndValue(r);
anim->setDuration(4000);
connect(anim, SIGNAL(finished()), current, SLOT(deleteLater()));
anim->start();
}
current = newPage;
current->show();
}
private:
QWidget *placeholder;
QWidget *current;
};
#include "main.moc"
int main(int argc, char **argv) {
QApplication app(argc, argv);
Widget w;
w.show();
return app.exec();
}

Related

Can we include and show some others widgets in a QVideoWidget? [duplicate]

everyone! I try to set a click property to a QMediaPlayer Element, but I can not find the mode to make it, and if I try to put a button in front to Video, the button puts behind to video, even with
button->raise();
videoWidget->lower();
And If I put a Button to fullscreen the screen turns in black and don't shows the video
this id the code of the video player
QMediaPlayer *player = new QMediaPlayer(this);
QVideoWidget *vw = new QVideoWidget(this);
QMediaPlaylist *PlayList = new QMediaPlaylist(this);
PlayList->addMedia(QUrl::fromLocalFile("/home/user/Videos/video.mp4"));
PlayList->setPlaybackMode(QMediaPlaylist::Loop);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(vw);
player->setVideoOutput(vw);
player->setPlaylist(PlayList);
vw->setGeometry(0,0,800,480);
vw->show();
player->play();
One possible solution is to create a widget where the QVideoWidget is placed through a layout, the button is also added and we change the position through the resizeEvent() event.
#include <QApplication>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QPushButton>
#include <QUrl>
#include <QVBoxLayout>
#include <QVideoWidget>
#include <QDebug>
class VideoWidgetButton: public QWidget{
QPushButton *btn;
QVideoWidget *vw;
QMediaPlayer *player;
public:
VideoWidgetButton(QWidget *parent=Q_NULLPTR):QWidget(parent){
setLayout(new QVBoxLayout);
layout()->setContentsMargins(0, 0, 0, 0);
vw = new QVideoWidget(this);
btn = new QPushButton(this);
btn->setIcon(QIcon(":/icons/tux.jpeg"));
btn->resize(QSize(128, 128));
btn->setIconSize(QSize(128, 128));
connect(btn, &QPushButton::clicked, [](){
qDebug()<<"clicked";
});
layout()->addWidget(vw);
player = new QMediaPlayer(this);
player->setVideoOutput(vw);
QMediaPlaylist *playList = new QMediaPlaylist(this);
playList->addMedia(QUrl("qrc:/video/SampleVideo_1280x720_1mb.mp4"));
playList->setPlaybackMode(QMediaPlaylist::Loop);
player->setPlaylist(playList);
player->play();
}
protected:
void resizeEvent(QResizeEvent *ev){
btn->move(rect().bottomRight()-btn->rect().bottomRight());
return QWidget::resizeEvent(ev);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
VideoWidgetButton w;
w.resize(640, 480);
w.show();
return a.exec();
}
The complete example can be found in the following link.

Issue with Qt Toolbar extension button

I have to add a toolbar in Qt like the Windows file system explorer one under menu bar (I'm under Windows 7) , that means when the window width is reduced, icons which don't have enough place to be displayed are automatically hidden and put into a drop down list (which is displayed when clicking to an arrow which appears to the toolbar's right side). I first copy paste a code that I found to the web :
#include <QApplication>
#include <QAction>
#include <QMainWindow>
#include <QLineEdit>
#include <QToolBar>
#include <QHBoxLayout>
void initWindow(QMainWindow* w);
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(application);
QApplication app(argc, argv);
QMainWindow mainWin;
initWindow(&mainWin);
mainWin.show();
return app.exec();
}
void initWindow(QMainWindow* w)
{
QLineEdit* searchBar = new QLineEdit;
QAction* newAct = new QAction(QIcon(":/images/new.png"), "&New", w);
newAct->setShortcuts(QKeySequence::New);
QAction* openAct = new QAction(QIcon(":/images/open.png"), "&Open...", w);
openAct->setShortcuts(QKeySequence::Open);
QAction* saveAct = new QAction(QIcon(":/images/save.png"), "&Save", w);
saveAct->setShortcuts(QKeySequence::Save);
QAction* cutAct = new QAction(QIcon(":/images/cut.png"), "Cu&t", w);
cutAct->setShortcuts(QKeySequence::Cut);
QAction* copyAct = new QAction(QIcon(":/images/copy.png"), "&Copy", w);
copyAct->setShortcuts(QKeySequence::Copy);
QAction* pasteAct = new QAction(QIcon(":/images/paste.png"), "&Paste", w);
pasteAct->setShortcuts(QKeySequence::Paste);
QToolBar* fileToolBar = w->addToolBar("File");
fileToolBar->addAction(newAct);
fileToolBar->addAction(openAct);
fileToolBar->addAction(saveAct);
QToolBar* editToolBar = w->addToolBar("Edit");
editToolBar->addAction(cutAct);
editToolBar->addAction(copyAct);
editToolBar->addAction(pasteAct);
editToolBar->addWidget(searchBar);
}
... but the problem is that code works only for toolbars into a QMainWindow (and add by using QMainWindow::addToolbar() method). But into the code which I'm working for I have to do that into a QWidget, not a QWindow. So I created a horizontal layout, I added several widget into it (a QLineEdit and several QAction) and it works fine for QAction but not for QLineEdit : When I click to the arrow, all hidden QAction are visibles but not QLineEdit. Here is my code :
#include <QApplication>
#include <QtGui/QWindow>
#include <QToolbar>
#include <QVBoxLayout>
#include <QMainWindow>
#include <QPushButton>
#include <QAction>
#include <QIcon>
#include <QLineEdit>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget* w = new QWidget;
QHBoxLayout* tb1 = new QHBoxLayout;
tb1->addWidget(new QPushButton("item11"));
tb1->addWidget(new QPushButton("item12"));
tb1->addWidget(new QPushButton("item13"));
tb1->addWidget(new QPushButton("item14"));
QHBoxLayout* spacerLayout = new QHBoxLayout;
spacerLayout->addSpacerItem(new QSpacerItem(50, 20, QSizePolicy::MinimumExpanding,QSizePolicy::Fixed) );
spacerLayout->setAlignment(Qt::AlignJustify);
QWidget* sep = new QWidget;
QRect rect = sep->geometry();
rect.setWidth(0);
sep->setGeometry(rect);
QToolBar* tb3 = new QToolBar;
QLineEdit* searchBar = new QLineEdit;
QAction* item31 = new QAction(QIcon(":/images/cut.png"), "cut");
QAction* item32 = new QAction(QIcon(":/images/copy.png"), "copy");
QAction* item33 = new QAction(QIcon(":/images/open.png"), "open");
QAction* item34 = new QAction(QIcon(":/images/paste.png"), "past");
QAction* item35 = new QAction(QIcon(":/images/save.png"), "save");
tb3->addWidget(sep);
tb3->addWidget(searchBar);
tb3->addAction(item31);
tb3->addAction(item32);
tb3->addAction(item33);
tb3->addAction(item34);
tb3->addAction(item35);
QVBoxLayout* mainLayout = new QVBoxLayout;
QHBoxLayout* topLayout = new QHBoxLayout;
topLayout->addLayout(tb1);
topLayout->addLayout(spacerLayout);
topLayout->addWidget(tb3);
QHBoxLayout* bottomLayout = new QHBoxLayout;
bottomLayout->addWidget(new QPushButton);
mainLayout->addLayout(topLayout);
mainLayout->addLayout(bottomLayout);
w->setLayout(mainLayout);
w->show();
return app.exec();
}
These are screenshots of the result with the 2nd solution : I first launch application :
http://img4.hostingpics.net/pics/224120tb1.jpg
When I reduce its width, widgets which are to the right side disapeared. Then I click to the arrow to display them into the drop down list and they are all displayed except the QLineEdit :
http://img4.hostingpics.net/pics/903380tb2.jpg
Is someone here knows what the problem is ? Thanks.
Regrettably, tool bars only function correctly when embedded in a QMainWindow. The good news is that you can use a QMainWindow as if it were a widget. You can parent it to another widget, and then it won't be a standalone window. I've done this, and it works well. I was creating the objects using Qt Designer, and I had to remove the QMainWindow menu bar because Designer creates that automatically.
It's not an intuitive thing to do, but it works just fine, and it's a fairly easy change. A well-written comment explaining why you did that would probably be welcomed by anyone else reading the code in the future...
Thank you for your answer, I tried to test with a QMainWindow but it completely messed up the layout on which I worked and as it's a complex window (a lot of people worked on it in the past) and I have to finish my work soon I preferred to try a new approach. So after some research on the web I found that it's possible to do that I want even if the toolbar is not into a QMainWindow, but I have to replace all QWidget's that I want to have into QToolBar by a class which derived of QWidgetAction's, and instantiate them into QWidgetAction::createWidget() method. So I did this code which works correctly :
main.cpp :
#include <QApplication>
#include <QtGui/QWindow>
#include <QToolbar>
#include <QVBoxLayout>
#include <QMainWindow>
#include <QPushButton>
#include <QAction>
#include <QIcon>
#include <QLineEdit>
#include <QSlider>
#include <QVariant>
#include <QCheckBox>
#include <QWidgetAction>
#include "QMyWidgetAction.h"
void test2(QApplication& app);
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
test2(app);
return app.exec();
}
void test2(QApplication& app)
{
QWidget* w = new QWidget;
QHBoxLayout* l1 = new QHBoxLayout;
l1->addWidget(new QPushButton("item11"));
l1->addWidget(new QPushButton("item12"));
l1->addWidget(new QPushButton("item13"));
l1->addWidget(new QPushButton("item14"));
QHBoxLayout* l2 = new QHBoxLayout;
l2->addSpacerItem(new QSpacerItem(50, 20, QSizePolicy::MinimumExpanding,QSizePolicy::Fixed) );
l2->setAlignment(Qt::AlignJustify);
QHBoxLayout* l3 = new QHBoxLayout;
QToolBar* tb = new QToolBar;
l3->addWidget(tb);
QAction* item31 = new QAction(QIcon(":/images/cut.png"), "cut");
QAction* item32 = new QAction(QIcon(":/images/copy.png"), "copy");
QAction* item33 = new QAction(QIcon(":/images/open.png"), "open");
QAction* item34 = new QAction(QIcon(":/images/paste.png"), "past");
QAction* item35 = new QAction(QIcon(":/images/save.png"), "save");
QLineEdit* searchBar = new QLineEdit;
QMyWidgetAction* widgetAction = new QMyWidgetAction(tb);
QLineEditAction* lineEditAction = new QLineEditAction(tb);
tb->addSeparator();
tb->addWidget(searchBar);
tb->addAction(item31);
tb->addAction(item32);
tb->addAction(item33);
tb->addAction(item34);
tb->addAction(item35);
tb->addAction(widgetAction);
tb->addAction(lineEditAction);
QVBoxLayout* mainLayout = new QVBoxLayout;
QHBoxLayout* topLayout = new QHBoxLayout;
topLayout->addLayout(l1);
topLayout->addLayout(l2);
topLayout->addLayout(l3);
QHBoxLayout* bottomLayout = new QHBoxLayout;
bottomLayout->addWidget(new QPushButton);
mainLayout->addLayout(topLayout);
mainLayout->addLayout(bottomLayout);
w->setLayout(mainLayout);
w->show();
}
QMyWidgetAction.h :
#ifndef QMAYAWIDGETACTION_H
#define QMAYAWIDGETACTION_H
#include <QObject>
#include <QWidget>
#include <QWidgetAction>
class QLineEdit;
class QMyWidgetAction : public QWidgetAction
{
Q_OBJECT
public:
QMyWidgetAction(QWidget* parent);
QWidget* createWidget(QWidget* parent);
};
class QLineEditAction : public QWidgetAction
{
Q_OBJECT
public:
QLineEditAction(QWidget* parent);
QWidget* createWidget(QWidget* parent);
protected slots:
virtual void searchTextChanged(const QString& text);
private:
QLineEdit* fWidget;
};
#endif // QMAYAWIDGETACTION_H
QMyWidgetAction.cpp :
#include <QApplication>
#include <QtGui/QWindow>
#include <QToolbar>
#include <QVBoxLayout>
#include <QMainWindow>
#include <QPushButton>
#include <QAction>
#include <QIcon>
#include <QLineEdit>
#include <QSlider>
#include <QVariant>
#include <QCheckBox>
#include <QWidgetAction>
#include "QMyWidgetAction.h"
QMyWidgetAction::QMyWidgetAction(QWidget* parent)
: QWidgetAction(parent)
{
}
QWidget* QMyWidgetAction::createWidget(QWidget* parent)
{
QPushButton* widget = new QPushButton("bouton", parent);
widget->setMinimumSize(100, 30);
return widget;
}
QLineEditAction::QLineEditAction(QWidget* parent)
: QWidgetAction(parent)
{
}
QWidget* QLineEditAction::createWidget(QWidget* parent)
{
fWidget = new QLineEdit(parent);
connect(fWidget, SIGNAL(textChanged(QString)), this, SLOT(searchTextChanged(QString)));
fWidget->setMinimumSize(100, 30);
return fWidget;
}
void QLineEditAction::searchTextChanged(const QString& text)
{
fWidget->setMinimumWidth(fWidget->minimumWidth() + 10);
}
So now here is what I get when I reduce the window width :
So the result is correct (and controls works, I tested them), but now I would like to know if it's possible to display the extension list horizontally instead of vertically ? (I mean "past" action at the right of "open" action, "save" action at the right of past action etc.) Thanks for your help.

Qt3 vs Qt5 programming syntax

Hi I'm teaching myself Qt based on Qt 5.7.0 (MSVC 2013, 32 bit), Qt Creator 4.1.0 - community edition. I am using an book, "Programming with Qt, 2nd Edition" by Matthias Kalle Dalheimer which focuses on QT3. One of the exercises is to have a slider which uses the LCD number display. There are also two buttons (add, subtract) to change the slider and LCD display. I was not able to get the book code to work because there have been major syntax changes.
I was able to get my code to work using the Qt designer but I want to do it without that as well. How can I do that? I was thinking of using events but I couldn't figure out the syntax.
Here is the snippets from the book.
QObject::connect(decrement, SIGNAL(clicked()), myslider, SLOT(subtractStep()));
QObject::connect(increment, SIGNAL(clicked()), myslider, SLOT(addStep()));
These are the error messages from the console for my code below in main.cpp:
"QObject::connect: No such slot QSlider::SingleStep()in ..\ProgrammingQt\main.cpp:31
QObject::connect: No such signal QSlider::triggerAction(SliderSingleStepAdd) in ..\ProgrammingQt\main.cpp:32"
Here is my code without the ui. - main.cpp
#include <iostream>
#include <qapplication.h>
#include <qwidget.h>
#include <qslider.h>
#include <qlcdnumber.h>
#include <qpushbutton.h>
#include <qstring.h>
using namespace std;
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QWidget *widget = new QWidget();
widget->setGeometry(400, 300, 170, 150);
QSlider *slider = new QSlider(Qt::Horizontal, widget);
slider->setGeometry(10, 10, 150,30);
QLCDNumber *lcd = new QLCDNumber(2, widget);
lcd->setGeometry(60, 50, 50, 50);
lcd->display(1);
QObject::connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
QPushButton *addBtn = new QPushButton("ADD ONE", widget);
addBtn->setGeometry(10, 110, 50, 30);
//QObject::connect(addBtn, SIGNAL(clicked(bool)), slider, SLOT(SliderSingleStepAdd()));
//QObject::connect(addBtn, SIGNAL(clicked(bool)), slider, SLOT(SingleStep()));
//QObject::connect(slider, SIGNAL(triggerAction(SliderSingleStepAdd)), lcd, SLOT(display(int)));
QPushButton *minusBtn = new QPushButton("MINUS ONE", widget);
minusBtn->setGeometry(100, 110, 60, 30);
// QObject::connect(minusBtn, SIGNAL(clicked(bool)), slider, SLOT (SliderSingleStepSub()));
QObject::connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
widget->setWindowTitle("LCD Number");
widget->show();
return app.exec();
}
Here is the code using the Qt Designer: mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_slider_valueChanged(int value)
{
ui->lcd->display(value);
}
void MainWindow::on_addBtn_clicked()
{
int incVal = ui->slider->value();
incVal++;
ui->slider->setValue(incVal);
ui->lcd->display(incVal);
}
void MainWindow::on_minusBtn_clicked()
{
int decVal = ui->slider->value();
decVal--;
ui->slider->setValue(decVal);
ui->lcd->display(decVal);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSlider>
#include <QLCDNumber>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_slider_valueChanged(int value);
void on_addBtn_clicked();
void on_minusBtn_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
The slots SliderSingleStepAdd, SingleStep or SliderSingleStepSub are not found because there are not defined in the object slider.
According to the documentation,
All classes that inherit from QObject or one of its subclasses (e.g.,
QWidget) can contain signals and slots.
So you need a class where you must implement your required signals and slots.
For example, your main should be something like this:
#include <iostream>
#include <qapplication.h>
#include <qwidget.h>
#include <qslider.h>
#include <qlcdnumber.h>
#include <qpushbutton.h>
#include <qstring.h>
#include <myclass.h>
using namespace std;
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MyClass myClass;
QWidget *widget = new QWidget();
widget->setGeometry(400, 300, 170, 150);
QSlider *slider = new QSlider(Qt::Horizontal, widget);
slider->setGeometry(10, 10, 150,30);
QLCDNumber *lcd = new QLCDNumber(2, widget);
lcd->setGeometry(60, 50, 50, 50);
lcd->display(1);
QObject::connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
QPushButton *addBtn = new QPushButton("ADD ONE", widget);
addBtn->setGeometry(10, 110, 50, 30);
QObject::connect(addBtn, SIGNAL(clicked(bool)), &myClass, SLOT(SliderSingleStepAdd()));
QObject::connect(addBtn, SIGNAL(clicked(bool)), &myClass, SLOT(SingleStep()));
// QObject::connect(slider, SIGNAL(triggerAction(SliderSingleStepAdd)), lcd, SLOT(display(int)));
QPushButton *minusBtn = new QPushButton("MINUS ONE", widget);
minusBtn->setGeometry(100, 110, 60, 30);
QObject::connect(minusBtn, SIGNAL(clicked(bool)), &myClass, SLOT(SliderSingleStepSub()));
QObject::connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
widget->setWindowTitle("LCD Number");
widget->show();
return app.exec();
}
And you should have a class like the following one:
#ifndef MYCLASS_H
#define MYCLASS_H
#include <iostream>
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass(): QObject() {}
virtual ~MyClass() {}
public slots:
void SliderSingleStepAdd ()
{
std::cout << "SliderSingleStepAdd" << std::endl;
}
void SingleStep ()
{
std::cout << "SingleStep" << std::endl;
}
void SliderSingleStepSub ()
{
std::cout << "SliderSingleStepSub" << std::endl;
}
};
#endif // MYCLASS_H
In my opinion, all your objects (slider, lcd and buttons) should be in a class that inherits from QWidget so you can connect those objects. This should be also necessary in case of the following connect:
QObject::connect(slider, SIGNAL(triggerAction(SliderSingleStepAdd)), lcd, SLOT(display(int)));

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.

How to make QTextBrowser scale nicely within QVBoxLayout?

I'd like to display a list of short html snippets in a scrollable list. Thus i place a QVboxLayout into a QScrollArea and add multiple QTextBrowsers:
#include <QApplication>
#include <QScrollArea>
#include <QTextBrowser>
#include <QVBoxLayout>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QScrollArea scrollArea;
scrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea.setWidgetResizable(true);
QWidget *scrollWidget = new QWidget;
QVBoxLayout *layout = new QVBoxLayout;
for(int i=0;i<6;i++) {
QString text = "some <b>text</b> ";
for(int j=0;j<i;j++) text += text;
QTextBrowser *browser = new QTextBrowser();
QTextDocument *doc = new QTextDocument(browser);
doc->setHtml(text);
browser->setDocument(doc);
layout->addWidget(browser);
}
scrollWidget->setLayout(layout);
scrollArea.setWidget(scrollWidget);
scrollArea.show();
return app.exec();
}
My problem: The boxes all have the same size. I want them to be as big as necessary, but not bigger. How can i make the textbrowsers to take only as much space as they really need?
Ok, i found a solution derived from http://www.qtcentre.org/threads/39839-QTextBrowser-height-adjusted-to-content. Is there a simpler/mor elegant solution?
#include <QApplication>
#include <QScrollArea>
#include <QTextBrowser>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QDebug>
#include <QShowEvent>
#include <QResizeEvent>
class MyBrowser : public QTextBrowser {
private:
QTextDocument *doc;
public:
MyBrowser(const QString &text, QWidget *parent = 0) : QTextBrowser(parent) {
doc = new QTextDocument(this);
doc->setHtml(text);
setDocument(doc);
}
void adjust() {
QMargins margins = contentsMargins();
int width = size().width() -
margins.left() - margins.right() - doc->documentMargin()*2;
doc->setPageSize(QSizeF(width,-1));
int height = doc->size().height() + margins.top() + margins.bottom();
setMaximumHeight(height);
setMinimumHeight(height);
}
void showEvent(QShowEvent *) {
adjust();
}
void resizeEvent(QResizeEvent *) {
adjust();
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QScrollArea scrollArea;
scrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea.setWidgetResizable(true);
QWidget *scrollWidget = new QWidget;
QVBoxLayout *layout = new QVBoxLayout;
for(int i=0;i<6;i++) {
QString text = "some <b>text</b> ";
for(int j=0;j<i;j++) text += text;
MyBrowser *browser = new MyBrowser(text, scrollWidget);
layout->addWidget(browser, 0, 0);
}
scrollWidget->setLayout(layout);
scrollArea.setWidget(scrollWidget);
scrollArea.show();
return app.exec();
}
Instead of doing
layout->addWidget(browser);
You should do:
layout->addWidget(browser, 0, 0);
This will tell QT not to stretch the widget according to its layout.

Resources