QLabel show command opens new Window - c++

I've created an Application which derives from QWidget. When I create an QLabel and yield the show command, it opens in a separate window. I was deriving my BaseClass from QMainWindow before which worked fine.
#include "widget.h"
#include "ui_widget.h"
#include <iostream>
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testlabel = new my_qlabel(parent);
QImage myImage = QImage(QString::fromStdString("D:/Lighthouse.jpg"));
testlabel->setParent(parent);
testlabel->name="testName";
testlabel->setPixmap(QPixmap::fromImage(myImage, Qt::AutoColor));
testlabel->setGeometry(QRect(500, 500, 100, 100));
testlabel->show();
std::cout<<"i am in the output "<<std::endl;
qDebug() << QString("init");
}
Widget::~Widget()
{
delete ui;
}

testlabel = new my_qlabel(parent);
The above should probably instead be
testlabel = new my_qlabel(this);
Also make sure that your my_qlabel constructor is passing its QWidget pointer argument up to the superclass's (QLabel?) constructor. If you forgot to do that, then the my_qlabel object will not have a parent widget, which will cause it to show up as top-level window, which would match the behavior you are seeing.
testlabel->show();
Once you have testlabel's parenting problems fixed, this show() command should no longer be necessary (or appropriate), since any child widgets you add to your Widget object will be automatically show()'n when the Widget itself is first show()'n. (The only time you would need to manually call show() is if you had previously called hide() or setVisible(false) on that same widget, and now you wanted to make it re-appear; or if you had added the child widget to its parent widget after the parent widget was already visible on-screen; neither is the case here)

Related

Qt - QLineEdit doesn't update the page and URL

I've got a small problem with my web browser project. Whenever I enter the URL address (via QLineEdit), the browser doesn't show the page, and whenever I change the page (via click on-site with starting page included) the address doesn't show up on the URL bar.
Here's my mainwindow.cpp code. The program executes and exits with code 0. I tried using qDebug inside the functions (changeUrlBar(QUrl) and setUrl()) and it turns out that the program enters these functions but they don't do anything. Every advice would be very appreciated.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
browserView(new QWebEngineView),
urlBar(new QLineEdit)
{
ui->setupUi(this);
//
// initialization of widgets and layouts
// widgets
QWidget *browserWindow = new QWidget(this);
QLineEdit *urlBar = new QLineEdit;
QProgressBar *progressBar = new QProgressBar;
// WebEngineView - actual web browser
QWebEngineView *browserView = new QWebEngineView(parent);
// layouts
QVBoxLayout *mainLayout = new QVBoxLayout;
QHBoxLayout *topBarLayout = new QHBoxLayout;
// push buttons
QPushButton *buttonBack = new QPushButton("Back");
QPushButton *buttonForward = new QPushButton("Forward");
QPushButton *buttonReload = new QPushButton("Reload");
//
// creating the widgets and layouts
// top bar
topBarLayout->addWidget(buttonBack);
topBarLayout->addWidget(buttonForward);
topBarLayout->addWidget(buttonReload);
topBarLayout->addWidget(urlBar);
// main layout of the browser
mainLayout->addLayout(topBarLayout);
mainLayout->addWidget(progressBar);
mainLayout->addWidget(browserView);
browserWindow->setLayout(mainLayout);
setCentralWidget(browserWindow);
//
// connecting slots and signals
// internal connections
connect(buttonBack, SIGNAL(clicked()), browserView, SLOT(back()));
connect(buttonForward, SIGNAL(clicked()), browserView, SLOT(forward()));
connect(buttonReload, SIGNAL(clicked()), browserView, SLOT(reload()));
connect(browserView, SIGNAL(loadProgress(int)), progressBar, SLOT(setValue(int)));
// browser connections
connect(browserView, SIGNAL(urlChanged(QUrl)), this, SLOT(changeUrlBar(QUrl)));
connect(urlBar, SIGNAL(editingFinished()), this, SLOT(setUrl()));
// set starting page
browserView->load(QUrl("https://www.wikipedia.org"));
}
void MainWindow::setUrl()
{
browserView->load(QUrl::fromUserInput(urlBar->text()));
}
void MainWindow::changeUrlBar(QUrl)
{
urlBar->setText(browserView->url().toString());
}
MainWindow::~MainWindow()
{
delete ui;
delete browserView;
delete urlBar;
}
Your actual problem is that you've defined two local variables (urlBar and browserView) that are hiding the declaration of MainWindow::urlBar and MainWindow::browserView.
Those local objects are the ones added to the user interface, but in the slots you are using the member objects (those that were not included in the UI). Even when they are initialized in the constructor, they are not neither receiving user input nor being displayed on the user interface.
MainWindow::MainWindow(QWidget *parent) :
// ...
QLineEdit *urlBar = new QLineEdit; // <-- local variable hiding member declaration
QProgressBar *progressBar = new QProgressBar;
// WebEngineView - actual web browser
QWebEngineView *browserView = new QWebEngineView(parent); // <-- local variable hiding member declaration
// ...
void MainWindow::changeUrlBar(QUrl)
{
urlBar->setText(browserView->url().toString()); // <-- urlBar and browserView are members
}
Moral: avoid hiding or be conscious about it ;). Some tricks used to reduce this are to always access member through this (this->urlBar), or using a different notation for members (like m_urlBar or urlBar_). Also, many compilers should warn about this.
I feel like an idiot now because I managed to solve this issue and the only thing to do was to delete following lines:
QLineEdit *urlBar = new QLineEdit;
QWebEngineView *browserView = new QWebEngineView(parent);
As these objects were already initialised.

