How does designer create a Line widget? - qt

In Qt Designer , you can drag a "Line" widget , which will create a line in your layout.
But I checked the document and headers , I didn't find the "Line" header / widget , what was it ?

In Qt 5.7 the code generated by Qt Designer for a Horizontal Line (which can be checked in the menu using "Form/View Code...") is:
QFrame *line;
line = new QFrame(Form);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
This will create the lines you see in Qt Designer.
The current answers do not seem to give working solutions, here is a comparison of all answers (this solution is the first line):
Full code:
#include <QtWidgets>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QWidget widget;
auto layout = new QVBoxLayout;
widget.setLayout(layout);
widget.resize(200, 200);
auto lineA = new QFrame;
lineA->setFrameShape(QFrame::HLine);
lineA->setFrameShadow(QFrame::Sunken);
layout->addWidget(lineA);
QWidget *lineB = new QWidget;
lineB->setFixedHeight(2);
lineB->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
lineB->setStyleSheet(QString("background-color: #c0c0c0;"));
layout->addWidget(lineB);
auto lineC = new QFrame;
lineC->setFixedHeight(3);
lineC->setFrameShadow(QFrame::Sunken);
lineC->setLineWidth(1);
layout->addWidget(lineC);
QFrame* lineD = new QFrame;
lineD->setFrameShape(QFrame::HLine);
layout->addWidget(lineD);
widget.show();
return app.exec();
}

I guess you mean a horizontal / vertical line widget: it's just a simple QWidget with a gray background color and the horizontal is a fix height (1-3 pixel) and expanding width widget, the vertical is a fix width expanding height widget.
Horizontal example code:
QWidget *horizontalLineWidget = new QWidget;
horizontalLineWidget->setFixedHeight(2);
horizontalLineWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
horizontalLineWidget->setStyleSheet(QString("background-color: #c0c0c0;"));

Check out QFrame::setFrameShape(). To get a line, use either QFrame::HLine or QFrame::VLine as the function's argument.
// Create a horizontal line by creating a frame and setting its shape to QFrame::HLine:
QFrame* hFrame = new QFrame;
hFrame->setFrameShape(QFrame::HLine);
// Create a vertical line by creating a frame and setting its shape to QFrame::VLine:
QFrame* vFrame = new QFrame;
vFrame->setFrameShape(QFrame::VLine);

It is a QFrame with height 3, sunken shadow and line width equal to 1.
You can see it if examine header generated by uic tool.

Related

QToolButton with text: Overwrite minimal height to minic regular button height

