I have a class controlPanel : public wxPanel.
Creating a dialog I just put a list of panels in a wxBoxSizer in constructor.
controlPanel *cp[20];
for(int i=0; i<20; i++)
{
cp[i]=new controlPanel(this,true,"asd",i,i+1);
bSizer5->Add(cp[i],0, wxALL|wxEXPAND, 0 );
}
But I can not scroll up and down to see all panels. What should I do?
Also bSizer5 covers all other widgets, so bSizer5 is in top of all.
Related
I'm learning wxWidgets and am trying to make minesweeper using wxButtons. I use the following code to create and position the buttons:
int length = 10;
wxGridSizer *grid = new wxGridSizer(length, length, 0, 0);
wxButton *buttons[length*length];
for (int i=0; i<length*length; i++){
buttons[i] = new wxButton(this, wxID_ANY);
grid->Add(buttons[i], 1, wxEXPAND | wxALL);
if (mineField[i]){
Bind(wxEVT_BUTTON, &MainWindow::isMine, this);
} else {
Bind(wxEVT_BUTTON, &MainWindow::notMine, this);
}
}
I expect this to generate a 10x10 grid of buttons, but instead it positions all of the buttons at (0,0). I have been Googling the problem for a while now but I can't find the issue. How do I position the buttons in a 10x10 grid? Thanks.
To make the grid sizer layout the buttons, you need to either
set it to be the sizer for a window or
add it to another sizer.
Assuming the code above is from the constructor of your main frame window, you would set grid to be the sizer for the frame like this
SetSizer(grid);
On the other hand, if you have other controls in the frame and need to add grid to another sizer, you could do that something like this:
otherSizer->Add(grid,wxSizerFlags(0));
Obviously, 'otherSizer' should be replaced with the name of the other sizer. There are many options that can be used with wxSizerFlags to get the exact layout you want.
In addition, as mentioned above, it's sometimes helpful to end all the code the creates and organizes the controls your using with a call to the Layout() method.
Another tactic you can use is to have a single panel be the only child of the frame and then set a sizer for the panel. This works because in wxWidgets whenever a top level window such as a frame has a single child, that child is automatically sized to fill all of the available area.
Using this technique, a layout with a text control along the top and the grid underneath it could be created like this:
// Create the controls
wxPanel* bgPanel = new wxPanel(this, wxID_ANY);
wxTextCtrl* text = new wxTextCtrl(bgPanel, wxID_ANY);
wxGridSizer *grid = new wxGridSizer(length, length, 0, 0);
wxButton *buttons[length*length];
for (int i=0; i<length*length; i++){
buttons[i] = new wxButton(bgPanel, wxID_ANY);
grid->Add(buttons[i], 1, wxEXPAND | wxALL);
if (mineField[i]){
Bind(wxEVT_BUTTON, &MainWindow::isMine, this);
} else {
Bind(wxEVT_BUTTON, &MainWindow::notMine, this);
}
}
// Create a sizer for the panel and add the text control and grid to it.
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
mainSizer->Add(text, wxSizerFlags(0).Expand().Border(wxALL));
mainSizer->Add(grid,wxSizerFlags(1).Expand().Border(wxLEFT|wxRIGHT|wxBOTTOM));
bgPanel->SetSizer(mainSizer);
I'm getting closer to getting a QScrollArea working, but it's still shrinking my custom widgets as they are added. Everything is resizing fluidly, and if the scroll area is too small, then the scroll bar appears, so it clearly has some idea of a minimum size.
At start, with two custom widgets in the scroll area, you can see some shrinking:
Here's the same window below the critical point. The text is now completely gone, but it won't shrink the QLineEdit, so it finally adds a scrollbar. (the scroll area has a blue background, the content widget is the purple)
I started in Design, but everything below the scroll area's widget is in code, as I was having trouble getting the vertical layout to work right using design.
Here's the starting point:
There's a page in a StackWidget that has two elements in a vertical layout. The scroll area has a QWidget. The constructor for MainWindow defines a vertical layout, assigning it to the member scrollWidgetLayout, and giving that layout to the scroll area's widget:
scrollWidgetLayout = new QVBoxLayout(ui->scrollAreaWidgetContents);
ui->scrollAreaWidgetContents->setLayout(scrollWidgetLayout);
The app starts on the first page of the stack widget, the user logs in, and the app runs off to fetch records from the server. Each record is turned into a widget:
RecordFolderWidget::RecordFolderWidget(Record *r, QWidget *parent) : QWidget(parent)
{
record = r;
//setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
QGridLayout *layout = new QGridLayout();
pathLineEdit = new QLineEdit();
finderButton = new QPushButton("...");
QLabel *nameLabel = new QLabel(record->name);
layout->setSpacing(5);
layout->setMargin(3);
layout->addWidget(nameLabel, 0, 0, 0, 1, Qt::AlignCenter);
layout->addWidget(pathLineEdit, 1, 0);
layout->addWidget(finderButton, 1, 1);
setLayout(layout);
//setMinimumHeight(sizeHint().height());
}
Note that there are some lines commented out, these are things I have been playing with to try to get it to work. The sizeHint, btw, appears to be correct, and does not change.
Once that Widget is created, it gets added to the scroll area's widget:
RecordFolderWidget *rf = new RecordFolderWidget(record);
rf->setParent(ui->scrollAreaWidgetContents);
scrollWidgetLayout->addWidget(rf);
I tried here to also resize the scroll areas contents, with no luck:
ui->scrollAreaWidgetContents->resize(rfSize.width(), rfSize.height() * records.count());
where rfSize was pulled from the custom widget's sizeHint after it was created, and this line was called once after the loop to create/add all of the widgets.
Other than the setMinimumHeight and resize above, I've tried changing the SizePolicy for the scrollAreaWidgetContents from preferred to expanding to minimumexpanding and did not see any difference. I'm sure I've missed something trivial, but just can't find it.
The problem that I see in your code is when adding the QLabel you are setting the rowSpan to 0, I have changed it and I can observe it correctly. In the next part I show my test code and the result:
QVBoxLayout *scrollWidgetLayout = new QVBoxLayout(ui->scrollAreaWidgetContents);
for(int i=0; i<10; i++){
QWidget *widget = new QWidget;
QGridLayout *layout = new QGridLayout(widget);
QLineEdit *pathLineEdit = new QLineEdit;
QPushButton *finderButton = new QPushButton("...");
QLabel *nameLabel = new QLabel(QString("name %1").arg(i));
layout->setSpacing(5);
layout->setMargin(3);
layout->addWidget(nameLabel, 0, 0, 1, 1, Qt::AlignCenter);
layout->addWidget(pathLineEdit, 1, 0);
layout->addWidget(finderButton, 1, 1);
scrollWidgetLayout->addWidget(widget);
}
Currently I have this code to add several QLineEdits to ui.widget but I also need a vertical scrollbar in case of too many elements -> limited space available:
QGridLayout *gridLayout = new QGridLayout(ui.widget);
int rowIndex = 0, colIndex = 0;
for(auto number : m_numbers)
{
QLineEdit *lineEdit = new QLineEdit();
gridLayout->addWidget(lineEdit, rowIndex, colIndex, Qt::AlignLeft);
if(colIndex == 7)
{
colIndex = 0;
++rowIndex;
}
else ++colIndex;
}
ui.widget->setLayout(gridLayout);
How can I make it scrollable?
Use QScrollBar : The QScrollBar widget provides a vertical or horizontal scroll bar.
define a fix size for your widget and if user create too much QLineEdit, add your customized QScrollBar to that widget.
QScrollBar * scroll = new QScrollBar(Qt::Vertical, ui->widget);
OR use QScrollArea like this image:
This is a sample project for your question on github download here.
I have read few pages about QScrollArea, and I couldn't solve my issue. I have the next code:
QDialog *window = new QDialog;
window->resize(300, 300);
for(int i = 0; i < 50; ++i)
{
QLabel *label = new QLabel(window);
label->move(10, i * 15);
label->setText("Text");
}
QScrollArea *area = new QScrollArea;
area->setWidget(window);
area->show();
It seems that the vertical scroll from QScrollArea doesn't appear. I can't use QVBoxLayout because on my QDialog I don't have only QLabels aligned vertically ( this is just a simplified version of my QDialog ).
The QScrollArea won't get scrollbars unless the QWidget inside grows. Just moving some QLabels out of bounds doesn't make the parent QWidget grow, especially without a QLayout.
But if you manually resize them so that the QWidget is bigger than the QScrollAreay, you'll get scroll bars as expected :
QDialog *window = new QDialog;
window->resize(300, 600); //< 600px high widget
for(int i = 0; i < 50; ++i)
{
QLabel *label = new QLabel(window);
label->move(10, i * 15);
label->setText("Text");
}
QScrollArea *area = new QScrollArea;
area->setWidget(window);
area->resize(300,300); //< Inside a 300px high scrollarea, expect scrollbars!
area->show();
Note that now you will have both scroll bars, because the vertical scroll bar means there isn't enough room for our 300px width anymore. You can forcefully hide the horizontal scroll bar with area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
You could also always force a vertical scroll bar to appear with area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);, but this by itself wouldn't solve your problem. You'd still have a 300px widget inside a 300px area, and the scrollbar wouldn't have any space to move.
Making sure the QWidget is big enough for everything it contains is what you'll want to do, the QScrollArea will adapt. Usually we use layouts for that, but you can make it work by hand as well.
I have created a QDialog of size 720x480. I added 100 QLabels on it, and after that I created a QScrollArea, which has as widget the QDialog:
QDialog *window = new QDialog;
window->setWindowTitle("My Dialog");
window->setFixedSize(720, 480);
for(int i = 0; i < 100; ++i)
{
QLabel *label = new QLabel(window);
label->setText(QString::number(i));
label->move(10, i * 100);
}
QScrollArea area;
area.setWidget(window);
window->exec();
But the result is not that expected (like the vertical scrollbar to appear and to work properly ).
Your window has fixed height (to 480) and you place labels far beyond this size (last one will be placed at position 10, 9900).
You need to change your window's size.