Tabbed Dialog Box using Qt Designer - qt

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.

Related

Proper way to manually set the layout of a window in 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.

Change Widget Constructor in UI

I ran into a problem with Qt while promoting my QGLWidget for the GUI.
Since the constructor of my QGLWidget is
GLWidget::GLWidget( const QGLFormat& format, QWidget* parent )
: QGLWidget( format, parent ),
m_vertexBuffer( QGLBuffer::VertexBuffer ) {}
So the object should get instantiated like this
QGLFormat glFormat;
glFormat.setVersion( 3, 3 );
glFormat.setProfile( QGLFormat::CoreProfile );
glFormat.setSampleBuffers( true );
GLWidget w( glFormat, parent );
But the ui_mainwindow.h does this automatically with
widget = new GLWidget(centralWidget);
which can't be modified due to the fact that the ui_mainwindow.h is created new every time the UI is recompiled. So I will probably have to tell in my maindwindow.cpp that the GLWidget is to be instantiated different from the standard constructor, but with a QFormat. Any idea how this is done?
I believe this can not be achieved using the Qt Designer auto-generated code.
There are atleast two different kind of solutions for this:
Subclass QGLWidget to set the QGLFormat in its MyGLWidget(QWidget* parent = 0); constructor.
or
Create the widget manually (without Qt Designer).
I prefer the latter one because I like to be in control.

Subclassing QUiloader and reimplementing createWidget function of it

I needed to read widget classnames, names etc from gui loaded via QUiloader.
And I got answer here that I needed to subclass QUiloader and reimplement its method.
I have MainWindow, and via menu/toolbar I load the file, and show it. And when I load I want to know what elements are in that gui to work further with them.
The code I got from a user here:
class UiLoader : public QUiLoader
{
Q_OBJECT
public:
QStringList *wlist;
UiLoader(QObject *parent = 0) : QUiLoader(parent) {}
virtual QWidget* createWidget(const QString &className, QWidget *parent =0, const QString &name = QString())
{
QWidget* widget = QUiLoader::createWidget(className, parent, name);
//here do my stuff with className, parent, name
return widget;
}
};
I used Uiloader to load my file. And it is working.
My question now is how I intercept createWidget before returning widget, I want to get the list of widget and then return Widgets.
I do not know how what is the efficient way to create a list as simple as this one:
0=>TextBox, 1=>Button, ...
I really do not care about the structure I just need to know which one comes first and what it is.
Thanks.
I wouldn't reimplement class loader at all honestly.. May be only if you need to 'inject' something into existing code which use QUiLoader a lot.. but in general only thing you need:
pWidget = ...->createWidget(...);
QList<QWidget *> widgets = pWidget->findChildren<QWidget *>();
here you go, your widgets contains list of all form components..

Changing QWidget with QGlWidget in Qt 4.8.0

I am working on an application that currently uses QWidgets for rendering moving images, and I am trying to move from using QWidgets to QGlWidgets, but my application keeps crashing.
The only modifications I've done are:
from this:
class MyClass : public QWidget
{
MyClass(QWidget *parent):QWidget(parent)
{
...
}
}
to this:
class MyClass : public QGlWidget
{
MyClass(QWidget *parent):QGlWidget(QGLFormat(QGL::SampleBuffers),parent)
{
...
}
}
Do I have to modify my code more, if so what other modifications are needed?
I am currently using Visual studio 2010, and qt 4.8.0
MyClass(QWidget *parent):QGlWidget(QGLFormat(QGL::SampleBuffers),parent)
{
...
}
It looks like you're creating a temporary QGLFormat object, which is being passed by reference to QGLWidget, and when that temporary object goes out of scope, you'll have an invalid reference.
I would use a different form of the constructor.
I found what the problem was.
In my QWidget class I had a member object QPainter, that I would reuse in the paint event. I kept searching and found that this is a bad practice, so now I declared a QPainter object at the beginning of the paint event and my problem is solved.

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