Can i use quick controls in a qt widgets application? - qt

I need material styled replacements of standard widgets and it's kind of hard to implement them by using custom widgets. I was wondering if there's any way to include widgets from quick control module and use them as regular widgets?

If your application is Qt5.1 and above, the answer is yes you can.
You have to use the QQuickView object and pass it to static function createWindowContainer of QWidget, which takes QWindow as in paramater.
QQuickView derived from QQuickWindow which is derived from QWindow.
So you can pass a QQuickView as an input to the createWindowContainer.
Below is some rough code.
//CREATE A QQuickView OBJECT.
QQuickView *view = new QQuickView();
//ADD THE QQuickView OBJECT TO QWidget::createWindowContainer
QWidget *container = QWidget::createWindowContainer(view, this);
//ADD SOURCE
view->setSource(QUrl("your.qml"));
//ADD THE CONTAINER TO YOUR LAYOUT.
ui->verticalLayout->addWidget(container);

You can use QQuickWidget if you want to insert your QML view in a layout :
//CREATE THE QQuickWidget
QQuickWidget *quickWidget = new QQuickWidget(this);
//ADD SOURCE
view->setSource(QUrl("your.qml"));
//ADD THE QQuickWidget TO YOUR LAYOUT.
ui->verticalLayout->addWidget(quickWidget);
I adapted #katamarayudu's code to use QQuickWidget instead of QQuickView.

Related

QStackedWidget connect QActions to custom QGraphicsView of QWidget

I've made a MainWindow with a QStackedWidget and a QMenuBar.
One of my widgets contains a QGraphicsView that I promoted to my custom QGraphicsView (DrawingView).
I'd like to connect the QActions from the menuBar to my custom DrawingView.
I managed to get the QActions that were connected to the widget working, but I don't know how to access the methods from the DrawingView.
This is the code I used for the other QActions:
draw = qobject_cast<Drawing*>(ui->stackedWidget->widget(1));
connect(ui->actionOpen, &QAction::triggered, draw, &Drawing::openPhoto);
connect(ui->actionSave, &QAction::triggered, draw, &Drawing::saveFile);
connect(ui->actionExit, &QAction::triggered, draw, &Drawing::close);
I tried this for the DrawingView, but I know that it just makes a new DrawingView instead of using the one from the Draw ui.
drawView = new DrawingView();
connect(ui->actionZoom_In, &QAction::triggered, drawView, &DrawingView::zoomIn);
connect(ui->actionZoom_Out, &QAction::triggered, drawView, &DrawingView::zoomOut);
I also tried this, which gave an error on ui->stackedWidget->widget(1)->graphicsView:
drawView = qobject_cast<DrawingView*>(ui->stackedWidget->widget(1)->graphicsView); //also tried (ui->stackedWidget->widget(1)->ui->graphicsView)
connect(ui->actionZoom_In, &QAction::triggered, drawView, &DrawingView::zoomIn);
connect(ui->actionZoom_Out, &QAction::triggered, drawView, &DrawingView::zoomOut);
Any help on how to connect from the MainWindow or how to access the ui of MainWindow inside 2nd widget.
Isn’t your problem simply that graphicsView is a private member of the containing widget?
You could either make it a public member or add a wrapper function:
auto draw = qobject_cast<Drawing*>(ui->stackedWidget->widget(1));
connect(ui->actionZoom_In, &QAction::triggered, draw, &Drawing::zomIn);
and in the Drawing class:
void Drawing::zoomIn() {
ui->graphicsView.zoomIn();
}
A third option is to
emit a custom zoomIn signal from the MainWindow
make the main window accessible to Drawing (e.g. passing it to the constructor or creating a global mainWindow singleton)
and do the connect directly in Drawing

deleting widget of QScrollArea

i have to update or change the widget inside the scrollArea depending on the selection of tree items in left.
QWidget *scrollAreaWidget = new QWidget;
scrollAreaWidget->setObjectName("ScrollAreaWidget");
QVBoxLayout *scrollLayout = new QVBoxLayout;
scrollAreaWidget->setLayout(scrollLayout);
foreach (PyInfo pInfo, list) {
//Adding widget
rowWidget->setObjectName(objName);
scrollLayout->addWidget(rowWidget);
}
m_pScrollArea->setWidget(scrollAreaWidget);
so when i need to update a new widget i tried to clear the old widget added to scrollArea like this
QWidget *wid = m_pScrollArea->widget();
if(wid)
wid->deleteLater();
is deleteLated() call is enough or i have to explicitly delete all the widgets i added as a child to the ScrollArea->widget() and disconnect my signals in it.
Yes, this should be enough. Qt takes care about the rest. From Qt documentation:
The parent takes ownership of the object; i.e., it will automatically
delete its children in its destructor.
......
A signal-slot connection is removed when either of the objects
involved are destroyed.

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.

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.

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