Creating tabs in Qt using QTabWidget - c++

Here they tell us how to create tabs:
Create a QTabWidget.
Create a QWidget for each of the pages in the
tab dialog, but do not specify parent widgets for them.
Insert child
widgets into the page widget, using layouts to position them as
normal.
Call addTab() or insertTab() to put the page widgets into the
tab widget, giving each tab a suitable label with an optional
keyboard shortcut.
So, I created a tab widget:
class mainWindow : public QDialog
{
Q_OBJECT
QWidget* m_mainWindow;
QTabWidget* tab;
...
Then I have a Widget Class that defines a "page":
class tradeView : public QWidget
{
Q_OBJECT
QWidget* tradeWidget;
...
THis is how the c'tor of the widget (that is supposed to go into the tab as a page) looks like:
tradeView::tradeView()
{
tradeWidget = new QWidget;
tradeWidget->setWindowTitle("Trade View");
tradeWidget->setGeometry(150,18,1800,800);
m_pTableWidget = new QTableWidget(this);
m_pTableWidget->setRowCount(100);
m_pTableWidget->setColumnCount(6);
m_TableHeader<<"Client Id"<<"Symbol"<<"Quantity"<<"Strategy Id"<<"Expiry" << "Side";
m_pTableWidget->setHorizontalHeaderLabels(m_TableHeader);
m_pTableWidget->verticalHeader()->setVisible(false);
m_pTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_pTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
m_pTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
m_pTableWidget->setShowGrid(false);
m_pTableWidget->setStyleSheet("QTableView {selection-background-color: red;}");
m_pTableWidget->setGeometry(QApplication::desktop()->screenGeometry());
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(m_pTableWidget);
tradeWidget->setLayout(layout);
}
Then I did the following inside my main dialog c'tor:
mainWindow::mainWindow(QWidget* parent):QDialog(parent)
{
m_mainWindow = new QWidget;
m_mainWindow->setWindowTitle("Main Window");
QVBoxLayout *layout = new QVBoxLayout;
tradeView* tradeViewWindow = new tradeView();
orderView* orderViewWindow = new orderView();
tab = new QTabWidget(this);
tab->addTab(tradeViewWindow, "Trade");
tab->addTab(orderViewWindow, "Order");
layout->addWidget(tab);
m_mainWindow->setLayout(layout);
m_mainWindow->setGeometry(150,18,1850,900);
m_mainWindow->show();
}
I was expecting the widget to show up in the tab.
But when I run the code, the tab is created, but is completely empty.
What am I missing here ?

Your widget construction is strange. The rough object ownership of your widgets is like the following:
MainWindow (top-level QDialog)
m_mainWindow (top-level QWidget)
tab (QTabWidget)
tradeViewWindow (QWidget)
orderViewWindow (QWidget)
tradeView->tradeWidget (hidden top-level QWidget)
QTableWidget
orderView->orderWidget (hidden top-level QWidget)
QTableWidget
Do you see the problem now? You actually have 4 top-level QWidgets and two of them are hidden. You are seeing empty tabs since you create QTableWidget in another QWidget which is hidden. In other words, QTableWidget's parent is not the tab, its parent is a hidden top-evel QWidget.
The solution: tradeView is already a QWidget itself, there is no need to create another tradeWidget inside it again. You should set the layout's parent to tradeView itself:
tradeView::tradeView()
{
//tradeWidget = new QWidget; // this is a hidden top-level QWidget
//tradeWidget->setWindowTitle("Trade View");
//tradeWidget->setGeometry(150,18,1800,800);
m_pTableWidget = new QTableWidget(this);
m_pTableWidget->setRowCount(100);
m_pTableWidget->setColumnCount(6);
m_TableHeader<<"Client Id"<<"Symbol"<<"Quantity"<<"Strategy Id"<<"Expiry" << "Side";
m_pTableWidget->setHorizontalHeaderLabels(m_TableHeader);
m_pTableWidget->verticalHeader()->setVisible(false);
m_pTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_pTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
m_pTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
m_pTableWidget->setShowGrid(false);
m_pTableWidget->setStyleSheet("QTableView {selection-background-color: red;}");
m_pTableWidget->setGeometry(QApplication::desktop()->screenGeometry());
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(m_pTableWidget);
//tradeWidget->setLayout(layout);
this->setLayout(layout);
}
As a sidenote, your MainWindow which is a QDialog creates another m_mainWindow as well, are you sure this is your intention?

Related

Why is the QScrollArea restricted in size?

To my custom widget, inherited from QWidget, I have added a QScrollArea like this:
MainWindow::MainWindow(QWidget *parent) :
QWidget(parent)//MainWindow is a QWidget
{
auto *scrollArea = new QScrollArea(this);
auto *widget = new QWidget(this);
widget->setStyleSheet("background-color:green");
scrollArea->setWidget(widget);
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
QVBoxLayout *parentLayout = new QVBoxLayout(widget);
this->setStyleSheet("background-color:blue");
for(int i=0;i<12;i++){
QHBoxLayout* labelLineEdit = f1();
parentLayout->addStretch(1);
parentLayout->addLayout(labelLineEdit);
}
parentLayout->setContentsMargins(0,0,40,0);
}
QHBoxLayout* MainWindow::f1()
{
QHBoxLayout *layout = new QHBoxLayout;
QLabel *label = new QLabel("Movie");
label->setStyleSheet("background-color:blue;color:white");
label->setMinimumWidth(300);
label->setMaximumWidth(300);
layout->addWidget(label);
QLineEdit *echoLineEdit = new QLineEdit;
echoLineEdit->setMaximumWidth(120);
echoLineEdit->setMaximumHeight(50);
echoLineEdit->setMinimumHeight(50);
echoLineEdit->setStyleSheet("background-color:white");
layout->addWidget(echoLineEdit);
layout->setSpacing(0);
return layout;
}
This produces a window which looks like this:
The problem is, that I want the scrollArea to occupy the entire window, but it does not. It also doesn't get resized when I resize the window.
How could I fix this?
The problem is, that I want the scrollArea to occupy the entire
window, but it does not. It also doesn't get resized when I resize the window.
The reason is that you have not set any kind of layout to manage the positioning of your QScrollArea widget itself, so it is just being left to its own devices (and therefore it just chooses a default size-and-location for itself and stays at that size-and-location).
A simple fix would be to add these lines to the bottom of your MainWindow constructor:
QBoxLayout * mainLayout = new QVBoxLayout(this);
mainLayout->setMargin(0);
mainLayout->addWidget(scrollArea);

Center children widget in parent widget(parent widget was added in layout)

I created a layout contain a parent widget. In that parent widget i created another widget.
My code is similarly to this:
QGridLayout *layout = new QGridLayout();
QWidget *parentWidget = new QWidget();
layout->addWidget(parentWidget );
QWidget *childWidget = new QWidget(parentWidget);
How can i center the child widget in parent widget ?
The problem is we cannot get the true size of parent widget because it's in a layout.
Move the child inside the parent's showeEvent. You can use a bool flag to do it only when the parent is shown for the first time.
void Parent::showEvent(QShowEvent *)
{
if(_first_show)
{
_first_show = false;
_child->move(this->rect().center() - _child->rect().center());
}
}
Proof that it works (red is the parent, and blue is the child):
You can do this by setting fixed size of child widget and placing it inside grid layout of parent widget.
QGridLayout *layout = new QGridLayout();
QWidget *parentWidget = new QWidget();
layout->addWidget(parentWidget );
QWidget *childWidget = new QWidget(parentWidget);
QGridLayout *parentLayout = new QGridLayout();
parentWidget->setLayout(parentLayout);
parentLayout->addWidget(childWidget);
childWidget->setFixedSize(/*some fixed size for child widget*/);

How to access widgets in different tabs of QTabWidget?

I know how to create a new tab and add new widgets to a new tab of QTabWidget.
My Code:
QPlainTextEdit *plainTextEdit = new QPlainTextEdit;
ui->tabWidget->addTab(plainTextEdit , "New");
When I clicked the button, new tab and its own QPlainTextEdit widget will be created.
But I don't know how to set property to different QPlainTextEdit or save their contents.
For example, I want set font size of QPlainTextEdit in tab4 and save contents of QPlainTextEdit in tab5.
How to achieve these functions?
To get the widget at a tab index you can use the widget function of QTabWidget .
In your case in which QPlainTextEdit is the only widget of every tab page :
QPlainTextEdit* plainTextEdit = (QPlainTextEdit*) ui->tabWidget->widget(0); // for the first tab
plainTextEdit->setPlainText("Hello!");
If the QPlainTextEdit is not the only widget, you need to get the children of the widget and find the QPlainTextEdit in them :
QList<QPlainTextEdit *> allTextEdits = ui->tabWidget->widget(0)->findChildren<QPlainTextEdit *>();
if (allTextEdits.count() >0)
allTextEdits[0]->setPlainText("Hello!");;
You should have pointers to your QPlainTextEdits as members of the main widget class:
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
void someFunction();
private:
QPlainTextEdit *plainTextEdit;
}
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
...
plainTextEdit = new QPlainTextEdit;
ui->tabWidget->addTab(plainTextEdit , "New");
}
void Widget::someFunction()
{
plainTextEdit->setPlainText("Hello!");
}