Update MainWindow for dialog

I have a MainWindow with a menu that opens a dialog for registration. How can I update the tableView in the MainWindow after the registration?
Here is my MainWindow implementation:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){
ui->setupUi(this);
}
void MainWindow::list()
{
qDebug() << "test";
QSqlQueryModel *model = new QSqlQueryModel();
//model->clear();
model->setQuery("SELECT test_qt FROM db_qt WHERE strftime('%Y-%m-%d', date)='"+dateTime.toString("yyyy-MM-dd")+"'");
model->setHeaderData(0, Qt::Horizontal, tr("qt_test"));
ui->tableView->setModel(model);
}
void MainWindow::on_actionMenu_triggered()
{
dialog_test->show();
}
Here is my Dialog implementation
Dialog_test::Dialog_test(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog_test)
{
ui->setupUi(this);
}
void Dialog_test::insert_date(){
QSqlQuery qry;
qry.prepare("INSERT INTO db_qt(test_qt) VALUES (?)");
qry.addBindValue(id);
if (qry.lastInsertId()>0){
QMessageBox::information(this,"test", "Success");
MainWindow *mw = new MainWindow(this);
mw->list(); // I call back list, but not update the tableView the MainWindow.
}
}
The following line in your code
MainWindow *mw = new MainWindow(this);
creates a new main window and updates the list of it. I assume this actually happens, but the window is never shown so you do not see any of it. What you actually want to do is update the list of your existing main window.
There are basically two ways of doing that. You can either obtain a pointer to the existing main window (which can be provided to the constructor of the dialog or a method of its own) or use the Signals and Slots concept of Qt which is the way to go in my opinion.
First of all, you define the signal in the header of the dialog:
...
signals:
void user_registered();
...
Then you emit the signal in your function
//MainWindow *mw = new MainWindow(this);
//mw->list();
emit this->user_registered();
Make sure the list() method is declared as a SLOT in the MainWindow header
Connect the signal in the MainWindow constructor to call the list() slot:
...
QObject::connect(this->dialog_test, SIGNAL(user_registered()), this, SLOT(list()));
...
With this approach, the dialog does not need to know the main window at all. It basically just tells anyone who is interested that a user registered and the main window acts on it completly by itself.

Qt creating MDI document window