I am displaying QToolButtons with icon plus text (Qt::ToolButtonTextBesideIcon) outside of a tool bar. Each button has a QAction associated with it which determines the used icon and the displayed text. All those buttons are placed inside a QGridLayout. So far so good.
Unfortunately, it looks like that as soon as you add a QAction to a QToolButton, Qt automatically decides to shrink it down to the minimal size, which is not what I want given my QGridLayout. I used the following lines to correct that behavior in the horizontal dimension:
QToolButton* pButton = new QToolButton(0);
pButton->addDefaultAction(pAction);
pButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
pButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
However that still leaves my button with a smaller height than a regular (push) button. I already tried various other size policies without success.
How to best solve this issue? Is there a reliable way to determine the "normal" button height?
One idea I had was to create a regular dummy button, place it in the same layout and then read its size. This size could then be applied to my QToolButton and the dummy button would be destroyed again. Is there a more elegant / reliable way?
I do not understand what do you want to achieve.
Difference between QPushButton and QToolButton is that, QToolButton has implemented PopupMenu ( can be done easily for QPushButton also )
As I understand visual difference is only small arrow in lower right corner of QToolButton, when you use added QActions to QToolButton
This arrow is for me only difference between QToolButton and QPushButton. But maybe I am missing something.
From your examples ( QToolButton with icon + text: How to center both? )
it does not look like you want to use that popup feature. Thats why I do not understand, why to use QToolButton instead of QPushButtons.
In this example shows:
1) Same height of QToolButton and QPushButton
2) PopuMenu for QPushButton
As for me, I do not understand why to use QToolButton and try to make it look like QPushButton when it is simple to use QPushButton as QToolButton
#include <QtGui>
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Prepare layout
QMainWindow *window = new QMainWindow;
QWidget *centralWidget = new QWidget(window);
QGridLayout *grid = new QGridLayout(centralWidget);
QTextEdit *textEdit = new QTextEdit();
window->setCentralWidget(centralWidget);
QAction *toolAction = new QAction(window->style()->standardIcon(QStyle::SP_MediaPlay), "ToolButton", window);
QObject::connect(toolAction, &QAction::triggered, [=]() {
qDebug() << "action";
});
QPushButton *pushButton = new QPushButton(toolAction->icon(), "PushButton1", window);
pushButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
QPushButton *pushButton2 = new QPushButton(toolAction->icon(), "PushButton2", window);
pushButton2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
QPushButton *pushButton3 = new QPushButton(toolAction->icon(), "PushButton2", window);
pushButton3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
QObject::connect(pushButton3, &QPushButton::released, [window, pushButton3, toolAction](){
QMenu menu;
menu.addAction(toolAction);
QPoint pos = window->mapToGlobal(pushButton3->pos());
pos += QPoint(0, pushButton3->height());
menu.exec(pos);
});
QObject::connect(pushButton, SIGNAL(pressed()), toolAction, SLOT(trigger()));
QObject::connect(pushButton2, SIGNAL(pressed()), toolAction, SLOT(trigger()));
QToolButton *toolButton = new QToolButton(window);
toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toolButton->setText("Popup action");
toolButton->addAction(toolAction);
toolButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QToolButton *toolButton2 = new QToolButton(window);
toolButton2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toolButton2->setDefaultAction(toolAction);
toolButton2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
toolButton->setMaximumHeight(pushButton->sizeHint().height());
toolButton->setMinimumHeight(pushButton->sizeHint().height());
toolButton2->setMaximumHeight(pushButton->sizeHint().height());
toolButton2->setMinimumHeight(pushButton->sizeHint().height());
grid->addWidget(textEdit ,0,0,1,2);
grid->addWidget(toolButton ,1,0,1,1);
grid->addWidget(pushButton ,1,1,1,1);
grid->addWidget(toolButton2 ,2,0,1,1);
grid->addWidget(pushButton2 ,2,1,1,1);
grid->addWidget(pushButton3 ,3,0,1,2);
window->show();
return a.exec();
}

Different alignment of widgets in QGridLayout

