PDA

View Full Version : Adding a scrollbar to a QWidget



qtUser500
1st September 2009, 15:23
I am using Qt4.4.3. Following is my issue;

1. I have a QWidget which I use to create a tag cloud view (a weighted list placed in a rectangle area where the words (text) are of varying size). See attachment.
2. The QWidget which has the tag cloud is created at runtime
3. The problem is when the amount of text is large, and its area exceeds that of the container QWidget, a ScrollBar DOESN't appear. You can see this in the attachment

4. I tried enclosing the the QWidget into a QScrollArea as follows, but it doesn't work, the scrollbar doesn't appear.


QWidget* tagCloudDisplay; // This is the widget which holds the tag cloud

QScrollArea *tagCloudScrollArea = new QScrollArea;
tagCloudScrollArea->setGeometry(tagCloudDisplay->geometry());
tagCloudScrollArea->setWidget(mainWidget->tagCloudDisplay); // MainWidget is the container widget i.e. the window itself
tagCloudScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
tagCloudScrollArea->setWidgetResizable(true);

5. Is it possible to havea ScrollArea for a QWidget, or should I be using a different type of widget instead of QWidget Eg a QTextEdit to create the tag cloud?

Any advise or suggestions will really be appreciated.
Thanks.

Boron
1st September 2009, 15:44
You have seen the little example in the docs http://qt.nokia.com/doc/4.5/qscrollarea.html#details?
Doesn't it work that way?

victor.fernandez
1st September 2009, 15:48
You are resizing the scroll area to the size of the widget. That makes the scrollarea bigger so that it doesn't need scrollbars. You can resize the widget itself if you want, but not the scrollarea.

You have also set widgetResizable to true, which makes the scroll area resize the widget. From the Qt docs:


If this property is set to true, the scroll area will automatically resize the widget in order to avoid scroll bars where they can be avoided, or to take advantage of extra space.


QWidget* tagCloudDisplay; // This is the widget which holds the tag cloud
tagCloudDisplay->resize(QSize(1000, 1000)); // optional: make it big enough

QScrollArea *tagCloudScrollArea = new QScrollArea;
tagCloudScrollArea->setWidget(tagCloudDisplay);

qtUser500
1st September 2009, 16:37
Boron: Yes, the first thing I tried was that example.

Victor: Thanks for the details.

The most puzzling part is when I add the ScrollArea, the window itself doesn't display :confused:

Example I tried what victor suggested:


QWidget* tagCloudDisplay; // This is the widget which holds the tag cloud
tagCloudDisplay->resize(QSize(1000, 1000)); // optional: make it big enough

QScrollArea *tagCloudScrollArea = new QScrollArea;
tagCloudScrollArea->setWidget(tagCloudDisplay);


But then there is no window displayed at all.
Note: This tagCloudDisplay in turn contains a QTextEdit in which a QStringList populates the textEdit with the words.

wysota
1st September 2009, 16:43
Did you implement sizeHint() for your widget? Did you apply a layout to your widget?

victor.fernandez
1st September 2009, 16:56
Did you call mainWidget->show() somewhere?

qtUser500
1st September 2009, 19:30
Did you implement sizeHint() for your widget? Did you apply a layout to your widget?

Wysota, I tried a couple of approaches:

Approach 1
-------------
Result: No Window displayed


QWidget* tagCloudDisplay; // This is the widget which holds the tag cloud
QVBoxLayout *vbLayout = new QVBoxLayout;
tagCloudDisplay->setLayout(vbLayout);
tagCloudDisplay->setMaximumHeight(100);
tagCloudDisplay->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);

QScrollArea *scroll = new QScrollArea;
scroll->setWidget(tagCloudDisplay);


Approach 2
-------------
Result:The program compiles but crashes at runtime.



// Function 1
void update()
{
:
// Layout
QVBoxLayout *cloudVerticalBoxLayout = new QVBoxLayout;
cloudVerticalBoxLayout->addWidget(MainWidget->tagCloudDisplay);
mainWidgetr->setLayout(cloudVerticalBoxLayout);

// Setting the scrollArea
QScrollArea *tagCloudScrollArea = new QScrollArea;
tagCloudScrollArea->setWidget(tagCloudDisplay );


mainWidget->updateTagCloud(); // Calls function below which adds the tag cloud words to the widget
}