I am trying to create a MDI document program. I have a question on creating the subwindow.
This is my mainwindow constructor:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle(tr("MDI"));
workspace = new QMdiArea;
setCentralWidget(workspace);
//fileNew();
createActions();
createMenus();
createToolbars();
statusBar()->showMessage(tr("Done"));
enableActions();
}
The interesting point is the fileNew(); function. It is a private slot function actually which I want to invoke when "New File" button is triggered. Here is the private slot fileNew() function:
void MainWindow::fileNew()
{
DocumentWindows* document = new DocumentWindows;
workspace->addSubWindow(document);
}
This function works perfectly when I call from the mainwindow constructor. However, there is a problem when I call it from the createActions(); function which uses a signal-slot mechanism.
Here is my createActions()
void MainWindow::createActions()
{
newAction = new QAction(QIcon(":/Image/NewFile.png"),tr("&New"),this);
newAction->setShortcut(tr("Ctrl+N"));
newAction->setToolTip(tr("Open new document"));
connect(newAction, SIGNAL(triggered(bool)), this, SLOT(fileNew()));
}
No subwindow is created even the SLOT is triggered. Subsequently, I find out that if I add document->show();, everything works well.
void MainWindow::fileNew()
{
DocumentWindows* document = new DocumentWindows;
workspace->addSubWindow(document);
document->show();
}
My question is: Why the show() function is needed in a SLOT but not in the constructor?
PS. DocumentWindows is just a class inherits QTextEdit.
This problem has nothing to do with the class of the widgets one is using. It is unrelated to documents, MDI, or the main window. After you add a child widget to a widget that is already visible, you must explicitly show it. Otherwise, the widget will remain hidden.
All widgets are hidden by default. When you initially show the MainWindow, all of its children are recursively shown too. When you later add a child MDI widget, it remains hidden. When widgets are added to layouts, they are shown by default - but your widget is managed by the MDI area, not by a layout.
This is a minimal test case demonstrating your issue:
// https://github.com/KubaO/stackoverflown/tree/master/questions/widget-show-32534931
#include <QtWidgets>
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QWidget w;
w.setMinimumSize(200, 50);
QLabel visible{"Visible", &w};
w.show();
QLabel invisible{"Invisible", &w};
invisible.move(100, 0);
return app.exec();
}

Can't open Widget from the MainWindow

I want to open a Widget from my MainWindow. I thought this was easy to do, and all the tutorials I read do it like this:
void MainWindow::on_pushButton_Types_clicked()
{
m_typesWin = new TypesWindow(m_db, this);
m_typesWin->show();
this->hide();
}
However, this only works for me if I don't pass "this" into the constructor. When I add "this" to the constructor, I don't see the widget, the program just stops. If I don't hide "this", then I can see that parts of my widget are actually in my main window. I have no idea why.
EDIT: The classes are automatically created by QtCreator, so they should be alright.
If you want a QWidget to be displayed as a window, a parent widget should not be specified to that widget. Here, because you specify main window as the parent of TypesWindow, TypesWindow becomes embedded in main window. So when you hide main window, TypesWindow embedded in main window also gets hidden.
Since you want TypesWindow to be a separate window, don't pass parent widget to the QWidget constructor in TypesWindow constructor. If you want to access main window from TypesWindow, you can store main window pointer in a pointer field in TypesWindow.
To open a Mainwindows from the new Qwidget:
1)in the NEWWIDGET.CPP:
QWidget *w;
NEWWIDGET::NEWWIDGET(QWidget *parent,QWidget *win) :
QWidget(parent),
ui(new Ui::NEWWIDGET)
{
ui->setupUi(this);
w=win;
}
..
void NEWWIDGET::on_pushButton_clicked()
{
this->hide();
w->show();
}
2)In the NEWWIDGET.H
public:
explicit NEWWIDGET(QWidget *parent=nullptr,QWidget *win=nullptr);
~NEWWIDGET();

qt example from the book

I have this snippet of the code:
#include <QApplication>
#include <QFont>
#include <QPushButton>
#include <QWidget>
class MyWidget : public QWidget
{
public:
MyWidget(QWidget *parent = 0);
};
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
setFixedSize(200, 120);
QPushButton *quit = new QPushButton(tr("Quit"), this);
quit->setGeometry(62, 40, 75, 30);
quit->setFont(QFont("Times", 18, QFont::Bold));
connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
can somebody please explain what exactly is going on in this line
MyWidget(QWidget *parent = 0);
a little bit difficult understand what is this parent, thanks in advance
That is an argument to the constructor with a default argument (NULL since NULL is defined as 0 as per the c++ standard). Default meaning passing no parameter is the same as passing NULL.
Since Qt's widgets are arranged in a hierarchal system (parent -> child relationships) parent is the widget which is the "owner" or "container" of the current one (NULL means no parent aka a root widget of sorts). For GUI items a widget will often have the widget it is contained in as its parent.
This is advantageous since when a parent is deleted, it will delete any children is has automatically removing the need for much of the memory management that comes with c++.
The parent argument is for giving parents to new widgets. When given, it is useful for Qt to manage the object tree. (To automatically delete child objects.) It also has the concrete visible effect of "attaching" a new widget to another widget (ie, the parent). In your code however, the parent argument is not ever given, causing the widget to appear as a top level window and not to be deleted by Qt automatically. (It would not require deletion by Qt anyway in that code though.)
Its a 0 pointer (think NULL without the type), or in Qt terms, "no parent".