If I just start from main with a QGraphicsView, it displays.
But if I place the QGraphicView in mainwindow.cpp, it flashes up and disappears??
int main(int argc, char **argv)
{
QApplication a(argc, argv);
QGraphicsView view;
view.resize(1000, 800);
view.show();
return a.exec();
}
int main(int argc, char **argv)
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPushButton *m_button1 = new QPushButton("1", this);
m_button1->setGeometry(QRect(QPoint(100, 100), QSize(100, 100)));
connect(m_button1, SIGNAL(released()), this, SLOT(handleButton1()));
}
void MainWindow::handleButton1()
{
QGraphicsView view;
view.resize(1000, 800);
view.show();
}
You've created a local QGraphicsView variable there in the handleButton1() function that will be destroyed as soon as the function finishes, in your first example, the view would exist until the end of main() which is the end of the application, i.e it exists until you close the application. Your best bet would be to either use Qt Designer to place the QGraphicsView in the MainWindow or to give MainWindow a private QGraphicsView* member variable
If you use a private variable, use Qts built in memory management to set the parent of it to the MainWindow so it's cleaned up when the window is destroyed.
class MainWindow : QMainWindow {
// etc...
private:
QGraphicsView *view;
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) {
ui->setupUi(this);
view = new QGraphicsView(this);
view->setGeometry(QRect(50, 50, 400, 200));
view->show();
// etc...
}
Instead of using 'this' as above, if you have a central widget, or any widget where you want the QGraphicsView, you would do
view = new QGraphicsView(ui->centralWidget);
Related
Im using setAttribute(Qt::WA_TranslucentBackground); to make my QMainWindow background transparent, however, this attribute only work if:
I also set: setWindowFlag(Qt::FramelessWindowHint);
or, have at least one QOpenGLWidget in my GUI.
I have no experience with QOpenGlWidget, i wonder if its possible to use QSurfaceFormat or something like, to achieve the same 'thing' QOpenGL does when added to a QMainWindow, that makes the attribute work.
Or if there's any other 'option' than setting the FramelessWindowHint flag or creating an QOpenGL widget.
Example code:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
/*
QSurfaceFormat format;
format.setAlphaBufferSize(8);
QSurfaceFormat::setDefaultFormat(format);
QSurfaceFormat format;
format.setAlphaBufferSize(8);
format.setSamples(16);
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
format.setRenderableType(QSurfaceFormat::OpenGL);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
*/
MainWindow w;
w.show();
return a.exec();
}
//mainwindow.h
#include <QtWidgets/QMainWindow>
#include "ui_MainWindow.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindowClass; };
QT_END_NAMESPACE
class MainWindow : public QMainWindow{
Q_OBJECT
public:
MainWindow(QWidget* parent = nullptr);
}
//mainwindow.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindowClass())
{
ui->setupUi(this);
setAttribute(Qt::WA_TranslucentBackground);
QGridLayout* layout = new QGridLayout();
ui->centralWidget->setStyleSheet("background-color: transparent;");
ui->centralWidget->setLayout(layout);
QWidget* widget = new QWidget(this);
widget->setStyleSheet("background-color: green; border-radius: 32px;");
layout->addWidget(widget);
//QOpenGLWidget* opengl = new QOpenGLWidget(this);
//opengl->deleteLater();
}
Creating the QOpenGlWidget and calling opengl->deleteLater() the WA_TranslucentBackground works, however, it make the application use 50mb more of ram compared to not creating the QOpenGLWidget.
This is not much if i were creating just one GUI, but I'm creating multiples.
Why not try setting the opacity level of the window by changing the windowOpacity property using setProperty?
Example:
YourWindow->setProperty("windowOpacity", 0.0);
Setting the opacity level to 0 results in a transparent background
i am new at QT
i created a window and i want to add a button on this window but the button is opened in different window.
How to add this button to default window
Here is my code;
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QPushButton"
#include "QDesktopWidget"
#include <iostream>
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
QPushButton* buton1 = new QPushButton("Hello");
buton1 -> setGeometry(QRect(QPoint(100,100),QSize(200,50)));
connect(buton1, &QPushButton::released, this, &MainWindow::buton_fonk);
buton1 -> show();
ui->setupUi(this);
}
void MainWindow::buton_fonk()
{
cout << "here" << endl;
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QDesktopWidget>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.setWindowState(Qt::WindowMaximized);
w.showFullScreen();
return a.exec();
}
You need to make QPushButton a child of the main window for it to be rendered inside the main window, otherwise QPushButton will be an independent widget.
Usually all Qt Widgets accept a pointer to parent widget, QPushButton also accept a pointer to parent widtet.
QPushButton(const QString &text, QWidget *parent = nullptr)
To make QPushButton child of MainWindow, add this as second parameter to QPushButotn constructor.
QPushButton* buton1 = new QPushButton("Hello", this); // Make MainWindow as parent of QPushButton
Ideally you should create a layout and add all your widgets to this layout and then set the central widget of MainWindow to this layout.
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(button1);
// Add anyother widget to your layout
this->setCentralWidget(mainLayout);
Hope this helps.
I have a QQuickwidget in a Qt C++ application where i have loaded a QML file (main.qml) and using QAction(actionstart) and C++ functions i have to load another QML file(main1.qml) slightly different to previous one on the same QQuickWidget object.
I am able to do this , but my 2nd QML file is overlapped from the middle section of QQuickwidget and further.
I have did this to stop overlapping of 2 QML files but not successful completely. count3 = 1 is defined in public section of Guiapplication.h file.
void GuiApplication::on_actionstart_triggered()
{
if (count3 == 1)
{
set_animation();
count3 = 2;
}
}
C++ Function for loading 1st QML file(main.qml)
void GuiApplication::rolling_animation()
{
QQuickView *quickWidget=new QQuickView();
QWidget *contain = QWidget::createWindowContainer(quickWidget,this);
contain->setMinimumSize(1008,349);
contain->setMaximumSize(1008,349);
contain->setFocusPolicy(Qt::TabFocus);
quickWidget->setSource(QUrl("qrc:/Resources/main.qml"));
ui->horizontalLayout_6->addWidget(contain);
}
C++ Function for loading 2nd QML file(main1.qml)
void GuiApplication::set_animation()
{
QQuickView *quickWidget=new QQuickView();
QWidget *Contain = QWidget::createWindowContainer(quickWidget,this);
Contain->setMinimumSize(1008,349);
Contain->setMaximumSize(1008,349);
Contain->setFocusPolicy(Qt::TabFocus);
quickWidget->setSource(QUrl("qrc:/Resources/main1.qml"));
ui->horizontalLayout_6->addWidget(Contain);
//ui->horizontalLayout_9->invalidate();
//ui->horizontalLayout_9->removeWidget(quickWidget_4);
}
output window image
Depending on whether you want to save or not the state of the QML that you want to hide there are the following alternatives:
Reject the same QQuickWidget (I recommend changing QQuickView to QQuickWidget) and just change the source.
#include <QtQuickWidgets>
class Widget: public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent=nullptr):
QWidget(parent),
m_widget(new QQuickWidget)
{
m_widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
QPushButton *button1 = new QPushButton("show 1");
QPushButton *button2 = new QPushButton("show 2");
QHBoxLayout *lay = new QHBoxLayout(this);
QVBoxLayout *vlay = new QVBoxLayout;
vlay->addWidget(button1);
vlay->addWidget(button2);
lay->addLayout(vlay);
lay->addWidget(m_widget);
connect(button1, &QPushButton::clicked, this, &Widget::show1);
connect(button2, &QPushButton::clicked, this, &Widget::show2);
show1();
}
private slots:
void show1(){
m_widget->setSource(QUrl("qrc:/main1.qml"));
}
void show2(){
m_widget->setSource(QUrl("qrc:/main2.qml"));
}
private:
QQuickWidget *m_widget;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
Use 2 QuickWidgets and use a QStackedWidget to toggle the widgets, with this method only hidden so the state of the QML will persist, in the previous case when changing the source is lost.
#include <QtQuickWidgets>
class Widget: public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent=nullptr):
QWidget(parent),
m_stacked_widget(new QStackedWidget)
{
for(const QString & url: {"qrc:/main1.qml", "qrc:/main2.qml"}){
QQuickWidget *widget = new QQuickWidget;
widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
widget->setSource(QUrl(url));
m_stacked_widget->addWidget(widget);
}
QPushButton *button1 = new QPushButton("show 1");
QPushButton *button2 = new QPushButton("show 2");
QHBoxLayout *lay = new QHBoxLayout(this);
QVBoxLayout *vlay = new QVBoxLayout;
vlay->addWidget(button1);
vlay->addWidget(button2);
lay->addLayout(vlay);
lay->addWidget(m_stacked_widget);
connect(button1, &QPushButton::clicked, this, &Widget::show1);
connect(button2, &QPushButton::clicked, this, &Widget::show2);
show1();
}
private slots:
void show1(){
m_stacked_widget->setCurrentIndex(0);
}
void show2(){
m_stacked_widget->setCurrentIndex(1);
}
private:
QStackedWidget *m_stacked_widget;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
The examples can be found here
There is following code. It creates QGraphicsView object, sets a scene and then there is created a QGraphicsWebView object which is added to the scene:
QGraphicsWebView* graphicsWebView;
QGraphicsScene* graphicsScene;
QGraphicsView* graphicsView;
QMainWindow* mainWindow;
class Deleter : public QObject
{
Q_OBJECT
public slots:
void deleteWebView()
{
mainWindow->hide();
mainWindow->centralWidget()->setParent(0);
mainWindow->setCentralWidget(new QWidget());
delete graphicsView; // <-- crashes about 2 seconds after that
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
mainWindow = new QMainWindow;
graphicsView = new QGraphicsView;
graphicsScene = new QGraphicsScene(graphicsView);
graphicsView->setScene(graphicsScene);
graphicsWebView = new QGraphicsWebView;
graphicsWebView->setUrl(QUrl("http://www.google.com"));
graphicsView->scene()->addItem(graphicsWebView);
graphicsView->setViewport(new QGLWidget());
graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
mainWindow->setAttribute(Qt::WA_TranslucentBackground);
mainWindow->setCentralWidget(graphicsView);
mainWindow->show();
Deleter d;
QTimer::singleShot(10000, &d, SLOT(deleteWebView()));
return app.exec();
}
#include "main.moc"
10 seconds later there is invoked a slot which tries to delete QGraphicsView object. The problem is that when I try to delete graphicsView, the program crashes after about 2 seconds. The backtraces are garbage. Theoretically QGraphicsView object should remove its children and the child is QGraphicsScene object. The scene should remove its child which is QGraphicsWebView object.
How to correctly delete QGraphicsView object without crashing the process?
This is Qt 4.8
I don't understand why it doesn't clean up properly, but I would not make graphicsView a parent of your scene. Instead of giving the scene a parent, just delete it in your deleteWebView slot after the view.
I can't reproduce. The following works consistently and without crashes on Qt 4.8.7 on OS X:
#include <QtGui>
#include <QGraphicsWebView>
#include <QGLWidget>
class Window : public QMainWindow {
Q_OBJECT
QWidget central;
QVBoxLayout layout{¢ral};
QPointer<QGraphicsView> view;
QPushButton button{"Toggle View"};
Q_SLOT void toggle() {
if (!view) {
view = new QGraphicsView;
auto scene = new QGraphicsScene(view);
auto webView = new QGraphicsWebView;
webView->setUrl(QUrl("http://www.google.com"));
scene->addItem(webView);
view->setScene(scene);
view->setViewport(new QGLWidget);
view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
layout.addWidget(view);
} else {
delete view;
view = nullptr;
}
}
public:
Window() {
layout.addWidget(&button);
layout.addStretch(1);
setAttribute(Qt::WA_TranslucentBackground);
setCentralWidget(¢ral);
connect(&button, SIGNAL(clicked(bool)), SLOT(toggle()));
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Window w;
w.show();
return app.exec();
}
#include "main.moc"
I try to create a window in another window with Qt and delete the first window. When the second window is opened the first window is deleted but when I try to delete the second window I get this error:
HEAP[Flash-TestBench-Client-Rev1-0.exe]:
Heap block at 18FBC298 modified at 18FBC2C4 past requested size of 24
Here is my simplified code:
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ConnectionWindow *w = new ConnectionWindow;
return a.exec();
}
connectionwindow.cpp
ConnectionWindow::ConnectionWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *w = new QWidget;
QVBoxLayout *l = new QVBoxLayout;
QPushButton *button = new QPushButton;
button->setText("Connect");
conenect(button, SINGNAL(pressed()), this, (openW()));
l->addWidget(button);
w->setLayout(l);
this->setCentralWidget(w);
this->setAttribute(Qt::WA_DeleteOnClose);
this->show;
}
void ConnectionWindow::openW(){
MainWindow *window = new MainWindow;
this->close;
}
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *w = new QWidget;
QVBoxLayout *l = new QVBoxLayout;
QPushButton *button = new QPushButton;
button->setText("Close");
conenect(button, SINGNAL(pressed()), this, (closeW));
l->addWidget(button);
w->setLayout(l);
this->setCentralWidget(w);
this->setAttribute(Qt::WA_DeleteOnClose);
this->show;
}
void MainWindow::closeW(){
this->close();
}