The following code (Qt 5, same behaviour with Qt 4.8) uses a QGridLayout to add widgets above and to the left of a QScrollArea (to serve as a kind of header later):
#include <QApplication>
#include <QMainWindow>
#include <QGridLayout>
#include <QScrollArea>
class ColoredWidget : public QWidget {
public:
ColoredWidget(const QColor& color, QWidget* parent) : QWidget(parent) {
QPalette pal;
QBrush brush(color);
brush.setStyle(Qt::SolidPattern);
pal.setBrush(QPalette::Active, QPalette::Window, brush);
setPalette(pal);
setAutoFillBackground(true);
}
};
class MainWindow : public QMainWindow {
public:
MainWindow(QWidget* parent) : QMainWindow(parent) {
resize(300, 400);
QWidget* centralwidget = new ColoredWidget(QColor(0xff, 0xf0, 0xb5), this);
QGridLayout* layout = new QGridLayout();
centralwidget->setLayout(layout);
setCentralWidget(centralwidget);
// create widget with fixed height of 20 px and maximum width of 200
QWidget* topHeader = new ColoredWidget(Qt::green, centralwidget);
topHeader->setMaximumWidth(200);
topHeader->setFixedHeight(20);
// create widget with fixed width of 20 px and maximum height of 200
QWidget* leftHeader = new ColoredWidget(Qt::blue, centralwidget);
leftHeader->setFixedWidth(20);
leftHeader->setMaximumHeight(200);
// create scroll area as main widget
QWidget* view = new QScrollArea();
layout->addWidget(topHeader, 0, 1);
layout->addWidget(leftHeader, 1, 0);
// layout->addWidget(leftHeader, 1, 0, Qt::AlignTop); // widget not displayed at all!
layout->addWidget(view, 1, 1);
}
};
int main(int argc, char ** argv) {
QApplication app( argc, argv );
MainWindow win(0);
win.show();
return app.exec();
}
The QGridLayout documentation says that "Columns and rows behave identically", thus I would expect that the two widgets are layouted the same way.
However, the left one is automatically vertically centered, while the top widget is aligned to the left within the cell (and not centered horizontally). I would like to have the left widget also at a fixed position, means aligned to the top:
Which property causes this different behaviour between the two widgets, one beeing centered, the other being at a fixed position?
How can I influence the alignment (I can probably add a flexible spacer to fix it, but ideally I would like to avoid that)? I tried with Qt::AlignTop, but that made the blue widget disappear.
Althought this question is pretty old, I will add my answer for all those that come here afterwards, like me.
Setting the alignment either with
layout->setAlignment(leftHeader, Qt::AlignHCenter | Qt::AlignTop);
or with
layout->addWidget(leftHeader, 1, 0, Qt::AlignTop);
is intuitiv and seems to be the right way. If it is setup completly it is also working as expected.
But why does the Widget vanish then?
Long story short: because leftHeader has a size of 0.
In my pretty similar situation I've setfixedHeight() and the widget reappeared, this should also work by setting a value for minimalHeight() for example.
Long Story - Details
I've put myself in position of gridLayout and tried to determine the size of leftHeader:
Outside of the layout leftHeader got a fixed width of 20 - ok, but no given height. With the defaults of QWidget this leads to a default-height of 0.
Documentation of void QGridLayout::addWidget() and void QGridLayout::addLayout() states:
... The alignment is specified by alignment. The default alignment is
0, which means that the widget fills the entire cell. ...
source
Hence for default alignment of 0 the height of leftHeader is obviously set as height of its row.
But in case a different Qt::Alignment is used, as in the question (Qt::AlignTop ), it is not that simple.
From my point of view the layout is unable to determine the correct height without further settings from the designer.
Having a quick look at the implementation of void QGridLayout::addWidget(), we can detect that a QLayoutItem(as part of QGridBox) is created inside the QGridLayout for each added widget resp. Layout.
So it seems that the QGridLayout relies on default layout mechanisms of Qt based on the settings from the added widget/Layout (like minSize, maxSize, BaseSize, Size Increment, etc ).
In combination with 1.) this implies a height of 0 for leftHeader and therefore nothing to draw resp. it seems that the widget has vanished.
Although not a minimal solution you could probably fix the alignments by adding a QHBoxLayout in the cell for the green widget and a QVBoxLayout in the cell for the blue widget. Add the green widget to the QHBoxLayout and the blue widget to the QVBoxLayout. Then apply addStretch(n) to both the QHBoxLayout and QVBoxLayout. Maybe this is what you already mentioned you could do and then we are at the same level of knowledge concerning this. I believe this is the way I have solved these kind of issues and I haven't spent more time on it.
Try this:
setAlignment(Qt::AlignHCenter | Qt::AlignTop );

How to set dock widget below widget

I want to set dock widget at place below a widget as in figure
But when I am setting geometry as start point of Y to equivalent the gap size but it is not working.
I think position of QDockWidget should be handled different way, then setting its geometry.
This example shows how QDockWidgets are positioned as you want + one more dock widget tabbed together with another one.
#include <QtGui>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Main window
QMainWindow *window = new QMainWindow;
window->setDockNestingEnabled(true);
// Anything to add as central widget
QWidget *widget = new QWidget;
window->setCentralWidget(widget);
// First dock in the left top corner
QDockWidget *dockWidget = new QDockWidget("--- 1 ---");
window->addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
// Second dock below first one
QDockWidget *dockWidget2 = new QDockWidget("--- 2 ---");
window->addDockWidget(Qt::LeftDockWidgetArea, dockWidget2);
// Third in tab with second one
QDockWidget *dockWidget3 = new QDockWidget("--- 3 ---");
window->tabifyDockWidget(dockWidget2, dockWidget3);
window->show();
return a.exec();
}
QMainWindow Has several functions how to handle spliting, moving or tabbing QDockWidgets

