PDA

View Full Version : Add QScrollArea to QDialog



cpsmusic
22nd June 2011, 17:23
Hi,

Is it possible to create a Qdialog with a QScrollArea?

I've tried the following but neither method works:



QScrollArea scrollArea;
scrollArea.viewport()->setBackgroundRole(QPalette::Dark);
scrollArea.viewport()->setAutoFillBackground(true);
scrollArea.setWindowTitle(QObject::tr("Mixer Strip"));
scrollArea.setHorizontalScrollBarPolicy(Qt::Scroll BarAlwaysOn);
scrollArea.setVerticalScrollBarPolicy(Qt::ScrollBa rAlwaysOn);
scrollArea.setParent(this);
scrollArea.show();




QScrollArea scroll;
scroll.setHorizontalScrollBarPolicy(Qt::ScrollBarA lwaysOn);
scroll.setVerticalScrollBarPolicy(Qt::ScrollBarAlw aysOn);
QWidget *viewport = new QWidget;
scroll.setWidget(viewport);
scroll.setWidgetResizable(true);
QVBoxLayout *l = new QVBoxLayout(viewport);
setLayout(l);
scroll.show();


Cheers,

Chris

Rachol
22nd June 2011, 19:31
The second example seems to be correct, but what is the parent of QScrollArea?

cpsmusic
23rd June 2011, 02:03
If I change the code to the following I still don't see the QScrollArea:



QScrollArea scroll;
scroll.setHorizontalScrollBarPolicy(Qt::ScrollBarA lwaysOn);
scroll.setVerticalScrollBarPolicy(Qt::ScrollBarAlw aysOn);
QWidget *viewport = new QWidget;
scroll.setWidget(viewport);
scroll.setWidgetResizable(true);
QVBoxLayout *l = new QVBoxLayout(viewport);
setLayout(l);
scroll.setParent(this);
scroll.show();

Santosh Reddy
23rd June 2011, 02:23
Create QScrollArea on heap

QScrollArea * scroll = new QScrollArea(this);

cpsmusic
23rd June 2011, 14:12
Hi,

I tried the following:



setWindowTitle("Mixer Strip");
setMinimumSize(600, 350);

QScrollArea *scroll = new QScrollArea(this);
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn );
scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
QWidget *viewport = new QWidget;
scroll->setWidget(viewport);
scroll->setWidgetResizable(true);
QHBoxLayout *l = new QHBoxLayout(viewport);
setLayout(l);


Using this code the scrollbars are visible however they're positioned in the top left corner of the dialog and don't change position when the dialog is resized. I can just makeout the widgets that are added.

Cheers,

Chris

Santosh Reddy
23rd June 2011, 17:36
If you are adding widgets to QHBoxLayout *l then


QHBoxLayout *l = new QHBoxLayout(viewport);
viewport->setLayout(l);

cpsmusic
24th June 2011, 02:14
I tried the following:



QScrollArea *scroll = new QScrollArea(this);
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn );
scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
QWidget *viewport = new QWidget;
scroll->setWidget(viewport);
scroll->setWidgetResizable(true);
QHBoxLayout *l = new QHBoxLayout(viewport);
viewport->setLayout(l);


The scrollbars are visible however they're still not attached to the dialog.

I also tried removing the call to


scroll->setWidget(viewport)

In this case, the scrollbars are visible (and the size of the area they contain is larger) but they're still not attached to the dialog.

Santosh Reddy
24th June 2011, 02:57
I think I got you problem, not sure how you are using QDialog, let me put both the ways, check which is applicable to you

1. If sub-classing QDialog, then in the constructor of the sub-calss

MyDialog::MyDialog(QWidget * parent) : QDialog(parent)
{
QScrollArea *scroll = new QScrollArea(this);
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn );
scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);

QWidget *viewport = new QWidget(this);
scroll->setWidget(viewport);
scroll->setWidgetResizable(true);

QHBoxLayout *l = new QHBoxLayout(viewport);
viewport->setLayout(l);

// add needed widgets to layout "l"
for(int i = 0; i < 10; i++)
l->addWidget(new QPushButton());

// Add a layout for QDialog
QHBoxLayout *dialog_layout = new QHBoxLayout(this);
dialog_layout->addWidget(scroll); // add scroll to the QDialog's layout
setLayout(dialog_layout);

// show dialog
show();
}

1. If using QDialog directly, then

QDialog * dialog = new QDialog(this); //my be you already have this

QScrollArea *scroll = new QScrollArea(dialog);
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn );
scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);

QWidget *viewport = new QWidget(dialog);
scroll->setWidget(viewport);
scroll->setWidgetResizable(true);

QHBoxLayout *l = new QHBoxLayout(viewport);
viewport->setLayout(l);

// add needed widgets to layout "l"
for(int i = 0; i < 10; i++)
l->addWidget(new QPushButton());

// Add a layout for QDialog
QHBoxLayout *dialog_layout = new QHBoxLayout(dialog);
dialog->setLayout(dialog_layout);
dialog->layout()->addWidget(scroll); // add scroll to the QDialog's layout
dialog->show();


