How to Make Dynamic Screen of different size in QT for Nokia Devices in QT Creator?
Just set fullscreen window state on your topmost widget:
w->setWindowState(w->windowState() ^ Qt::WindowFullScreen);
The fullscreen window fills the entire screen without any frame around it.
do it in this way it works fine:
MyMainWindow::QMyMainWindow(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QFrame* frame = new QFrame(this);
setCentralWidget(frame);
frame->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QRect rect(0, 0, 240, 320);
frame->setFrameShape(QFrame::Box);
frame->setLineWidth(3);
frame->setFrameShadow(QFrame::Plain);
frame->setGeometry(rect);
adjustSize();
}
I didn't specify main window size at first and it would be totally expanded by central widget.
I also tried other SizePolicy values, but the resulting size of main window was not (240, 320) as expected at all.
Related
A qDockWidget containing a qCustomPlot always starts with zero height. I am able to catch the qDockWidget resize event and change the qCustomPlot geometry using these answers, but the qCustomPlot is always hidden until it is manually stretched. Should this happen automatically, or do I need to calculate and set the dock height at startup?
This sample code creates a new qCustomPlot widget, places it in a layout, places that layout in another widget, and sets it to the dock. I have also tried placing the qCustomPlot widget directly into the dock. qCustomPlot setGeometry, setMinimumSize, and setSizePolicy seem to have no effect on the dock height.
#include <QMainWindow>
#include "qcustomplot.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(){
QCustomPlot *m_customPlot;
QDockWidget *dock;
resize(1200, 600);
//create the plot
QWidget *plot_frame_temp= new QWidget();
plot_frame_temp->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding);
m_customPlot = new QCustomPlot(plot_frame_temp);
m_customPlot->axisRect()->setupFullAxesBox(true);
m_customPlot->setBackground(Qt::black);
//size and margin settings
m_customPlot->setGeometry(QRect(0, 0, 500, 400));
m_customPlot->axisRect()->setMinimumSize(500,400);
m_customPlot->axisRect()->setAutoMargins(QCP::msLeft|QCP::msBottom|QCP::msRight|QCP::msTop);
// zoom and drag only on horrizontal axis
m_customPlot->axisRect()->setRangeZoomAxes(m_customPlot->xAxis,nullptr);
m_customPlot->axisRect()->setRangeDragAxes(m_customPlot->xAxis,nullptr);
//setup the top axis and labels
m_customPlot->xAxis->setVisible(false);
m_customPlot->xAxis2->setVisible(true);
m_customPlot->xAxis2->setTicks(true);
m_customPlot->xAxis2->setTickLabels(true);
m_customPlot->xAxis2->setTickPen(QColor(136, 136, 136));
m_customPlot->xAxis2->setTickLength(0,10);
m_customPlot->xAxis2->setTickLabelColor(QColor(136, 136, 136));
m_customPlot->xAxis2->setSubTickPen(Qt::NoPen);
m_customPlot->xAxis2->setBasePen(Qt::NoPen);
QFont font;
font.setStyleStrategy(QFont::PreferOutline);
m_customPlot->xAxis2->setTickLabelFont(font);
//setup the left axis and hide
m_customPlot->yAxis->setVisible(false);
m_customPlot->yAxis->setRangeReversed(true);
m_customPlot->yAxis2->setVisible(false);
//first graph
m_customPlot->addGraph();
m_customPlot->graph()->setPen(QPen(QColor(165, 165, 165)));
m_customPlot->graph()->setLineStyle((QCPGraph::lsStepLeft));
//second graph
m_customPlot->addGraph();
m_customPlot->graph()->setPen(QPen(QColor(165, 165, 165)));
m_customPlot->graph()->setLineStyle((QCPGraph::lsStepLeft));
// make some data
QVector<double> x(500), y0(500), y1(500);
for (int i=0; i<500; ++i)
{
x[i] = i;
y0[i] = (rand() % 2 + 0.2)/2;
y1[i] = (rand() % 2 + 1.4)/2;
}
//add data to graph
m_customPlot->graph(0)->setData(x, y0);
m_customPlot->graph(1)->setData(x, y1);
// set some options
m_customPlot->setNotAntialiasedElements(QCP::aeAll);
m_customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
//add plot widget to layout
QHBoxLayout *laLayout = new QHBoxLayout();
laLayout->addWidget(plot_frame_temp);
//add layout to another widget
QWidget *laWidget=new QWidget();
laWidget->setLayout(laLayout);
//add second widget to dock
dock = new QDockWidget(tr("qcustomplot"), this);
dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
dock->setWidget(laWidget);
addDockWidget(Qt::BottomDockWidgetArea, dock);
QWidget *centralWidget=new QWidget();
setCentralWidget(centralWidget);
}
};
Here is a minimum example done directly in mainwindow.h. A dock with a central widget and a QDockWidget with a qCustomPlot. I am using the compiled DLL version of qCustomPlot
Image: dock starts with zero height:
Initially the dock looks like this. The plot is hidden and the dock is claiming no height in an otherwise empty layout.
Image: dock stretched to show the plot
The plot is visible when the user stretches the dock.
I strongly suspect there is a way for the dock to adjust to the height of the qCustomPlot automatically. I can set the dock height from code, but that seems like a hack.
The most direct approach to solve your issue might be to define a minimum size for your QCustomPlot Widget. This can easily achieved with the following reduced example. Actually, the problems has nothing to do with QCustomPlot at all. It could have been any kind of widget with minimum size (0,0).
#include <QMainWindow>
#include "qcustomplot.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(){
auto m_customPlot = new QCustomPlot();
m_customPlot->axisRect()->setupFullAxesBox(true);
auto dock = new QDockWidget(tr("qcustomplot"), this);
dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
dock->setWidget(m_customPlot);
m_customPlot->setMinimumSize(QSize(500,500));
dock->setMinimumSize(m_customPlot->minimumSize());
addDockWidget(Qt::DockWidgetArea::BottomDockWidgetArea, dock);
setCentralWidget(new QWidget);
}
};
A better solution might to save and to restore the geometry of your dock widget configuration in the registry. This leaves the user with just the dock widget configuration that he finds desirable.
void MainWindow::closeEvent(QCloseEvent *event)
{
QSettings settings("MyCompany", "MyApp");
settings.setValue("geometry", saveGeometry());
QMainWindow::closeEvent(event);
}
QSettings settings("MyCompany", "MyApp");
dock->restoreGeometry(settings.value("myWidget/geometry").toByteArray());
How do the options size policy and stretch factors influence the size of a widget?
The image below shows previews of three differently arranged windows. For all three windows (W1-W3) the widget on the right is a QFrame widget with the horizontal and vertical size policies set to Preferred (this is the default setting). The horizontal stretch factor is set to 2. The widget on the left is a QListView widget which also has the size policies set to Preferred (by default this would be Expanding) and the horizontal stretch factor set to 1.
The three windows differ in the way the two widget are layout against each other.
(W1) The window on the left in the image above has a central widget set to a horizontal layout resulting in a size ratio of 2/3 of the widgets that I would expect because of the stretch factors set to 2 and 1.
(W2) The two widget are "connected" with each other through a QSplitter widget. The central widget is set to t horizontal layout. The results of the size of the widgets differ from W1 and are not in the ratio of 2/3.
(W3) The right window "connects" the two widget also with a QSplitter like in window W2. Howevert, The QListView widget is child to a QVBoxLayout. So the QSplitter has the QFrame and a QVBoxLayout as its children.
In detail the setup for the three different windows is shown in the image below:
I have the following questions:
Why do the ratios of the two widgets differ between W1, W2 and W3?
The ratio in W2 seems to be affected by the stretch factors, however not with the results expected. But W3 does not seem to be influenced by the stretch factors at all. Why is that the case?
The behavior of the splitter with relation to stretch factors is documented to be different than the behavior of a layout: you shouldn't expect them to look the same.
The W2 & W3 should look identical if implemented as you claim. Your ui file has a mistake in it.
Here's a test case that doesn't use a .ui file:
// https://github.com/KubaO/stackoverflown/tree/master/questions/layout-stretch-triad-37680657
#include <QtWidgets>
struct Window : public QMainWindow {
QWidget central;
QHBoxLayout layout{¢ral};
QListView view;
QFrame frame;
Window(const QString & title) {
setWindowTitle(title);
setCentralWidget(¢ral);
view.resize(300, 300);
view.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
frame.resize(300, 300);
frame.setLineWidth(3);
frame.setFrameStyle(QFrame::Box);
resize(500, 200);
show();
}
};
struct Window1 : Window {
Window1() : Window("W1") {
layout.addWidget(&view, 1);
layout.addWidget(&frame, 2);
}
};
struct Window2 : Window {
QSplitter splitter;
Window2() : Window("W2") {
layout.addWidget(&splitter);
splitter.addWidget(&view);
splitter.addWidget(&frame);
splitter.setStretchFactor(0, 1);
splitter.setStretchFactor(1, 2);
}
~Window2() { frame.setParent(0); view.setParent(0); }
};
struct Window3 : Window {
QSplitter splitter;
QWidget leftWidget;
QVBoxLayout leftLayout{&leftWidget};
Window3() : Window("W3") {
layout.addWidget(&splitter);
splitter.addWidget(&leftWidget);
splitter.addWidget(&frame);
splitter.setStretchFactor(0, 1);
splitter.setStretchFactor(1, 2);
leftLayout.setMargin(0);
leftLayout.addWidget(&view);
}
~Window3() { frame.setParent(0); view.setParent(0); }
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
Window1 w1;
Window2 w2;
Window3 w3;
w2.move(w1.pos() + QPoint(0, 75));
w3.move(w2.pos() + QPoint(0, 75));
return app.exec();
}
I am creating some images rendering the contents of a QGraphicsScene.
My project requirement is that it should handle a canvas size of 10 ft by 8 inches. On screen, and scene size, that is 8640 x 576 pixels.
I can render it fine.
The thing is, the output images need to have 300 resolution.
That means, the rendered image will have a width of 36000, which is over 2^15 - 1 = 32767 pixels.....
The output is clipped - in the code below, I would get a QImage of correct expected size (36000) but the QGraphicsScene only renders to 32767 pixels.
That is confusing... I cannot explain the outcome - if the QImage limitations were 32767 pixels, then I should not be able to create one in the first place. But I checked and the QImage "sanity check" is much higher.
Once the image is created, I do not see anything in the code for rendering QGraphicsScene that would clip at any value....
This is a simple code that is trying to expose my problem.
It creates a QImage of required size, and fills with yellow (for control).
Then it renders a QGraphicsScene with blue background brush and a red rectangle close to the right margin.
If it works correctly, the result should be: an image of width 36000, blue with a tiny red rectangle at the far right.
But... as it is, the result is an image of width 36000, blue for the first 32766 pixels then yellow for the rest, no red rectangle.
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QPainter>
void printScene(QGraphicsScene* s, qreal ratio) {
qreal w = s->width() * ratio;
qreal h = s->height() * ratio;
QRectF target(0, 0, w, h);
QImage image = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
image.fill(QColor(Qt::yellow).rgb());
QPainter painter;
painter.begin(&image);
s->render(&painter, target);
painter.end();
image.save("image.png");
}
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGraphicsScene s;
s.setSceneRect(0, 0, 8640, 576);
s.setBackgroundBrush(Qt::blue);
QGraphicsView view(&s);
view.show();
QGraphicsRectItem* r = s.addRect(8530, 250, 100, 100);
r->setBrush(Qt::red);
qreal ratio = 300/72.;
printScene(&s, ratio);
return app.exec();
}
As seen in sample images, the QImage is created successfully, QGraphicsScene though only renders to 2^15 - 1... But I stepped through their code and I didn't see it stop....
(I also tried creating the original scene 36000 x something (and setting the ratio to 1), and it displays fine... it just won't render to QImage anything beyond 32767 pixels)
Am I missing some setting ? What could be the cause of the QGraphicsScene::render() to not render more ?
I would love to find out how I can render the size I want - width of 36000 pixels - or a reason why this is not possible.
I am running this in Windows 7, 32 bit Qt 5.5.1 or 4.7.4
I have found the reason for the clipping - and imagined 2 workarounds.
Why:
Stepping through the rendering code, the clip rect gets limited to 32767:
bool QRasterPaintEngine::setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op)
{
Q_D(QRasterPaintEngine);
QRect clipRect = r & d->deviceRect;
...
}
Where deviceRect is set by
void QRasterPaintEnginePrivate::systemStateChanged()
{
deviceRectUnclipped = QRect(0, 0,
qMin(QT_RASTER_COORD_LIMIT, device->width()),
qMin(QT_RASTER_COORD_LIMIT, device->height()));
QRegion clippedDeviceRgn = systemClip & deviceRectUnclipped;
deviceRect = clippedDeviceRgn.boundingRect();
baseClip->setClipRegion(clippedDeviceRgn);
...
}
and
// This limitations comes from qgrayraster.c. Any higher and
// rasterization of shapes will produce incorrect results.
const int QT_RASTER_COORD_LIMIT = 32767;
Options:
1) Render to a max of 32767 and, if the target must be bigger, scale result. (should give slightly lower quality)
2) Create 2 images and combine them (I still need to figure that out but I think it is the better fix)
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 );
I have four widgets in a QWidgets named FourWindowWidget I am trying to put these four widgets in FourWindowWidget as one at top and remaining under that while the top one should always have 70% of the size of FourWindowWidget. I tried following :
QSize size = ui->FourWindowWidget->size();
ui->View1->setFixedHeight(size.height()*0.70);
QHBoxLayout * lay = new QHBoxLayout();
lay->addWidget(ui->View2);
lay->addWidget(ui->View3);
lay->addWidget(ui->View4);
lay->setMargin(0);
lay->setContentsMargins(0,0,0,0);
QGridLayout * mainlay = new QGridLayout;
mainlay->addWidget(ui->View1,0,0);
mainlay->setContentsMargins(0,0,0,0);
mainlay->setHorizontalSpacing(0);
mainlay->setSpacing(0);
mainlay->setMargin(0);
mainlay->addLayout(lay,1,0);
delete ui->FourWindowWidget->layout();
ui->FourWindowWidget->setLayout(mainlay);
this->update();
Now the problem is now View1 have fixed size but size of FourWindowWidget is not fixed. It changes when I remove any other widget around it like closing dock widget. This resize is expected, or say I don't want to make it fixed. So when ever FourWindowWidget get resized its child widgets should be as per ratio set. But I am unable to do this cause
1. There is no any signal that inform resize so the height of internal widget will be calculated.
2. No other way I found to set 70% height of top widget rather than setFixedHeight in grid layout.
I have tried with setting QSizePolicy to setHieghtForWidth but iit is not a working solution.
Please suggest me to do this by any way.
The Question is kind of duplicat of Resizing Qt Widgets based on Window size but there nobody answered.
Setting the stretch factor for your layout should work. I'm not sure why you are using a grid layout for this, when you are adding everything in the same column, but here is an example that works:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
gridLayout = new QGridLayout;
this->centralWidget()->setLayout(gridLayout);
label1 = new QLabel("l1");
label2 = new QLabel("l2");
label3 = new QLabel("l3");
label4 = new QLabel("l4");
gridLayout->addWidget(label1, 0, 0);
gridLayout->addWidget(label2, 1, 0);
gridLayout->addWidget(label3, 2, 0);
gridLayout->addWidget(label4, 3, 0);
gridLayout->setRowStretch(0,7);
gridLayout->setRowStretch(1,1);
gridLayout->setRowStretch(2,1);
gridLayout->setRowStretch(3,1);
}
In this example label1 will take 70% of the available vertical space, while the other labels will take combined 30% of the available vertical space.