QDockWidget sized wrong when docked on right side of Main Window

I am new to Qt and I am trying to create a DockWidget that docks on the right of the window. I set a maximum and minimum width for the dock (as you will see in the code below). This works if the dock widget is added with Qt::LeftDockWidgetArea, but when it is added with Qt::RightDockWidgetArea, The dock is "padded" out to the center of the window, like this:
I am probably not sizing the dock in the correct way.. Here is the code for this window:
int main(int argv, char** args)
{
QApplication app(argv, args);
QMainWindow window;
QDesktopWidget* desktop = QApplication::desktop();
//Docks
QDockWidget* propertyDock = new QDockWidget("",&window);
QWidget* propertyDockContents = new QWidget;
//This sets the window in the center of the screen.
int wWidth = 800; int wHeight = 600;
window.setGeometry(QRect( (desktop->width()-wWidth)/2 , (desktop->height()-wHeight)/2 ,wWidth,wHeight));
propertyDock->setAllowedAreas(Qt::RightDockWidgetArea);
propertyDockContents->setMaximumWidth(200);
propertyDockContents->setMinimumWidth(20);
propertyDock->setWidget(propertyDockContents);
window.addDockWidget(Qt::RightDockWidgetArea,propertyDock);
window.show();
return app.exec();
}
Is there a "correct" way to do this?
As stated in the documentation:
Note: Creating a main window without a central widget is not supported. You must have a central widget even if it is just a placeholder.
Yes! You can't creating a main window without a central widget, But you can set central widget's height to zero.
MainWindow.cpp
centralWidget()->setMaximumHeight(0);

Layout with two tableviews problem

I have a widget containing two QTableViews in a horizontal layout. I would like them to resize to their preferred size (so that they don't have to show autoscrolls). I also don't want them to grow more than their preferred size and leave empty space to the right if there is any left. It should look like this:
I've tried to achieve it with a spacer on the right, but the views don't grow because of autoscrolls.
Can you propose any solution?
If I understood your question, you want the two QTableViews to resize to their PreferredSize if there is enough space (but no more than thier PreferredSize) and to shrink if there is not enough space. If there is too much space, it should be left empty. Here's an example that does it:
#include <QtGui>
int main(int argc, char **argv) {
QApplication app(argc, argv);
QMainWindow w;
QHBoxLayout *hbox = new QHBoxLayout;
QWidget *centralw = new QWidget;
centralw->setLayout(hbox);
w.setCentralWidget(centralw);
QTableView *t1 = new QTableView;
QTableView *t2 = new QTableView;
// Version one: the preferred size is the maximum size
// t1->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
// t2->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
// Version two: the preferred size is the only accepted size
// if you want the widgets not to change their size, change the two previous lines with
// t1->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
// t2->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
// hbox->addWidget(t1);
// hbox->addWidget(t2);
// add a stretch that will fill empty space
// hbox->addStretch(1);
// Version three: tables have a minimum and maximum width. They can be shrunk
// but they try to expand to take the maximum available space up to their maximum
// width.
t1->setMinimumWidth(150);
t1->setMaximumWidth(400);
t2->setMinimumWidth(100);
t2->setMaximumWidth(200);
t1->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
t2->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
hbox->addWidget(t1);
hbox->addWidget(t2);
hbox->setStretchFactor(t1, 1);
hbox->setStretchFactor(t2, 1); // tableviews have the same stretch factor
hbox->addStretch(0); // lowest stretch factor
w.show();
return app.exec();
}
You can reimplement parent's widget resizeEvent function and not to use a layout at all. So when the parent widget is resized you can manually set the sizes of your tables.
The other way you can try is to reimplement sizeHint or/and minimumSizeHint functions of the QTableView so they return a good for you size.
Also take a look at QSizePolicy - it may be usefull

Resources