Scroll Area Added and Set Up but No Scrollbar Appears - c++

I've seen and tried various QT scrollArea solutions over the past 2 days but none of them work for me. Here's my scroll area setup code as it stands in the MainWindow constructor. This builds and runs without error but doesn't do anything. The scrollArea and ui->Contents have already been set up in the form using QTcreator and the needed widgets have been moved into the scrollArea.
ui->scrollArea->installEventFilter(this);
ui->scrollArea->setMouseTracking(true);
ui->scrollArea->setWidget(ui->Contents);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setSizeConstraint(QLayout::SetMinimumSize);
ui->scrollArea->setLayout(layout);
The last line seems interchangeable with:
layout->addWidget(ui->scrollArea)
but neither one changes the result, which is a fully-functioning application but without the scroll area I need.

I had similar problem which i solved by creating scrollArea and it's contents via code rather than form and only then using setWidget() method. I described the problem in this thread.
In your case code should look something like this:
QScrollArea *scrollArea;
scrollArea = new QScrollArea(this);
scrollArea->installEventFilter(this);
scrollArea->setMouseTracking(true);
scrollArea->setWidget(Contents);//whatever Contents is, i recommend creating it via code
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setSizeConstraint(QLayout::SetMinimumSize);
scrollArea->setLayout(layout);

Related

Qt remove nested layout

I've got several QHBoxLayout objects nested inside a single QVBoxLayout. I've looked through a number of stackoverflow questions and answers, but I've not been able to find a way to completely remove the layout for the contents of the QScrollArea widget. All the answers I've seen have only made it possible to set the layout again, but when the layout does get set a second time, the objects are still present.
This is the code that I'm working with:
QSignalMapper* sMap = new QSignalMapper(this);
QVBoxLayout* vBox = new QVBoxLayout();
outerVector = 0;
for (vector<vector<QPushButton*>>::iterator o_iter = buttonGrid.begin(); o_iter < buttonGrid.end(); o_iter++) {
int innerVector = 0;
QHBoxLayout* hBox = new QHBoxLayout();
for (vector<QPushButton*>::iterator i_iter = (*o_iter).begin(); i_iter < (*o_iter).end(); i_iter++) {
hBox->addWidget(buttonGrid.at(outerVector).at(innerVector));
sMap->setMapping(buttonGrid.at(outerVector).at(innerVector), ((outerVector * 100) + innerVector));
connect(buttonGrid.at(outerVector).at(innerVector), SIGNAL(clicked()), sMap, SLOT(map()));
innerVector++;
}
vBox->addLayout(hBox);
outerVector++;
}
ui->GameAreaWidgetContents->setLayout(vBox);
connect(sMap, SIGNAL(mapped(int)), this, SLOT(on_buttonGrid_clicked(int)));
Right now, I have this for clearing the layout:
delete hBox;
delete vBox;
ui->GameAreaWidgetContents->layout();
What is the best, and most effective way to clear the contents of the widget?
I believe I've fixed this, This is less of a Qt issue, but more of a lack of clearing the vector<vector<QPushButton*>> buttonGrid object. It looked like the layout wasn't being cleared, because the additional QPushButton objects were being added onto the vector<vector<QPushButton*>> object.
It's a fairly rookie mistake on my behalf.
Updated:
I infer that GameAreaWidgetContents is a QScrollArea. To clear its layout manager, you can do:
delete ui->GameAreaWidgetContents->layout();
The vbox will no longer be the widget's layout manager and any nested children will be deleted automatically by the Qt parenting system.
From the docs on QWidget::setLayout():
If there already is a layout manager installed on this widget, QWidget won't let you install another. You must first delete the existing layout manager (returned by layout()) before you can call setLayout() with the new layout.

Qt QStatusBar wider separator

I am using qt to develop an embedded gui application. I am using 2 QStatusBars to make a menu-like buttons one can see on an osciloscope for example:
My problem is I dont know a proper way of separating the buttons from eachother with a certain width. In the picture you can see I have added couple separators to achieve that, but it doesnt look that way when run on the target.
Is there a better way to separate buttons on QStatusBar with certain width?
I'd prefer you use a blank widget to do the seperation as suggested by Martin, like so;
//the 2 widgets in the status bar
button1 = new QPushButton("Button1");
button2 = new QPushButton("Button2");
//the blank widget. You can set your width with 'setFixedWidth(int)'
widget = new QWidget;
widget->setFixedWidth(50);
widget->setHidden(1);
widget->setVisible(1);
//placing them in the status bar
statusBar = new QStatusBar;
statusBar->addWidget(button1);
statusBar->addWidget(widget);
statusBar->addWidget(button2);

