How do I draw the close, minimize, and maximize buttons in Qt? - c++

I created a this->setWindowFlags(Qt::FramelessWindowHint); and so there is no title bar. Therefore, I am implementing my own. I wanted to know, however, before I continue whether there is a standard way to add the close, minimize, and maximize buttons in a native-os looking way (i.e. on windows it should look like the windows close buttons and the same for osx and linux).

QStyle take a lot of standard icons base on OS style. You can get this icon from current OS style and then draw it by your self.
This is a simple implementation for reference.
class TitleBar : public QWidget
{
Q_OBJECT
public:
explicit TitleBar(QWidget *parent = 0)
:QWidget(parent)
{
QStyle *style = qApp->style();
QIcon closeIcon = style->standardIcon(QStyle::SP_TitleBarCloseButton);
QIcon maxIcon = style->standardIcon(QStyle::SP_TitleBarMaxButton);
QIcon minIcon = style->standardIcon(QStyle::SP_TitleBarMinButton);
QPushButton *min = new QPushButton(this);
QPushButton *max = new QPushButton(this);
QPushButton *close = new QPushButton(this);
min->setIcon(minIcon);
max->setIcon(maxIcon);
close->setIcon(closeIcon);
QHBoxLayout *layout = new QHBoxLayout(this);
layout->setSpacing(0);
layout->addWidget(min);
layout->addWidget(max);
layout->addWidget(close);
setLayout(layout);
}
};

Related

How to reduce distance between widgets and window size with Qt?

What I currently have:
What I want:
For those unable to view the images; the widgets are spread out by some sort of margin between them. I would like to keep them as close as possible. How can I squeeze the widgets closer together?
I have already tried:
setFixedSize(sizeHint()); and setSizeConstraint(QLayout::SetFixedSize); on the main window, layouts, and widget object. Nothing seems to work.
As an extra, I would also appreciate this:
(having the label get even closer to the lineEdit)
I am using Windows and Qt 5.11.1, 64-bits.
The window constructor code:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
widget = new QWidget();
label = new QLabel(tr("Enter your name:"));
nameLine = new QLineEdit;
nameLine->setMinimumWidth(250);
label->setBuddy(nameLine);
okButton = new QPushButton (tr("Ok"));
clearButton = new QPushButton (tr("Clear"));
connect(okButton, SIGNAL(clicked()), this, SLOT(message()));
connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
QGridLayout *grid = new QGridLayout;
grid->addWidget(label,0,0);
grid->addWidget(nameLine,1,0);
grid->addWidget(okButton,0,1);
grid->addWidget(clearButton,1,1);
widget->setLayout(grid);
setWindowTitle(tr("Leo v0.0"));
setCentralWidget(widget);
}
A possible solution is to establish a QVBoxLayout with addStretch():
QVBoxLayout *vlay = new QVBoxLayout;
QGridLayout *grid = new QGridLayout;
grid->addWidget(label, 0, 0);
grid->addWidget(nameLine, 1, 0);
grid->addWidget(okButton, 0, 1);
grid->addWidget(clearButton, 1, 1);
vlay->addLayout(grid);
vlay->addStretch();
widget->setLayout(vlay);
setCentralWidget(widget);

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);

How to resize an expandable dialog?

I am trying to create an expandable Qt dialog application. The main layout is a QVBoxLayout. The top part has two views and a QPushButtonbutton. Clicking button will unfold the bottom widget which is initially hidden. In the bottom widget, there is another push button, which could fold (hide) the bottom widget. When the bottom widget fold/unfold, I expect the size of the dialog size to change as well.
But for some reason, the dialog size only increases when the bottom widget is unfolded. And never shrink back to (200, 100). Is there anything I missed?
Environment: Qt Creator 3.6.1; Based on Qt5.6.0 (MSVC2013 32bit); build on Mar 14 2016; revision d502727b2c
The code I am using :
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
QTreeView *tree = new QTreeView;
QTableView *table = new QTableView;
QPushButton *button_show = new QPushButton;
button_show->setText(tr("Show hidden panel"));
QHBoxLayout *layout_top = new QHBoxLayout;
layout_top->addWidget(tree);
layout_top->addWidget(table);
layout_top->addWidget(button_show);
QHBoxLayout *layout_bottom = new QHBoxLayout;
QTextEdit *editor = new QTextEdit;
QPushButton *button_hide = new QPushButton;
button_hide->setText(tr("Hide the bottom panel"));
g_pEditor = editor;
layout_bottom->addWidget(editor);
layout_bottom->addWidget(button_hide);
QWidget *panel = new QWidget;
panel->setLayout(layout_bottom);
QVBoxLayout *layout_main = new QVBoxLayout;
layout_main->addLayout(layout_top);
layout_main->addWidget(panel);
setLayout(layout_main);
panel->hide();
connect(button_show, &QPushButton::clicked
, panel
, [=]()
{
panel->setVisible(true);
button_show->setEnabled(false);
resize(200, 200);// not really working, the dialog size is able to increase without calling resize()
});
connect(button_hide, &QPushButton::clicked, panel, [=]()
{
panel->hide();
button_show->setEnabled(true);
resize(200,100);// does not shrink the dialog size*
});
resize(200,100);
}
Thanks for your help :)
Your should try setFixedSize(w, h) instead. This sets both, the minimum and the maximum size to (w, h). "This will override the default size constraints set by QLayout."

Qt C++ Display new window centered on old window

I have QWidget with button. When button is pressed, show new smaller window (Qwidget too). I want then new window is centered horizontal and veritcal on main window. Code which display new window is:
QWidget *wdg = new QWidget;
QPushButton *closeBtn = new QPushButton("Close");
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(closeBtn);
wdg->setLayout(layout);
wdg->show();
wdg->resize(400,200);
Use the move slot. For example:
QPoint centerPoint = oldWidget->geometry()->center();
newWidget->adjustSize();
newWidget->move(centerPoint.x() - newWidget->width()/2, centerPoint.y() - newWidget->height()/2);
You may consider using frameGeometry() instead of geometry().
http://qt-project.org/doc/qt-5/application-windows.html#window-geometry
Hope that helps.

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)));
}
};