Replace page of a QTabWidget with a new widget

Basically I have a QTabWidget. At first it has a form widget, widget1. After that form is done being interacted with, the new widget2 form should take over that same tab.
I thought tabWidget->setCurrentWidget(new widget2()); would work, but it's basically an overload for setCurrentIndex(int).
Does anyone know of a way to do this?
You can use a QStackedWidget for this type of thing, in a tab or elsewhere.
Put all the widgets you'll want to display in that tab inside a single QStackedWidget, and place that stacked widget in a tab.
Here's a quick'n'dirty demo:
#include <QtGui>
class W: public QWidget
{
Q_OBJECT
public:
W(QWidget *parent=0): QWidget(parent)
{
// stacked widget displays one of its "children" at a time
QStackedWidget *sw = new QStackedWidget;
QPushButton *b1 = new QPushButton("hello");
sw->addWidget(b1);
QPushButton *b2 = new QPushButton("world");
sw->addWidget(b2);
// tab widget and simplistic layout
QTabWidget *tw = new QTabWidget(this);
tw->addTab(sw, "tab");
QHBoxLayout *l = new QHBoxLayout;
l->addWidget(tw);
setLayout(l);
// signal mapper to demo the widget switching
QSignalMapper *m = new QSignalMapper(this);
connect(b1, SIGNAL(clicked()), m, SLOT(map()));
m->setMapping(b1, 1);
connect(b2, SIGNAL(clicked()), m, SLOT(map()));
m->setMapping(b2, 0);
connect(m, SIGNAL(mapped(int)), sw, SLOT(setCurrentIndex(int)));
}
};