// Function 2
void updateTagCloud()
{
QWidget* tagCloudDisplay; // This is the widget which holds the tag cloud
:
:
QTextEdit *textAreaForTags = new QTextEdit;
textAreaForTags->setWindowFlags(Qt::ToolTip);
:
// Code here to retreive required words
:

// Start of loop
tagCloudArray[i].setParent(tagCloudDisplay);
:
// End of loop

}



Questions:
1. Do I need a layout in this case? As there is only one widget which contains the QTextEdit?
2. What is the order in which the components are build?

Any suggestions will be appreciated.
Thanks once again for your time.

wysota
1st September 2009, 20:28
Hold on... the code above suggests you don't know how to use layouts. Is that true? Can you show us the definition of your tag cloud widget?

qtUser500
1st September 2009, 21:16
Hold on... the code above suggests you don't know how to use layouts. Is that true?

Well, yes I am learning, and have been looking at different forum threads and QT documentation to understand why it is not working in my application, and if I am getting the order wrong or missing out on calling cetain settings.
So, yes, I am not 100% comfortable in the way the layouts work, but am eager to learn the right approach.


Can you show us the definition of your tag cloud widget?
I have put snippets of what my code looks like hence it might not be complete.
The mainWidget inherits from another user-defined class (which has some customised functions ) and this in turn inherits from QWidget

ie. mainWidget--> myCustomisedClass->QWidget

Thank you once again for your patience.

wysota
2nd September 2009, 08:23
I don't care what it is derived from. I only care if it has a proper layout or not. Please provide the full unmodified contents of the constructor.

qtUser500
2nd September 2009, 16:51
There is no layout specified in the constructor.

I tried implementing layouts in the ui, and have enclosed them (both ui's: before and after my changes)

- To give you additional information of this Window. It has an option of either viewing words as a list (QListWidget) or as a tag cloud (QWidget)
Before
- In the UI file, there is only the QlistWidget added , there is no layout present. (attachment: tagCloud-before.ui)
- But when the application runs for the listWidget the scrollbar appears when needed.
- the tag cloud widget is added at runtime.

After
- I made modifications to the ui file (tagCloud-after.ui), by enclosing the QListWidget in a ScrollArea.
- I put them in a grid-layout, as when I tried other layouts the QListWidget was not expanding as the window is resized.
Question: Is this the correct layout to use? If not, if you have just one widget in a scrollArea, which is the preferred layout?
- at runtime I tried to hookup the tagcloud to the scrollArea



Ui::TagCloud ui_tagCloud;
ui_tagCloud.scrollAreaWords->setWidget(tagCloudDisplay);

The application starts to run but hangs after awhile.

Is this a good approach?

wysota
2nd September 2009, 18:25
The one "after" is better. But still, I was asking about your tag cloud (tagCloudDisplay) and not the scroll area window.

qtUser500
2nd September 2009, 19:38
Thanks Wyosta.

In reply to your questions:
- tagCloudDisplay is a member variable.
- Details are as follows

Class 1 : MyApplication


void MyApplication::createTagWindow()
{
TagWindowWidget* tagWindow = new TagWindowWidget; // This class inherits from a customised class which in turn inherits from QObject
Ui::TagCloud ui_TagCloud; // This is the ui attached
ui_tagCloud.setupUi(tagWindow );

}

Class 2: WordsManager (inherits directly from QObject)


void WordsManager::loadWordWindow( QWidget *tagCloud, QListWidget *wordList)
{

WordsDisplay *wordsDisplayWindow = new WordsDisplay(tagCloud, wordList)
}


The WordsDisplay class structure is as follows:



class WordsDisplay : public QObject
{

Q_OBJECT

protected:
QWidget* tagCloudDisplay;
QListWidget* wordListDisplay;
:
:

}


- I am trying to associate the 'scrollArea' in the ui to the tagCloudDisplay. Would this be the solution?
- How can I do this with the structure I have? As I am not able to retrieve the ui.scrollArea after the tagCloudDisplay is instantiated

wysota
2nd September 2009, 19:48
We're not getting anywhere...

I'm asking you to present your code because I want to have a look at it, not because I want to steal something from you. If you want me to help you, you have to provide the code I ask you for, not the one you feel like sharing at the moment.

I need to know how the tag cloud is composed. It probably doesn't have a layout applied and I'm pretty certain you didn't reimplement sizeHint() for your widget. Therefore the widget has no real size and will not make the scroll area have scrollbars ever.

Furthermore please read this: Using a Designer .ui File in Your Application - please follow one of the recommended approaches.