Edit: your actual problem is you are adding QScrollArea to QDialog, where as you should be adding QScrollArea to QDialog's layout

cpsmusic
24th June 2011, 10:15
Thanks, that fixed the problem. :)

cpsmusic
24th June 2011, 16:02
Although I've got the scrollbars showing now, I've run into another problem - the widgets are being spread too widely in the horizontal direction. What I'd like is for the widgets to bunch up on the left hand side of the layout. I tried using a QGridLayout however this didn't fix the problem. The code I'm using is below. One thing, the widget is a custom widget that has a fixed size. I'm implemented the sizeHint method returning the size of the widget.




MixerDialog::MixerDialog(QWidget *parent) :
QDialog(parent) {

setWindowTitle("Mixer");
setMinimumSize(600, 350);

QScrollArea *scrollArea = new QScrollArea(this);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn );
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);

QWidget *viewport = new QWidget(this);
scrollArea->setWidget(viewport);
scrollArea->setWidgetResizable(true);

QHBoxLayout *hlayout = new QHBoxLayout(viewport);
hlayout->setMargin(0);
hlayout->setSpacing(0);
viewport->setLayout(hlayout);

// add needed widgets to layout "hlayout"
int numberOfChannels = 10;
for(int i = 0; i < numberOfChannels; i++) {
MixerStrip *strip = new MixerStrip;
hlayout->addWidget(strip);
}
hlayout->addStretch();

// Add a layout for QDialog
QHBoxLayout *dialog_layout = new QHBoxLayout(this);
dialog_layout->setMargin(0);
dialog_layout->setSpacing(0);
dialog_layout->addWidget(scrollArea); // add scrollArea to the QDialog's layout
setLayout(dialog_layout);

// show dialog
show();
}

Santosh Reddy
24th June 2011, 18:42
You code should work, hlayout->addStretch(); does the magic...Post a screenshot indicating the of the probelm

cpsmusic
25th June 2011, 09:36
Here's a screenshot of how the widgets are being laid out:

Grab.tiff (http://www.labyrinth.net.au/~cpsmusic/Grab.tiff)

The addStretch() doesn't seem to push them left.

Rachol
25th June 2011, 09:52
Have you tried hlayout->setSizeConstraint ( QLayout::SetFixedSize ); ?

cpsmusic
25th June 2011, 10:17
Have you tried hlayout->setSizeConstraint ( QLayout::SetFixedSize ); ?

I just tried what you've suggested however it didn't make any difference.

Rachol
25th June 2011, 10:28
Can you try your code with QPushButton instead of MixerStrip and then see if the widgets are being laid out normally?

Santosh Reddy
25th June 2011, 11:04
Ok, Your problem seems to be with in mixer widget, set proper size constraint to it, and also don't use any spacers if designing from Qt Designer (i mean don't place spacers in such a position which will cause the mixer widget to fit the area available)

cpsmusic
25th June 2011, 12:00
I'm not clear about how to set the size constraint in the widget. I tried adding:



setSizeConstraint ( QLayout::SetFixedSize );


to the MixerStrip (which inherits from QWidget) but the code won't build.

I'm not using Qt Designer so I don't think that's the problem.

Rachol
25th June 2011, 12:09
setSizeConstraint -> this is QLayout API, so of course it won't work. Have you tried what I suggested in my previous post? How did it work? How is your MixerStrip widget implemented?

Santosh Reddy
25th June 2011, 12:30
You can use
hlayout.setSizeConstraint(QLayout::SetMinimumSize) ;This will set the layout and the containing widget to smallest size possible.

cpsmusic
25th June 2011, 13:28
Can you try your code with QPushButton instead of MixerStrip and then see if the widgets are being laid out normally?

If I use QPushButtons they're laid out correctly.

Here's the code for the MixerStrip:



#include "mixerstrip.h"

MixerStrip::MixerStrip(QWidget *parent) :
QWidget(parent)
{
QSlider *volSlider = new QSlider(Qt::Vertical);
volSlider->setMinimum(0);
volSlider->setMaximum(100);
QPalette pal = volSlider->palette();
pal.setColor(volSlider->backgroundRole(), QColor(128, 128, 128));
volSlider->setPalette(pal);
volSlider->setAutoFillBackground(TRUE);
volSlider->setGeometry(0,0,20,220);
volSlider->setParent(this);

Meter *meter = new Meter;
meter->setGeometry(20,0,50,220);
meter->setParent(this);

QPushButton *muteButton = new QPushButton("M");
QPushButton *soloButton = new QPushButton("S");
muteButton->setCheckable(true);
soloButton->setCheckable(true);

pal = muteButton->palette();
pal.setColor(muteButton->backgroundRole(), QColor(128, 128, 128));
muteButton->setPalette(pal);
muteButton->setAutoFillBackground(TRUE);
pal = soloButton->palette();
pal.setColor(soloButton->backgroundRole(), QColor(128, 128, 128));
soloButton->setPalette(pal);
soloButton->setAutoFillBackground(TRUE);

muteButton->setGeometry(0,220,70,20);
soloButton->setGeometry(0,240,70,20);
muteButton->setParent(this);
soloButton->setParent(this);

QSlider *panSlider = new QSlider(Qt::Horizontal);
panSlider->setMinimum(-100);
panSlider->setMaximum(100);
panSlider->setValue(0);
pal = panSlider->palette();
pal.setColor(panSlider->backgroundRole(), QColor(128, 128, 128));
panSlider->setPalette(pal);
panSlider->setAutoFillBackground(TRUE);
panSlider->setGeometry(0,260,70,20);
panSlider->setParent(this);

QLineEdit *trackName = new QLineEdit();
trackName->setAlignment(Qt::AlignCenter);
trackName->setText("Track");
trackName->setGeometry(0,280,70,20);
trackName->setParent(this);

QObject::connect(volSlider, SIGNAL(valueChanged(int)), meter, SLOT(valueChanged(int)));
volSlider->setValue(0);

setFixedSize(size());
//setSizeConstraint ( QLayout::SetFixedSize );
}