Qt : Qlabel and QPushButton in a QVBoxLayout

I have an issue, when I'm trying to add a QLabel and a QPushbutton object into a QVBoxLayout. The problem is, that it adds too much space between them like in the picture
Here is a code example of creating the layouts and the labels, and adding them. I'm adding the buttons later on, but that is just with another ->addWidget(button).
jobbcimke= new QLabel(trUtf8("Jobb oldal"));
jobbkozepcimke= new QLabel(trUtf8("Jobb part"));
balcimke= new QLabel(trUtf8("Bal oldal"));
balkozepcimke=new QLabel(trUtf8("Bal part"));
jobbfelulet=new QVBoxLayout();
jobbkozepfelulet=new QVBoxLayout();
balkozepfelulet=new QVBoxLayout();
balfelulet=new QVBoxLayout();
osszefogo=new QHBoxLayout();
jobbfelulet->setAlignment(Qt::AlignRight);
jobbkozepfelulet->setAlignment(Qt::AlignRight);
balfelulet->setAlignment(Qt::AlignLeft);
balkozepfelulet->setAlignment(Qt::AlignLeft);
balfelulet->addWidget(balcimke);
balkozepfelulet->addWidget(balkozepcimke);
jobbfelulet->addWidget(jobbcimke);
jobbkozepfelulet->addWidget(jobbkozepcimke);
osszefogo->addLayout(balfelulet);
osszefogo->addLayout(balkozepfelulet);
osszefogo->addLayout(jobbkozepfelulet);
osszefogo->addLayout(jobbfelulet);
setLayout(osszefogo);
How could I remove the space between them, or is there a better method to do this? I've created the labels for the layout size allocation.
If you dig into the documentation there's a setSpacing(int x) method for QLayouts that allows you to edit the spacing in between the elements, you may also need to add some QSpacerItems to get the positioning exactly where you want it, or apply constraints with the setGeometry(QRect rect) method.

wx* layout in wxNotebookPage

i'm trying to program the front-end for a schedule-application. In my main tab should be two lists (one above the other one). But this seems to be impossible (I've sat yesterday the half day and today for three more hours). So this is my result:
And this is the common part of my Code:
// LayoutManagement - Main
sizer = new wxBoxSizer(wxVERTICAL);
this->SetSizer(sizer);
// Tabpane
tab_pane = new wxNotebook(this,TAB_PANE);
sizer->Add(tab_pane,1,wxEXPAND);
// Overview tab
wxBoxSizer *ot_sizer = new wxBoxSizer(wxVERTICAL);
overview_tab = new wxNotebookPage(tab_pane,TAB_OVERVIEW);
overview_tab->SetSizer(ot_sizer);
tab_pane->AddPage(overview_tab,_("Countdown und Nachrichten"),true);
// Schedule
schedule_list = new wxListBox(overview_tab, SCHEDULE_LIST);
ot_sizer->Add(schedule_list,1,wxEXPAND);
// NewsList
news_list = new wxListBox(overview_tab,NEWS_LIST);
ot_sizer->Add(news_list,3,wxEXPAND);
And my header (part):
wxListBox *schedule_list;
wxBoxSizer *sizer;
wxListBox *news_list;
wxNotebook *tab_pane;
wxNotebookPage *overview_tab, *settings_tab, *about_end_tab;
What i'm doing wrong?
Greetings
Michael
(Sorry for my bad english)
The reason this code is not working is that you have called SetSizer() BEFORE adding the widgets to the sizer. You should either move the call to SetSizer AFTER the addition of widgets to the sizer, or force the sizer to redo the layout after the adds.
ot_sizer->Add(news_list,3,wxEXPAND);
// all widgest added to sizer, now arrange layout as specified
ot_sizer->Layout();
This should fix your code for the moment.
A final comment on the structure of your code: you seem to be constructing everything in one large code section. This is not a great idea. As you continue to add elements to your GUI it is going to become very confusing. It is better to subclass each page and create the widgets that belong to each page in the constructor of that page.
class cOverviewTab : public wxNotebookPage
{
public:
cOverviewTab() : wxNotebookPage(tab_pane,TAB_OVERVIEW)
{
wxBoxSizer *ot_sizer = new wxBoxSizer(wxVERTICAL);
ot_sizer->Add( new wxListBox(overview_tab, SCHEDULE_LIST) );
ot_sizer->Add( new wxListBox(overview_tab,NEWS_LIST) );
SetSizer( ot_sizer );
}
};
I had the same problem, and it took me about 2 hours to fix it.
There is no reason to change other lines in your code. You have just to use the wxPanel class instead of wxNotebookPage to create new pages for the wxNotebook object. This is because wxNotebookPage is just a typedef of wxWindow and wxWindow doesn't have some necessary functionality that the wxPanel has.
Your other code doesn't need modifications for this to work, except that it would be really good as noted above to subclass your pages to avoid GUI mess.

