Proper way to manually set the layout of a window in Qt - qt

I need a QMainWindow layout to change depending on the number of cores.
Therefore I set it manually (not using the Design mode).
My question is:
After this layout was created, how can I refer to the widgets it contains?
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//...
buildLayout();
//...
// Now I'd like to use something like this:
// ui->threadingTable->...
// However, it's not the member of ui
}
void MainWindow::buildLayout()
{
QWidget *window = new QWidget(this);
QTableView *threadingTable = new QTableView(window);
//...
QGridLayout *layout = new QGridLayout(window);
layout->addWidget(threadingTable, 0, 0);
//...
window->setLayout(layout);
this->setCentralWidget(window);
}
I can get the QLayoutItem out of this->centralWidget().
Or I can make all widgets in layout members of MainWindow class and access them directly.
However, I feel that neither of these is the right way.
Is there a way to pass the widgets to ui?
So that I could access them by calling
ui->threadingTable

Both options are fine. It is possible to get pointer to threadingTable from the main class member or directly from the objects hierarchy:
qDebug() << qobject_cast<QGridLayout *>(this->centralWidget()->layout())->itemAtPosition(0, 0)->widget();
qDebug() << this->centralWidget()->layout()->itemAt(0)->widget();
Of course, null verification may be required. You can also check this question QGridLayout: Getting the list of QWidget added.
The class Ui::MainWindow is automatically generated from the .ui xml form that can be generated in the Design mode: "Using a Designer UI File in Your Application"
Since the layout is constructed manually the .ui file and the ui instance is not needed at all. You can remove them from your project.
On the other hand, it is possible to use custom widgets even in the Design mode in .ui forms.
So, if you need some tricky object you can build the entire form in handy Design mode and then, for example, the standard QTableView may be promoted to your CustomTableView that is inherited from QTableView. That custom class may implement some special behavior.

Related

Correct way of promoting QTableWidget

I need to have a custom qtablewidget for which I've promoted built in QTableWidget as follows :
Just created a class called Inventory, then inherited it from QTableWidget, added a qtablewidget into mainwindow from the qt designer and promoted it to Inventory class
//inventory.h
#ifndef INVENTORY_H
#define INVENTORY_H
#include <QTableWidget>
class Inventory : public QTableWidget
{
public:
Inventory(QTableWidget* parent = 0);
};
#endif // INVENTORY_H
//inventory.cpp
#include "inventory.h"
Inventory::Inventory(QTableWidget *parent)
: QTableWidget(parent)
{
setRowCount(3);
setColumnCount(3);
horizontalHeader()->setDefaultSectionSize(160);
verticalHeader()->setDefaultSectionSize(160);
}
but for some reason it just won't build correctly, throwing this instead:
error: invalid conversion from ‘QWidget*’ to ‘QTableWidget*’ [-fpermissive]
tableWidget = new Inventory(centralWidget);
^
in a ui_mainwindow.h file at the line
where tableWidget is declared as Inventory* tableWidget
what is wrong ??
How to fix this ?
p.s.
building with qt 5.7.1
and qtcreator 4.2.0
I think you are confused between your derived class which base is QTableWidget and the constructor for your derived Inventory class.
Obviously for Qt and Qt Editor to work, you need to define a
Inventory::Inventory(QWidget* parent = 0)
constructor, taking a QWidget as a parent widget. ( parent here in the sense of container widget, often a layout)
Your constructor is taking a QTableWidget* which seems very fishy to me, and your compiler is telling you that a QWdget* is not a to QTableWidget*, which makes sense.
Change the signature of the Inventory constructor should make the job

Tabbed Dialog Box using Qt Designer

I'm new to Qt and having a problem with the TabbedDialog box designed using the Qt Designer.
I have a Dialog dlg on which i have placed a tabWidget MyTabWidget containing two tabs Tab1 and Tab2. I want to make separate cpp files for each tab and define the functions in their respective files. the problem i'm having is how to access the UI widgets of the dialog dlg in these respective files.
There are a few steps to be taken here which is well-explained in the following documentation.
1) Include #include "ui_foo.h"
This is necessary to access the UI elements in your code. This is the file that is available through the QtDesigner and ui compiler, aka. uic process.
2) Either inherit Ui::Foo or have an object with composition with it within your class. It would be something like:
class Foo : public QWidget
{
Q_OBJECT
public:
Foo(QWidget *parent = 0);
private:
Ui::Foo ui;
};
or
class Foo : public QWidget, private Ui::Foo
{
Q_OBJECT
public:
Foo(QWidget *parent = 0);
};
3) Then you can use this instance to access the widgets (something like ui->foo) created by the QtDesigner application.
bool Foo::doStuff()
{
ui->foo()->doStuff();
}
You probably do not wish to have two separate source files and classes as you wrote, but if you wish, the above steps could be applied for both.
That being said, I think it is better if you go through the aforementioned documentation because it is lot more detailed about the several approaches, and how to access the UI components in your source code generated by QtDesigner.
You can pass a tab pointer to your function you want to use. Something like:
void Class1::yourFunction1(QWidget *tab1);
void Class2::yourFunction2(QWidget *tab2);
You can access these widget tabs like:
ui->tab
if it was created in QtDesigner.