QSize MixerStrip::sizeHint() const
{
QSize size(70,300);

return size;
}



You can use
hlayout.setSizeConstraint(QLayout::SetMinimumSize) ;This will set the layout and the containing widget to smallest size possible.

I tried what you suggested but it still doesn't fix the problem.

Rachol
25th June 2011, 16:21
Ok, now it is easy:)

There are couple of ways to solve your problem.

1. The easiest way would be to place a layout inside your MixerStrip class and then place all the widgets inside the layout instead of hardcoding all coordinates.
2. Re-implement minimumSizeHint and maximumSizeHint. You could return the same value that you return in your sizeHint implementation.

cpsmusic
26th June 2011, 04:26
Ok, now it is easy:)

There are couple of ways to solve your problem.

1. The easiest way would be to place a layout inside your MixerStrip class and then place all the widgets inside the layout instead of hardcoding all coordinates.
2. Re-implement minimumSizeHint and maximumSizeHint. You could return the same value that you return in your sizeHint implementation.

I tried the second suggestion (see below) however the widgets are still spread out.



#include "mixerstrip.h"

MixerStrip::MixerStrip(QWidget *parent) :
QWidget(parent)
{
QSlider *volSlider = new QSlider(Qt::Vertical);
volSlider->setMinimum(0);
volSlider->setMaximum(100);
QPalette pal = volSlider->palette();
pal.setColor(volSlider->backgroundRole(), QColor(128, 128, 128));
volSlider->setPalette(pal);
volSlider->setAutoFillBackground(TRUE);
volSlider->setGeometry(0,0,20,220);
volSlider->setParent(this);

Meter *meter = new Meter;
meter->setGeometry(20,0,50,220);
meter->setParent(this);

QPushButton *muteButton = new QPushButton("M");
QPushButton *soloButton = new QPushButton("S");
muteButton->setCheckable(true);
soloButton->setCheckable(true);

pal = muteButton->palette();
pal.setColor(muteButton->backgroundRole(), QColor(128, 128, 128));
muteButton->setPalette(pal);
muteButton->setAutoFillBackground(TRUE);
pal = soloButton->palette();
pal.setColor(soloButton->backgroundRole(), QColor(128, 128, 128));
soloButton->setPalette(pal);
soloButton->setAutoFillBackground(TRUE);

muteButton->setGeometry(0,220,70,20);
soloButton->setGeometry(0,240,70,20);
muteButton->setParent(this);
soloButton->setParent(this);

QSlider *panSlider = new QSlider(Qt::Horizontal);
panSlider->setMinimum(-100);
panSlider->setMaximum(100);
panSlider->setValue(0);
pal = panSlider->palette();
pal.setColor(panSlider->backgroundRole(), QColor(128, 128, 128));
panSlider->setPalette(pal);
panSlider->setAutoFillBackground(TRUE);
panSlider->setGeometry(0,260,70,20);
panSlider->setParent(this);

QLineEdit *trackName = new QLineEdit();
trackName->setAlignment(Qt::AlignCenter);
trackName->setText("Track");
trackName->setGeometry(0,280,70,20);
trackName->setParent(this);

QObject::connect(volSlider, SIGNAL(valueChanged(int)), meter, SLOT(valueChanged(int)));
volSlider->setValue(0);

setFixedSize(size());
//setSizeConstraint ( QLayout::SetFixedSize );
}

QSize MixerStrip::sizeHint() const
{
QSize size(70,300);

return size;
}

QSize MixerStrip::minimumSizeHint() const
{

QSize size(70,300);

return size;
}

QSize MixerStrip::maximumSize()
{
QSize size(70,300);

return size;
}

Santosh Reddy
26th June 2011, 06:19
Ok, I hope this should fix your problem for sure.

When you implement size hints on your MixerStrip, then you don't need to set it to fixed size explicitly. Just remove the following statement at the end of MixerStrip Ctor, you should be done, worrying.:cool:

//setFixedSize(size());

cpsmusic
26th June 2011, 08:21
Thanks, that last change solved the problem! Thanks very much, the people on this forum are very helpful.