setCentralWidget() causing the QMainWindow to crash.. Why?

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
this->setupUi(this);
this->setupActions();
this->setWindowTitle(tr("CuteEdit"));
label = new QLabel(tr("No Open Files"));
this->setCentralWidget(label);
label->setAlignment(Qt::AlignCenter);
}
By above code, I get a GUI like this(Its a screenshot of whole screen, Only observe the window displayed in middle of page of ebook). (I used QT Designer)
Now, i want user to select File->Open.. A Dialog appears and file gets selected.. Its contents are to be displayed in *textEdit widget..
Function for that is below..
void MainWindow::loadFile()
{
QString filename = QFileDialog::getOpenFileName(this);
QFile file(filename);
if (file.open(QIODevice::ReadOnly|QIODevice::Text))
{
label->hide();
textEdit->setPlainText(file.readAll());
mFilePath = filename;
QMainWindow::statusBar()->showMessage(tr("File successfully loaded."), 3000);
}
}
The window crashes at line:-
textEdit->setPlainText(file.readAll());
But if i comment the line:-
this->setCentralWidget(label);
i mean i remove label as being the central widget, the program runs as expected.. Why?
And also, I am not clear about the concept of CentralWidget. Pls guide.
JimDaniel is right in his last edit. Take a look at the source code of setCentralWidget():
void QMainWindow::setCentralWidget(QWidget *widget)
{
Q_D(QMainWindow);
if (d->layout->centralWidget() && d->layout->centralWidget() != widget) {
d->layout->centralWidget()->hide();
d->layout->centralWidget()->deleteLater();
}
d->layout->setCentralWidget(widget);
}
Do you see that if your MainWindow already had centralWidget() Qt schedules this object for deletion by deleteLater()?
And centralWidget() is the root widget for all layouts and other widgets in QMainWindow. Not the widget which is centered on window. So each QMainWindow produced by master in Qt Creator already has this root widget. (Take a look at your ui_mainwindow.h as JimDaniel proposed and you will see).
And you schedule this root widget for deletion in your window constructor! Nonsense! =)
I think for you it's a good idea to start new year by reading some book on Qt. =)
Happy New Year!
Are you sure it's not label->hide() that's crashing the app? Perhaps Qt doesn't like you hiding the central widget. I use Qt but I don't mess with QMainWindow that often.
EDIT: I compiled your code. I can help you a bit. Not sure what the ultimate reason is as I don't use the form generator, but you probably shouldn't be resetting the central widget to your label, as it's also set by the designer, if you open the ui_mainwindow.h file and look in setupGui() you can see that it has a widget called centralWidget that's already set. Since you have used the designer for your GUI, I would use it all the way and put the label widget in there as well. That will likely fix your problems. Maybe someone else can be of more help...
I'm not sure I understood your problem, neither what the guys above said (which I guess are valid information) and it seems to be an old topic.
However, I think I had a problem that looks like this and solved it, so I want to contribute my solution in case it helps anyone.
I was trying to "reset" central widget using QLabels. I had three different ones, switch from first to second, then to third and failed to switch back to the first one.
This is my solution that worked:
Header file
QLabel *imageLabel;
Constructor
imageLabel = new QLabel("<img src='/folder/etc.jpg' />");
this->setCentralWidget(imageLabel);
Reset
imageLabel = NULL;
imageLabel = new QLabel("<img src='/folder/etc.jpg' />");
this->setCentralWidget(imageLabel);
Hope that helps
Aris