Shortly: when I dragging the mouse over the QPushButton in MS Windows7 (64bit) my app eats some memory.
But if I close the widget where the buttons are then memory will be returned.
I'm using qt5 beta 2 and VC++ with crtdbg.h.
Here is my test app (Launch, open widget2 and drag mouse over the buttons on it. At the same time see task manager.)
//-- widget1.h
class Widget1 : public QWidget
{
Q_OBJECT
private:
void callWidget2();
public:
Widget1(QWidget* parent = 0);
~Widget1() {}
};
//-- widget1.cpp
Widget1::Widget1(QWidget* parent)
:QWidget(parent)
{
QPushButton* btn = new QPushButton(this);
btn->setText("show widget2");
connect(btn, &QPushButton::clicked, this, &Widget1::callWidget2);
this->resize(100, 100);
this->show();
}
void Widget1::callWidget2()
{
new Widget2();
}
//-- widget2.h
class Widget2 : public QWidget
{
Q_OBJECT
private:
public:
Widget2(QWidget* parent = 0);
~Widget2() {}
};
//-- widget2.cpp
Widget2::Widget2(QWidget* parent)
:QWidget(parent)
{
this->setAttribute(Qt::WA_DeleteOnClose);
this->resize(300, 300);
QPushButton* button = new QPushButton(this);
button->setText("btn1");
button = new QPushButton(this);
button->setText("btn2");
button->move(0, 20);
button = new QPushButton(this);
button->setText("btn3");
button->move(0, 40);
button = new QPushButton(this);
button->setText("btn4");
button->move(0, 60);
button = new QPushButton(this);
button->setText("btn5");
button->move(0, 80);
this->show();
}
//-- main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
new Widget1;
return a.exec();
}
This is the result of 5 minutes dragging.
I can't repeat this on windows XP 32bit.
What is this?
Related
I have a widget with this structure:
main->QMainWindow->QFrame->QGraphicsView->QScene->QGraphicsPixMapItem->QPixmap
I had to do it this way because im not using Qt creator or QML, just widgets. Anyway I added an event filter to my QMainindow to be movable when clicking and dragging whenever side of the window And it worked. But due to the QGraphicsView implementation if I try to drag it doesnt work but still receives input (a menu opens when i click). What makes QGraphicsview so stubborn and how do i make the window to be draggable when i click and drag on the QGraphics view, Even installing the eventFilter on the view and frame but with no results. Thanks in advance and this is my code.
This is the problem, the red square is the QGrapicsView, the white one is the MainWindow/Qframe. See how i still can make right clic on the red one and the menu still appears. I made a debug and see i get 2 objs when i click, the mainwindow and the Qgraphicview so i dont know why the move functionality just doesn work.
enter image description here
Main.cpp
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return QApplication::exec();
}
MainWindow.h
protected:
bool eventFilter(QObject *obj, QEvent *event) override{
if (event->type() == QEvent::MouseButtonPress ) {
qDebug() << event;
auto *ev = (QMouseEvent *) event;
if (ev->button() == Qt::RightButton) {
//Opens menu, it works well when i click on the QGraphics as well
auto *menu = new QMenu(this);
auto *idle = new QAction("Idle", this);
auto *close = new QAction("Quit", this);
menu->addAction(idle);
menu->popup(ev->globalPos());
connect(close, &QAction::triggered, [](){QCoreApplication::quit();});
connect(idle, &QAction::triggered, [this](){changeDance(0);});
}
else{
// "grab" the mainWindow
this->oldPos = ev->globalPos();
}
}
if (event->type() == QEvent::MouseMove) {
//drag the window
auto *ev = (QMouseEvent *) event;
const QPoint delta = ev->globalPos() - oldPos;
move(x() + delta.x(), y() + delta.y());
oldPos = ev->globalPos();
}
}
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent) {
setWindowTitle("waifu"); //waifu
setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
setFixedSize(screenWidth, screenHeight);
//setAttribute(Qt::WA_TranslucentBackground, true);
setWindowFlags(Qt::Widget | Qt::FramelessWindowHint);
setWindowFlags(Qt::BypassGraphicsProxyWidget);
//mainWindow->frame->view->scene->pixmap
installEventFilter(this);
frame = new Frame(this);
setCentralWidget(frame);
view = new View(frame);
view->setFixedSize(50, 50);
scene = new Scene(view);
view->setScene(this->scene); // That connects the view with the scene
frame->layout()->addWidget(view);
myItem = new QGraphicsPixmapItem(*new QPixmap());
//scene->setBackgroundBrush(QBrush(Qt::yellow));
scene->addItem(myItem);
view->show();
Frame.h
class Frame : public QFrame {
Q_OBJECT
public:
explicit Frame(QMainWindow *parent = 0) : QFrame(parent) {
setMouseTracking(true);
setStyleSheet("background-color: red;"); //delete
setLayout(new QVBoxLayout);
layout()->setContentsMargins(0, 0, 0, 0);
setWindowFlags(Qt::FramelessWindowHint); //No windowing
setAttribute(Qt::WA_TranslucentBackground); // No background
setStyleSheet("background-color: transparent;");
};
};
QGraphicsView.h
class View : public QGraphicsView {
Q_OBJECT
public:
explicit View(QFrame *parent) : QGraphicsView(parent) {
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setMouseTracking(true);
};
protected:
private:
};
Tried to install the event filter located in the main window, in the Qframe and QGraphicsView class. with the parameter event filter being *parent.
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
I am trying to show a QMainWindow inside a QDialog but the former does not appear.
I have subclassed QDialog, let's call it myDialog
A small example:
myDialog(QWidget *p_parent) : QDialog(p_parent)
{
QGridLayout *p_dialogLayout = new QGridLayout(this);
QMainWindow *p_MainWindow = new QMainWindow(this);
QLabel *p_label = new QLabel(this);
p_MainWindow->setCentralWidget(p_label);
QPushButton *p_cancel = new QPushButton("Cancel", this);
p_dialogLayout ->addWidget(p_MainWindow, 0, 0);
p_dialogLayout ->addWidget(p_cancel, 1, 0);
}
If I execute the dialog, I only see the button, not the embeded QMainWindow.
If i force to show the qmainwindow, the mainwindow is shown in another window.
Use QLayout::setMenuBar to add a toolbar to your dialog.
#include <QtWidgets>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr) : QDialog(parent)
{
resize(600, 400);
setLayout(new QHBoxLayout);
QToolBar *toolbar = new QToolBar;
toolbar->addAction("Action one");
toolbar->addAction("Action two");
layout()->setMenuBar(toolbar);
layout()->addWidget(new QLabel("Label one"));
layout()->addWidget(new QLabel("Label two"));
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}
#include "main.moc"
I don't think this is supported by the Qt framework, according to their documentation from here, it's intended to be used only once in an application.
My suggestion would be to take all your MainWindow implementation in a separate form (inheriting QWidget), and just add that form to your MainWindow in the constructor using something like p_MainWindow->setCentralWidget(p_YourNewForm);
I have been able to do it.
The trick is to construct the QMainWindow without a parent, and then apply the .setParent
Here is how:
myDialog(QWidget *p_parent) : QDialog(p_parent)
{
QGridLayout *p_dialogLayout = new QGridLayout(this);
QMainWindow *p_MainWindow = new QMainWindow(); //Without a parent
QLabel *p_label = new QLabel(this);
p_MainWindow->setCentralWidget(p_label);
QPushButton *p_cancel = new QPushButton("Cancel", this);
p_dialogLayout ->addWidget(p_MainWindow, 0, 0);
p_dialogLayout ->addWidget(p_cancel, 1, 0);
p_MainWindow->setParent(this); //Set the parent, to delete the MainWindow when the dialog is deleted.
}
I'm building a simple application, the main window have to shows two widgets (QTreeView on the right, QTabWidget on the left), to perform this i use a QHBoxLayout.
This is the code i've written(constructor of MainWindow):
MainWindow::MainWindow()
{
mainLayout = new QHBoxLayout(this);
tabber = new QTabWidget(this);
analysisTreeView = new QTreeView(this);
tabber->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
mainLayout->addWidget(tabber, 0);
mainLayout->addWidget(analysisTreeView, 0);
createActions();
createMenus();
createToolBars();
connect(tabber, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
setLayout(mainLayout);
}
But when i run the application the main window shows no widgets. Why?
On request, i add some code:
Once a button in the mainwindows's toolbar is clicked a new tab is added to tabber:
void MainWindow::newSheet()
{
GraphicsScene *newScene = new GraphicsScene(itemMenu,this);
QGraphicsView *newView = new QGraphicsView(this);
newScene->setSceneRect(-200, -200, 400, 400);
newView->scale(1.5,1.5);
newView->setCacheMode(QGraphicsView::CacheBackground);
newView->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
newView->setRenderHint(QPainter::Antialiasing);
newView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
newView->setScene(newScene);
sheetList.append(newView);
tabber->addTab(newView,"PNC");
connect(newScene, SIGNAL(itemInserted(PItem*)), this, SLOT(itemInserted(PItem*)));
connect(newScene, SIGNAL(requestUpdateGUI(GraphicsScene*)), this, SLOT(updateGUI(GraphicsScene*)));
}
My main.cpp:
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(application);
QApplication a(argc, argv);
MainWindow window;
window.showMaximized();
return a.exec();
}
I suppose your class specializes QMainWindow. If so, it needs a centralWidget to be set:
MainWindow::MainWindow()
{
// added by jpo38
QWidget* mainWidget = new QWidget( this );
setCentralWidget( mainWidget );
// end added by jpo38
mainLayout = new QHBoxLayout(mainWidget);
tabber = new QTabWidget(mainWidget);
analysisTreeView = new QTreeView(mainWidget);
tabber->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
mainLayout->addWidget(tabber, 0);
mainLayout->addWidget(analysisTreeView, 0);
createActions();
createMenus();
createToolBars();
connect(tabber, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
setLayout(mainLayout);
}
Greetings all,
Is there any widget to separate two QWidgets and also give full focus to a one widget.
As shown in following figure ?
Thanks in advance,
umanga
How about QSplitter?
QWidget 1, for exmaple, QListView. QWidget 2 is a combination of QWidgets (the left part is simple QPushButton with show/hide caption, and the right part another widget)... All you have to do, is to hide your QWidget2 when user clicked on QPushButton...
If you need an example, I may post it.
Updated
main.cpp
#include "splitter.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
splitter w;
w.show();
return a.exec();
}
splitter.h
#ifndef SPLITTER_H
#define SPLITTER_H
#include <QtGui/QDialog>
class splitter : public QDialog
{
Q_OBJECT;
QWidget* widget1;
QWidget* widget2;
QPushButton* button;
public:
splitter(QWidget *parent = 0, Qt::WFlags flags = 0);
~splitter();
private slots:
void showHide(void);
};
#endif // SPLITTER_H
splitter.cpp
#include <QtGui>
#include "splitter.h"
splitter::splitter(QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags)
{
QApplication::setStyle("plastique");
QListView* listView = new QListView;
QTableView* tableView = new QTableView;
button = new QPushButton("Hide >");
widget1 = new QWidget;
QHBoxLayout* w1Layout = new QHBoxLayout;
w1Layout->addWidget(listView);
w1Layout->addWidget(button);
widget1->setLayout(w1Layout);
widget2 = new QWidget;
QHBoxLayout* w2Layout = new QHBoxLayout;
w2Layout->addWidget(tableView);
widget2->setLayout(w2Layout);
QSplitter *mainSplitter = new QSplitter(this);
mainSplitter->addWidget(widget1);
mainSplitter->addWidget(widget2);
connect(button, SIGNAL(clicked()), this, SLOT(showHide()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(mainSplitter);
setLayout(mainLayout);
}
splitter::~splitter()
{}
void splitter::showHide(void)
{
if (widget2->isVisible())
{ // hide
widget2->setVisible(false);
button->setText("< Show");
}
else
{ // show
widget2->setVisible(true);
button->setText("Hide >");
}
}