Issue with QLayout with QStackedWidget - c++

I am implementing a tab style UI. where tabs are shown by QListWidget and contents are shown by QStackedWidget. on every page of QStackWidget there is layout which allow to insert panel(widget) in QHBoxlayout. at every panel, there are couple of icons which are again in QHBoxLayout. Below is ideal case which I wanted to implement.
But on other page of QStackWidget this is not the case (with less icons) as below
I want to remove extra space ( or align icon to left to eliminate extra space among icons on panels)
I tried spacer, then this happened :(
please help me to correct this thing. My spacer code is as
inline QSpacerItem * buildSpacer(Qt::Orientation orientation)
{
QSpacerItem * pSpacer = nullptr;
if (orientation == Qt::Horizontal)
{
pSpacer = new QSpacerItem(1000, UNIT_VALUE, QSizePolicy::Expanding, QSizePolicy::Minimum);
}
else
{
pSpacer = new QSpacerItem(UNIT_VALUE, 1000, QSizePolicy::Minimum, QSizePolicy::Expanding);
}
return pSpacer;
}
Note
I donot want to use QTabWidget. By the way this issue is also with QTabWidget

Why not using QTabWidget in the first place?
Anyway, instead of creating the QSpacerItem by yourself, you should use addStretch():
my_layout->addWidget(new Widget("widget1"));
my_layout->addWidget(new Widget("widget2"));
my_layout->addStretch(1); // will "eat" extra space

Related

QAbstractItemView Tab Focus While Editing Item

I have a QTreeView populated with items from a model. When a call to edit() is made on an index, a custom editor displays. The editor consists of two QLineEdit widgets.
I want the focus to switch between the two QLineEdit widgets when Tab is pressed. However, pressing Tab cycles through everything else on my program. All my QPushButton and QTabWidget objects are included in the Tab order even though they are completely different widgets than my editor.
I've tried setting the tab order using setTabOrder() to loop it between the two QLineEdit widgets, however this still doesn't isolate the editor widget from the surrounding widgets. Why is this happening?
NOTE: I'm not trying to disable tab ordering anywhere else, just isolate it to my editor for the time being.
Thanks for your time!
This can be easily implemented using QWidget::focusNextPrevChild as follows:
class EditWidget : public QWidget
{
public:
EditWidget(QWidget *pParent) : QWidget(pParent)
{
QHBoxLayout *pLayout = new QHBoxLayout(this);
setLayout(pLayout);
pLayout->addWidget(m_pEdit1 = new QLineEdit ());
pLayout->addWidget(m_pEdit2 = new QLineEdit ());
}
bool focusNextPrevChild(bool next)
{
if (m_pEdit2->hasFocus())
m_pEdit1->setFocus();
else
m_pEdit2->setFocus();
return true; // prevent further actions (i.e. consume the (tab) event)
}
protected:
QLineEdit *m_pEdit1;
QLineEdit *m_pEdit2;
};

QTabWidget tab displays nothing in one of the tabs

I am trying to create a gui that has a QTabWidget with multiple tabs. As a preliminary test I have created one that has two tabs using the same layouts. The first tab (Page 1) is blank but then the second one shows the QTableView I created. Both tabs were created the exact same way, yet they perform differently. Anyone know why the first one is blank...?
I noticed that if I comment out the line int8Window->setLayout(_layout);. Page 1 shows up with the proper layout and the second tab is blank this time...
Here is the code for the gui:
// Main window and layout
QWidget* mainWindow = new QWidget;
QVBoxLayout *mainLayout = new QVBoxLayout;
// Tab widget
QTabWidget* tabWidget = new QTabWidget;
// The pages in the tab widget
QWidget* uInt8Window = new QWidget;
uInt8Window->setWindowTitle(QString("Page 1"));
QWidget* int8Window = new QWidget;
int8Window->setWindowTitle(QString("Page 2"));
QTableView* tableView = new QTableView;
QStandardItemModel* model = new QStandardItemModel(5, 5);
for (int row = 0; row < 5; ++row) {
model->setItem(row, 0, new QStandardItem("3"));
model->setItem(row, 1, new QStandardItem(5));
model->setItem(row, 2, new QStandardItem(2));
model->setItem(row, 3, new QStandardItem(1));
model->setItem(row, 4, new QStandardItem(5));
}
tableView->setModel(model);
// Setting the tab page layouts
_layout = new QVBoxLayout;
_layout->addWidget(tableView);
uInt8Window->setLayout(_layout);
int8Window->setLayout(_layout);
// Add the pages to the tab widget
tabWidget->addTab(uInt8Window, "Page 1");
tabWidget->addTab(int8Window, "Page 2");
// Add the tab widget to the main layout and show
mainLayout->addWidget(tabWidget);
mainWindow->setLayout(mainLayout);
mainWindow->show();
Read logs! I'm sure you have a respective warning.
You are assigning same layout to two different widgets. Once layout is assigned to a widget, it is owned by this widget forever.
You need create separate layout for each widget.
I recommend to split this onto couple methods. One is creating a widget for a page (you can use this couple times). Other creating a data model, and other composing tab widget.
Please remember also about memory management! Best approach is to set parent during construction (as parameter of constructor). You have a leak in data model.

Qt: How to add two widgets (say QPushButton) to the status bar, one to the left and other to the right side?

I would like to add two widgets (say QPushButton) to the status bar, one to the left and other to the right side.
I am thinking of adding horizontal spacer in between the two widgets, but don't know how to add.
PS: I tried using addWidget() to add to the left and addPermanentWidget() to add to the right but it doesn't look neat and also it doesn't feel right.
You can add two buttons to a layout in a widget and add the widget to the status bar using QStatusBar::addWidget :
QWidget * widget = new QWidget();
QPushButton * leftBut = new QPushButton("Left");
QPushButton * rightBut = new QPushButton("Right");
QGridLayout * layout = new QGridLayout(widget);
layout->addWidget(leftBut,0,0,1,1,Qt::AlignVCenter | Qt::AlignLeft);
layout->addWidget(rightBut,0,1,1,1,Qt::AlignVCenter | Qt::AlignRight);
ui->statusBar->addWidget(widget,1);
I am thinking of adding horizontal spacer in between the two widgets, but don't know how to add.
Here is a way to use a "fake" spacer.
QPushButton *leftButton = new QPushButton("Left");
QPushButton *rightButton = new QPushButton("Right");
QLabel *spacer = new QLabel(); // fake spacer
ui->statusBar->addPermanentWidget(leftButton);
ui->statusBar->addPermanentWidget(spacer, 1);
ui->statusBar->addPermanentWidget(rightButton);
The second parameter in addPermanentWidget is "used to compute a suitable size for the given widget as the status bar grows and shrinks".
Demo:
I think the simplest way is using a QGridLayout (honestly I never tried to modify a status bar anyway) supposing that the status bar is or descends from widget you can do this:
QGridLayout *myGridLayout = new QGridLayout();
statusbar->setLayout(myGridLayout)
QPushButton *button1 = new QPushButton(this);
myGridLayout->addWidget(button1,0,0,1,1);
QPushButton *button2 = new QPushButton(this);
myGridLayout->addWidget(button2,X,0,1,1);
The biggest is X the more space you want to leave in between, I would suggest to start with 3 and then make few tests to see how it looks.

Setting the form lines like iTunes info dialog on Mac with Qt

I'm just a beginner and I wonder if it would be possible to create a form widget on Mac like the info dialog in iTunes.
I tried using:
QGroupBox: I cannot find a way to get rid of the frames.
Creating my own widget: I cannot find a way to fix the spacing between the label and the QLineEdit widget using the QVBoxLayout (actually I'm not sure I understand well the differences between margin/spacing).
QFormLayout: I cannot find a way to reduce the size of the QLabel after using setrowWrapPolicy::WrapAllRows
Also I am not (yet) very comfortable with QtDesigner, so i'd like to avoir using it (for now)
Thanks in advance
Edit: Some precisions on the programs. I use QtCreator 2.6.1 with Qt 4.8.1 and 5.0 on Mac OS X Mountain Lion.
Edit 2: Here is the code.
Subclass of QWidget:
MCLineEdit::MCLineEdit(const QString &header)
{
m_lineEdit = new QLineEdit;
m_lineTitle = new QLabel(header);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(m_lineTitle);
layout->addWidget(m_lineEdit);
layout->setSpacing(0);
setLayout(layout);
}
To display the widget
myView::myView(QWidget *parent) :
QWidget(parent)
{
setFixedSize(600, 500);
MCLineEdit *lineEdit1 = new MCLineEdit("Test 1");
MCLineEdit *lineEdit2 = new MCLineEdit("Test 2");
MCLineEdit *lineEdit3 = new MCLineEdit("Test 3");
MCLineEdit *lineEdit4 = new MCLineEdit("Test 4");
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(lineEdit1);
mainLayout->addWidget(lineEdit2);
mainLayout->addWidget(lineEdit3);
mainLayout->addWidget(lineEdit4);
mainLayout->setSpacing(0);
setLayout(mainLayout);
}
This can be accomplished a ton of ways I am sure. Qt gives you all the possible layouts you could need to achieve this. You could do it with a QGridLayout, and add widgets with different amounts of "cell" spanning, and control the row and column sizes to suit. Or you can just do it with a bunch of nested vertical/horizontal layouts.
For example, you can group a label and a field together in a QVBoxLayout, by adding the widgets with a left alignment, and then setting the spacing to 0 between the items:
layout->setSpacing(0);
layout->addWidget(aLabel, Qt::AlignLeft);
layout->addWidget(aLineEdit, Qt::AlignLeft);
mainVerticalLayout->addLayout(layout);
For something like the track numbers, it is just more nested layouts:
vLayout->addWidget(aLabel);
hLayout->addWidget(aCheckbox);
hLayout->addWidget(aLabel);
hLayout->addWidget(aCheckbox);
vLayout.addLayout(hLayout);
And regarding your bullet points:
QGroupBox lets you remove the frame with setFlat(bool)
With layouts, the margin is the padding around the outside of the contained widgets. What you want is setSpacing(int) to control the amount of space between the items in the layout.
QFormLayout is probably not your best choice here. That is usually for having labels on one side and widgets on the other. Basically it is a 2 column layout. A QGridLayout would be more appropriate. And to reduce the size of the QLabel, you can give it a max or a fix size. Such as using setFixedWidth() or setMaximumWidth() on the label.
So I finally managed to get the expected result after playing a bit with QtCreator.
Here is the code for who might be interested:
myLineEdit:myLineEdit(const QString &header)
{
m_lineEdit = new QLineEdit;
m_groupBox = new QGroupBox;
QFont groupFont;
groupFont.setPixelSize(10);
groupFont.setBold(true);
m_groupBox->setTitle(header);
m_groupBox->setFlat(true);
m_groupBox->setFont(groupFont);
m_groupBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
QFont lineFont;
lineFont.setPixelSize(13);
lineFont.setBold(false);
m_lineEdit->setFont(lineFont);
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(m_lineEdit);
layout->setContentsMargins(0, 10, 0, 0);
layout->setSpacing(10);
layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
m_groupBox->setLayout(layout);
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(m_groupBox);
setLayout(mainLayout);
}
One comment though: will only work on Qt 5 since on 4.8 the setFlat() method will display a separating line between the header and the QLineEdit.
Thanks to jdi for his help!

How do I add a QTCreator-like left bar to my program?

I'm designing the GUI for a project, and I want a left bar like this ones
(source: patatux.net)
(source: tuxradar.com)
How do I put them in my .ui file?
You can try to use QToolBar with vertical orientation.
To emulate tabs behavior you should put actions to QActionGroup and make them checkable.
For example to create left panel Qt creator like:
welcomeAct = new QAction(...)
toolbar->addAction(welcomeAct)
editAct = new QAction(...)
toolbar->addAction(editAct)
designAct = new QAction(...)
toolbar->addAction(designAct)
...
//add spacing
QLabel *spacing = new QLabel;
spacing->setSizePolicy(Qt::Expanding, Qt::Expanding);
toolbar->addWidget(spacing);
//adding aditional actions
runAct = new QAction(...)
toolbar->addAction(runAct)
runDebugAct = new QAction(...)
toolbar->addAction(runDebugAct)
buildAct = new QAction(...)
toolbar->addAction(buildAct)
// put "tabs" action in QActionGroup
group = new QActionGroup(this);
group->addAction(welcomeAct)
group->addAction(editAct)
group->addAction(designAct)
...
Simplest way - is to use QtCreator's library libCorePlugin.so and corresponding includes (FancyTabBar.h) from QtCreator's srcs
You can most likely do it by putting everything into a QHBoxLayout, where the left hand side is a QVBoxLayout column of QPushButton's with icons matching what you want. Have the buttons trigger what the right hand pane looks like.
There is also the QTabBar which does most of this work for you. You just need to tell it to put the tabs on the left hand side.