How to build a simple custom widget with Qt?

How to build a simple custom widget with Qt? The widget is very simple with just 2 line edit QLineEdit' in a vertical box layoutQVBoxLayout`. How to do it? I read Qt's examples on custom widget generation. They reimplement paint event to rendering the custom widget. However, mine is so simple that I cannot find a solution in Qt's reference.
Well to do it all programatically it would look something like this:
class MyWidget : public QWidget {
public:
MyWidget(QWidget *parent=0) : QWidget(parent) {
QVboxLayout *layout = new QVboxLayout();
setLayout(layout);
layout->addWidget(new QLineEdit());
layout->addWidget(new QLineEdit());
}
};
Depending on your needs you could make the line edits member variables and manipulate them as you see fit.

connect from a QTab (in a QTabWidget) back to QMainWindow

The main Part of my Application is a Systray-Menu. For maintenance there should be a normal GUI.
My Problem is that now I have to create two Signal/Slot-Connections back to the MainWindow from each Tab. This is for minimizing the GUI and to update the Menu. I don't know how to do this.
I tried to connect with this->parent->parent from the ManageSession and ui_manag->session_ui->minimizeButton from MainWindow. I have a little knot in my head and am asking for help. Or should I re-think my design? I´m using only QtCreator 2.6.1 with Qt 4.8.4.
Screenshots of the GUI-Elements
This is the mainwindows.cpp:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle(QCoreApplication::applicationName());
QWidget *mainWidget = new QWidget;
QTabWidget *ui_manag = new ManageTab;
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(ui_manag);
mainWidget->setLayout(mainLayout);
setCentralWidget(ui_manag);
ui_manag->setCurrentIndex(0);
//Here comming Code to setup a TrayIcon, the Database and the Menus
}
The Tab is completely generated by the Designer:
ManageTab::ManageTab(QWidget *parent) :
QTabWidget(parent),
tab_ui(new Ui::ManageTab)
{
tab_ui->setupUi(this);
}
For each Setting I use the same GUI with multiple inheritance:
ManageSession::ManageSession(QWidget *parent) :
QWidget(parent),
session_ui(new Ui::ManageWidget)
{
session_ui->setupUi(this);
session_ui->manageLabel->setText(tr("Manage Session"));
connect(session_ui->addButton, SIGNAL(clicked()), this, SLOT(addButton_clicked()));
connect(session_ui->editButton, SIGNAL(clicked()), this, SLOT(editButton_clicked()));
connect(session_ui->deleteButton, SIGNAL(clicked()), this, SLOT(deleteButton_clicked()));
}
//Here follows the Functions for manipulating the TableView
// and emmiting a Signal to Update the Menu
Let's remake it in an answer (so you can accept it, hehe. j/k, to long for a comment):
First. As i said in comment:
You are inheriting without specifying access. So it defaults to private. That's why
ui_manag->session_ui->minimizeButton
wont allow you to access the button.
Second.
parent is a method, so It's: this->parent()->parent() or just parent()->parent() ;)
Again, it probably needs to inherit public. Not sure, tho.
That should work then.

How can I add another tab that looks exactly like the first one (like in a browser)?

I have a browser made in Qt and a I have a tabwidget with one tab (which has a label, lineedit and a webview). I want to add others that look like the first one (have label, lineedit and webview).
How can I do this?
I don't know of any way to "clone" or duplicate an existing tab or widget, so I believe you'll need to code the tab contents yourself (i.e. not through the designer).
If all you need are a QLabel, a QLineEdit and a QWebView, that's not very complex. The idea would be to:
create a custom widget (inheriting from QWidget directly, or from QFrame)
lay out the contained widgets in the fashion you want in its constructor
add as many tabs as you want, when you want them, via the QTabWidget.addTab function.
The Tab Dialog example has everything you need - it's actually more complex than what you need because it uses different widgets for each tab. You can get away with a single widget.
If you wonder how to do the layout, and you're satisfied with what you got from the designer, you can inspect the generated (.moc) files. You'll see what layouts it uses, and you can replicate that in your own code.
Skeleton widget:
class BrowserTab : public QWidet
{
Q_OBJECT
public:
BrowserTab(QUrl const& home, QWidget *parent = 0);
void setUrl(QUrl const& url);
private:
QWebView *web;
QLabel *title;
QLineEdit *urlEdit;
};
BrowserTab::BrowserTab(QUrl const& home, QWidget *parent)
: QWidget(parent)
{
urlEdit = new QLineEdit(this);
title = new QLabel(this);
web = new QWebView(this);
QVBoxLayout *vl = new QVBoxLayout;
vl->addLayout(title);
vl->addLayout(urlEdit);
vl->addLayout(web);
setLayout(vl);
setUrl(home);
}
void BrowserTab::setUrl(QUrl const& url)
{
web->load(url);
// update label & urlEdit here
}
You'll need to do a bit more to make it a proper browser (setUrl should probably be a slot too), but this should get you started.

Resources