I'm trying to learn how to create the layout of my Qt Symbian application so that it will expand/shrink and fit into the screen size of different devices.
In my default ui I have added a QTabWidget with five tabs that I want to fit into the screen of the device. I have two problems:
How can I make the tabs to shrink to always fit into the screen of the device, or is that not possible? What if one device has a width of 240px and another a width of 400px. As you can see now (Nokia Emulator) the tabs go outside of the screen. (And I don't want to use ScrollButtons)
As you can see in the red part of the picture (Nokia Emulator
) there is some spacing in the UI that I don't want. Instead I want the QTabWidget to fill the whole screen (all the red part).
In summary I'm learning right now and it would be great if you could give me some tips about where to look for more info regarding these problems with building an UI that fits into many devices and screen resolutions. Thanks!
This is the code in my UI file:
void setupUi(QMainWindow *UITest)
{
if (UITest->objectName().isEmpty())
UITest->setObjectName(QString::fromUtf8("UITest"));
UITest->resize(284, 167);
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(UITest->sizePolicy().hasHeightForWidth());
UITest->setSizePolicy(sizePolicy);
centralwidget = new QWidget(UITest);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
verticalLayout = new QVBoxLayout(centralwidget);
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
tabWidget = new QTabWidget(centralwidget);
tabWidget->setObjectName(QString::fromUtf8("tabWidget"));
tabWidget->setTabPosition(QTabWidget::South);
tabWidget->setUsesScrollButtons(false);
tab = new QWidget();
tab->setObjectName(QString::fromUtf8("tab"));
tabWidget->addTab(tab, QString());
...More tabs...
verticalLayout->addWidget(tabWidget);
UITest->setCentralWidget(centralwidget);
retranslateUi(UITest);
QMetaObject::connectSlotsByName(UITest);
} // setupUi
void retranslateUi(QMainWindow *UITest)
{
UITest->setWindowTitle(QApplication::translate("UITest", "UITest", 0, QApplication::UnicodeUTF8));
UITest->setStyleSheet(QApplication::translate("UITest", "background: red;\n" "padding: 0px;", 0, QApplication::UnicodeUTF8));
tabWidget->setStyleSheet(QApplication::translate("UITest", "background: white;\n" "margin: 0px;\n" "padding: 0px;", 0, QApplication::UnicodeUTF8));
} // retranslateUi
In main.cpp showMaximized() is used to show my widget as I also want the menu buttons in the bottom.
How do you show the widget? I suggest using the showFullScreen method to show it - that might do it.
Related
I am trying to add a QLabel with an image to my GUI at runtime, but the scaling is ignored and the image expands to its full size (which is larger than the screen), ignoring the size constraints and not scaling the contents correctly.
The image should be fit into the bottom, left side of the window, as my GridLayout describes here:
headerPnl= new HeaderPnl();
buttonPnl = new ButttonPnl;
mainContentPnl = new QStackedWidget;
mainLayout = new QGridLayout;
mainLayout->setMargin(0);
mainLayout->setSpacing(0);
mainLayout->addWidget(headerPnl, 0, 0, 1, 7);
mainLayout->addWidget(mainContentPnl, 1, 0, 10, 6);
mainLayout->addWidget(buttonPnl, 1, 6, 10, 1);
mainLayout->setRowStretch(0,1);
mainLayout->setRowStretch(1,2);
mainLayout->setRowStretch(2,2);
mainLayout->setRowStretch(3,2);
mainLayout->setRowStretch(4,2);
mainLayout->setRowStretch(5,2);
mainLayout->setRowStretch(6,2);
mainLayout->setColumnStretch(0,1);
mainLayout->setColumnStretch(1,1);
mainLayout->setColumnStretch(2,1);
mainLayout->setColumnStretch(3,1);
mainLayout->setColumnStretch(4,1);
mainLayout->setColumnStretch(5,1);
mainLayout->setColumnStretch(6,1);
this->setLayout(mainLayout);
The header goes across the top, the button panel goes along the right side, and the rest of the screen is changing depending on the workflow of the application (ie what buttons are pressed, etc).
When necessary, my GUI replaces the widgets and updates the GUI like this:
void MainWindow::setContentPane(QWidget *content){
mainLayout->replaceWidget(contentPnl, content);
contentPnl = content;
}
void MainWindow::setButtonPanel(QWidget *buttonPanel){
mainLayout->replaceWidget(buttonPnl, buttonPanel);
buttonPnl = buttonPanel;
}
void MainWindow::configureWelcome(){
QLabel *welcomeLbl = new QLabel;
welcomeLbl->setObjectName("welcomeLbl");
welcomeLbl->setPixmap(QPixmap(":/images/welcome.jpg"));
welcomeLbl->setScaledContents(true);
CustomWidget *welcomeWidget = new CustomWidget;
QHBoxLayout *welcomeLayout = new QHBoxLayout;
welcomeLayout->addWidget(welcomeLbl);
welcomeWidget->setLayout(welcomeLayout);
setContentPane(welcomeWidget);
CustomWidget *buttonPnl = createWelcomeButtonPanel();
setButtonPanel(buttonPnl);
}
How can I make this image fit inside the GridLayout properly? It seems like when adding widgets to a layout that has already been set, the GUI doesn't know how to handle the size constraints from the GridLayout. Replacing the buttons works fine, but adding an image does not.
Side question: I have been trying to stay away from a QStackedWidget, as this application is designed for a lower power system, and it doesn't make sense to me to create all the possible screens and add them all to a QStackedWidget when the application starts. Instead I would rather use the resources when necessary, and only create all the GUI elements when I need to (ie, when the right buttons are clicked). Does that make sense?
Did you had a QSizePolicy to the widget containing the QGridLayout? I suggest an horizontal and vertical QSizePolicy::Fixed.
In your first code segment add :
this->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
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.
Making my way up the Qt learning curve, I've seen many questions about dynamic layouts but the solutions aren't working for me or I don't quite understand them.
Reference questions:: Qt Scroll Area does not add in scroll bars, How can i make widgets overflow to make a scrollbar appear in Qt?
Question:: I want to have a dynamic layout of a set of widgets within a QScrollArea. I've been able to do this manually in Qt Creator and now I am trying to do it through code.
How do I prevent the widgets from stretching/force the area to scroll?
How do I have the added widgets start from the top? I have a vertical spacer in my QVBoxLayout but that pushes everything to the bottom.
Simple test code::
void MainWindow::on_pushButton_clicked()
{
ui->myScroll->setWidgetResizable(true); //making sure this is set
QPushButton *b = new QPushButton(this);
b->setText(QString("Hello Button"));
QHBoxLayout *h = new QHBoxLayout();
h->addWidget(b,0);
ui->myVBoxLayout->addLayout(h,0);
}
Result:: Left side squished (dynamic) – Right side Ok (set up manually)
Qt Creator Setup:: Left side: dynamic – Right side set up manually
Properties::
You can set use setMinimumHeight() on your buttons for preventing squished buttons. The layout can be configured with setContentsMargin() for space between item-border and item-content (QtDesigner has all four directions set to 9 IIRC) and setSpacing() for space between items (QtDesigner uses a default of 6). Also setWidgetResizable(true) allows your scrollarea to resize the view widgeth inside the area (this is where your layout and children are being placed).
This works for me:
In constructor or code set scrollArea->widget() to hold the QVBoxLayout:
v = new QVBoxLayout;
ui->scrollArea->widget()->setLayout(v);
In Button Slot:
void MainWindow::pushButtonPressed()
{
ui->scrollArea->setWidgetResizable(true);
QPushButton *b = new QPushButton(this);
b->setText(QString("Hello Button"));
QHBoxLayout *h = new QHBoxLayout();
h->addWidget(b,0);
v->addLayout(h);
}
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.
With some help from you QT sages, I was able to implement this window, with the desired layout and resizeability behavior. Now I have another interesting problem.
I want my entire window to have a "repeat-xy" seamless pattern. If I apply it to a simple window without layout and internal widgets, it works perfectly. I do however, now have a "tree" of widgets within widgets, and I can't set the stylesheet to draw my seamless background image to each and every one, cause it looks unnatural. The image must be underlying to all the widget topology I have. The problem is, it's invisible when i apply it to the bottom all-window-covering widget because it has widgets on top of it.
Is there a solution? maybe "transparent widgets" that can contain visible widgets?
I made the following using only CSS, there's a QPlainTextEdit, two QPushButton and a QLineEdit. In the image i added a red border to the QPlainTextEdit only so it can be seen, the rules are the following
QWidget#Form{
background-image: url(:/img/elephant_pattern.gif);
}
QPlainTextEdit{
background:transparent;
border:1px solid red;
}
As you can see all i had to was setting background transparent in the widgets i wanted.
Write your own widget that inherits QWidget. Reimplement the paintEvent and leave it empty. The widget itself won't be drawn, but its children will be.
my_widget::my_widget( QWidget* parent ) : QWidget( parent )
{
}
void my_widget::paintEvent( QPaintEvent* p_event )
{
// left empty to let my_widget be invisible
}
test_mw::test_mw( QWidget *parent ) : QMainWindow( parent )
{
test_widget = new my_widget( this );
QHBoxLayout* layout = new QHBoxLayout();
QPushButton* button0 = new QPushButton( "Button 0", 0 );
QPushButton* button1 = new QPushButton( "Button 1", 0 );
layout->addWidget( button0 );
layout->addWidget( widget );
test_widget->setLayout( layout );
setCentralWidget( test_widget );
}
Although the paintEvent of my_widget is empty, both QPushButtons are drawn. :-)
There was a QWidget::setBackgroundOrigin() method in earlier versions of Qt.
It's all done with styles now. See the examples http://doc.qt.nokia.com/latest/widgets-styles.html