Is there a way to add a QWidget to a QMenu in QtCreator

I'm creating a text editor and I'd like to put the QComboBox in the QMenu. I didn't find any method inside the QMenu that handled such a thing. The closest is QMenu::addAction(). I was wondering of getting around this hurdle.
Thanks!
You have to subclass QWidgetAction and then simply call the addAction to your menu.
Example code for Spin Box Action with a label
class SpinBoxAction : public QWidgetAction {
public:
SpinBoxAction (const QString& title) :
QWidgetAction (NULL) {
QWidget* pWidget = new QWidget (NULL);
QHBoxLayout* pLayout = new QHBoxLayout();
QLabel* pLabel = new QLabel (title); //bug fixed here, pointer was missing
pLayout->addWidget (pLabel);
pSpinBox = new QSpinBox(NULL);
pLayout->addWidget (pSpinBox);
pWidget->setLayout (pLayout);
setDefaultWidget(pWidget);
}
QSpinBox * spinBox () {
return pSpinBox;
}
private:
QSpinBox * pSpinBox;
};
Now simply create it and add it to your menu
SpinBoxAction * spinBoxAction = new SpinBoxAction(tr("Action Title"));
// make a connection
connect(spinBoxAction ->spinBox(), SIGNAL(valueChanged(int)),
this, SLOT(spinboxValueChanged(int)));
// add it to your menu
menu->addAction(spinBoxAction);
QWidgetAction is a QAction that contains a QWidget. You can use this to encapsulate your QComboBox and add it to your menu via QMenu::addAction.
You can always use a QWidget or QFrame as the Menu Widget, then put a QHBoxLayout on it, and insert your QWidgets inside.