QPushButton not clickable in MainWindow - c++

I'm writing a QT project in Xcode, I made a Widget application in the QT Editor and used the "qmake -spec macx-xcode" to convert the project into an Xcode project.
I have a standard project:
main.cpp
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
main window.cpp
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
m_button = new QPushButton(this);
m_button -> setText("button");
m_button->setGeometry(QRect(QPoint(100, 100),QSize(200, 50)));
QPushButton *workingButton = new QPushButton("Hello");
workingButton -> show();
connect(m_button, SIGNAL(clicked()), this, SLOT(quitButton()));
ui->setupUi(this);
}
void MainWindow::quitButton() {
m_button->setText("Example");
}
MainWindow::~MainWindow()
{
delete ui;
}
main window.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void quitButton();
private:
Ui::MainWindow *ui;
QPushButton *m_button;
};
#endif
The m_button shows up in the mainWindow but it is not clickable but the workingButton, shows up in its own separate window, and in the connect, when I replace the m_button with the workingButton, it is able to call the function. Any idea why the m_button is not sending a signal or function not being called?

The reason is quite simple: you have other transparent widgets overlaid on top of m_button. You must ensure that the button is not covered by anything else. E.g. move the creation of the button after the setupUi call or make the button a child of the central widget. Generally speaking, the setupUi call should be the first thing in a widget's constructor.
You also don't need to dynamically allocate the child widgets: prefer holding things by value: less things can go wrong then, and you're having less overhead, too!
Thus, pretending that the Ui_MainWindow class was really generated by uic:
// https://github.com/KubaO/stackoverflown/tree/master/questions/simple-button-main-41729401
#include <QtWidgets>
class Ui_MainWindow {
public:
QWidget *central;
QGridLayout *layout;
QLabel *label;
void setupUi(QMainWindow *parent);
};
class MainWindow : public QMainWindow, private Ui_MainWindow {
Q_OBJECT
QPushButton m_button{"Click Me"};
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
setupUi(this);
m_button.setParent(centralWidget());
m_button.setGeometry({{50, 50}, m_button.sizeHint()});
}
};
void Ui_MainWindow::setupUi(QMainWindow *parent) {
central = new QWidget{parent};
layout = new QGridLayout{central};
label = new QLabel{"Hello"};
label->setAlignment(Qt::AlignCenter);
label->setStyleSheet("background-color:blue; color:white;");
layout->addWidget(label, 0, 0);
parent->setCentralWidget(central);
parent->setMinimumSize(200, 200);
}
int main(int argc, char ** argv) {
QApplication app{argc, argv};
MainWindow w;
w.show();
return app.exec();
}
#include "main.moc"

Related

Widget initialized later will not show in MainWindow

I am learning Qt using Qt 5.13 on MacOS.
First I define MyWidget inherited from QWidget. MyWidget has a QPushButton, but this button will be created in a slot function called 'fresh', not in constructor.
I add MyWidget in MainWindow (inherited from QMainWindow), and defined another button_2 to emit signal to callMyWidget's 'fresh' function to create button.
If I did not hide MyWidget in MainWindow first, MyWidget's button will not show. If I hide MyWidget first, everything seems OK.
I hope to know the reason. Thanks
I tried to repaint or update MyWidget in 'fresh' function, but did not help.
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include<QPushButton>
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = nullptr);
~MyWidget();
public slots:
void fresh();
private:
QPushButton* myButton;
};
#endif // WIDGET_H
mywidget.cpp
#include "mywidget.h"
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent)
{
}
MyWidget::~MyWidget()
{
}
void MyWidget::fresh()
{
myButton = new QPushButton(this);
myButton->setStyleSheet("QPushButton { background-color: green;}");
show();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include"mywidget.h"
#include<QHBoxLayout>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
signals:
public slots:
private:
MyWidget* myWidget;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
QWidget* qwidget = new QWidget;
myWidget = new MyWidget(this);
QPushButton* button = new QPushButton("Show",this);
QHBoxLayout* mainLayout = new QHBoxLayout;
mainLayout->addWidget(myWidget);
mainLayout->addWidget(button);
qwidget->setLayout(mainLayout);
setCentralWidget(qwidget);
//myWidget->hide();
connect(button,&QPushButton::clicked,myWidget,&MyWidget::fresh);
}
main.cpp
#include "mywidget.h"
#include"mainwindow.h"
#include<QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
If I add myWidget->hide(); in mainwindow.cpp, it seems right.
If I remove it, the green button will not show, even if I repaint or update or show in fresh function.
'mywidget' is taking the whole space, if you want to know if it is taking all the space or not :
mywidget->setStyleSheet("* {border: 4px solid orange;}")
Since you are using a layout, you might want to determine the minimum size of a QPushButton. the QPushButton has a default horizontal size policy : "Minimum", by default. Maybe if you set the minimum width using this function : "setMinimumWidth(int width)", might fix your problem.
Also, don't forget to call this :
myButton->show();
Every object that inherits from QObject should be shown with this func ".show".
Here is all the flags for QSizePolicy will help you understand what is going on in layouts (layouts work a lot with QSizePlicy flags) : https://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum .
Unless you don't want the layout, you have to specify the position and the size in this way :
mywidget->setGeometry(QPoint(x, y), QSize(width, height));
and the same thing for your buttons.

hiding the main Window after opening the secondWindow?Also, when the secondWindow is closed by the user, how can the main window reappear?

Basically, when second window is opened from a push button in the main window, the main window will be closed. When the second window is closed, the main window will reappear.
QWidget *wdg = new QWidget;
wdg->show();
hide();
I put this under the class of mainwindow.cpp
I tried using this..but it doesn't seem to do anything?
this are the code I have so far. Everything is working but I just don't know how to hide the window when the second window is opened and also when the second window is closed the main window will reappear.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
public:
void show();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
secwindow.h
#ifndef SECWINDOW_H
#define SECWINDOW_H
#include <QDialog>
namespace Ui {
class SecWindow;
}
class SecWindow : public QDialog
{
Q_OBJECT
public:
explicit SecWindow(QWidget *parent = nullptr);
~SecWindow();
private:
Ui::SecWindow *ui;
};
#endif // SECWINDOW_H
source code
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QPixmap>
#include "secwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPixmap pix("C:/Users/Charlene/Downloads/Charlene Back-up/MAPUA/2nd Term/Object Oriented Programming/GOW-Gui/GOW-GUI/intro pic/intro.png");
ui->label->setPixmap(pix.scaled(230,250,Qt::KeepAspectRatio));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked() // Modal approach..mainwindow cannot be moved when secwindow is displayed.
{
SecWindow secwindow;
secwindow.setModal(true); //it'll set the secwindow
secwindow.exec(); //shows secwindow when button is pressed
}
secwindow.cpp
#include "secwindow.h"
#include "ui_secwindow.h"
SecWindow::SecWindow(QWidget *parent) :
QDialog(parent),
ui(new Ui::SecWindow)
{
ui->setupUi(this);
}
SecWindow::~SecWindow()
{
delete ui;
}
EDIT:
#Serhiy Kulish
What I added so far:
secWindow.h
class Dialog : public QDialog
{
Dialog();
};
mainwindow.cpp
#include <QDialog>
void MainWindow::show()
{
Dialog *dialog = new Dialog(this); //Error:no matching constructor for initialization of 'Diaolog'
connect(dialog, SIGNAL(accepted()), this, SLOT(show()));
connect(dialog, SIGNAL(rejected()), this, SLOT(show()));
dialog->show();
hide();
}
These are the errors I'm having so far.
Add your own class derived from QDialog. Then connect signals accepted and rejected with MainWindow::show().
Dialog *dialog = new Dialog(this);
connect(dialog, SIGNAL(accepted()), this, SLOT(show()));
connect(dialog, SIGNAL(rejected()), this, SLOT(show()));
dialog->show();
hide();
It works fine on Windows 10.
Also, depends your OS you maybe need
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
in main.cpp to prevent app closing. But in this case you have to quit from your app manually

Accessing Outside of a class

I am trying to access a QgraphicsView's Scene outside of a class. I can normally do this when I create a class that is derived from QGraohicsView, but this class is the MainWindow which derives from QMainWIndow and I can have it extend QGraphicsView because there is a conflict when you call the .show() method as the compiler does not know which one to choose.
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{}
So I create a new instance of QgraphicsView and make it public and also Qgraphicsscene and make it public.
Then in the exterior class
extern MainWindow * mainwindow
But when I try to access it and I get a undefined reference error.
mainwindow->view->scene()->addItem(item); or
mainwindow->mainwindow.scene->addItem(item);
Neither of them work.
I know its breaking encapsulation but there is no other way around this in this particular case.
** What I am trying to do is access a QgraphicsView's Scene outside of its class?
** MainWindow has public variables
QGraphicsScene *scene;
QGraphicsView * view;
In MainWindow.cpp
scene = new QGraphicsScene(this);
view = new QGraphicsView(scene);
view.show();
This works for me. Since view in your case was a pointer, you must access its members via ->, not .. But all that is superfluous anyway - you should store everything by value as much as possible and let the compiler worry about making sure the resources are freed when no longer needed. That's why you're using C++, not C, after all.
// https://github.com/KubaO/stackoverflown/tree/master/questions/simple-view-33508582
#include <QtWidgets>
class MainWindow : public QMainWindow {
Q_OBJECT
QGraphicsScene m_scene;
QWidget m_central;
QGraphicsView m_view; // must be declared after m_central per C++ semantics
QGridLayout m_layout;
public:
MainWindow(QWidget * parent = 0) :
QMainWindow(parent),
m_layout(&m_central) {
setCentralWidget(&m_central);
m_layout.addWidget(&m_view, 0, 0);
m_view.setScene(&m_scene);
}
QGraphicsScene * scene() { return &m_scene; }
QGraphicsView * view() { return &m_view; }
};
int main(int argc, char ** argv) {
QApplication app(argc, argv);
MainWindow win;
win.scene()->addEllipse(0, 0, 10, 10);
win.show();
return app.exec();
}
#include "main.moc"
You should also decide whether you need a QMainWindow at all. Just because a Qt Creator template uses it, doesn't mean you should blindly use it too. If you're not using QMainWindow's docking area functionality, a QDialog would be a more sensible base class to use:
// https://github.com/KubaO/stackoverflown/tree/master/questions/simple-view-33508582
#include <QtWidgets>
class MainWindow : public QDialog {
Q_OBJECT
QGraphicsScene m_scene;
QGraphicsView m_view;
QGridLayout m_layout;
public:
MainWindow(QWidget * parent = 0) :
QDialog(parent),
m_layout(this) {
m_layout.addWidget(&m_view, 0, 0);
m_view.setScene(&m_scene);
}
QGraphicsScene * scene() { return &m_scene; }
QGraphicsView * view() { return &m_view; }
};
int main(int argc, char ** argv) {
QApplication app(argc, argv);
MainWindow win;
win.scene()->addEllipse(0, 0, 10, 10);
win.show();
return app.exec();
}
#include "main.moc"

C++ - Adding item to QListWidget from QPushButton

Hello I am trying to add items to a QListWidget from a QPushButton. Both the QListWidget and QPushButton are added as individual widgets inside of a QGraphicsScene. I want the effect of a box that fills with text lines
main.c
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
QGraphicsView view;
QGraphicsScene *scene = new QGraphicsScene(0, 0, 1200, 1200, &view);
scene->setBackgroundBrush(Qt::gray);
view.setScene(scene);
QPushButton *PushButton1;
PushButton1 = new QPushButton();
PushButton1->setGeometry(QRect(19, 20, 154, 4));
QListWidget *ListWidget;
ListWidget = new QListWidget;
scene->addWidget(ListWidget);
scene->addWidget(PushButton1);
QObject::connect(PushButton1, SIGNAL(clicked()),&w, SLOT(handleClick(*QListWidget)));
view.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::handleClick(QListWidget *List)
{
int test;
List->addItem("TESTING");
//QApplication::quit();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QListWidget>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
public slots:
void handleClick(QListWidget *List);
};
#endif // MAINWINDOW_H
This code compiles fine. How I get the following error in the console when the application is running
QObject::connect: No such slot MainWindow::handleClick(*ListWidget) in ..\MenuTest\main.cpp:48
Can someone help me do this? I've seen several tutorials but it's using the designer to make the GUI and I'd like to know how to do it in code without using designer. Thanks.
Your slot accepts QListWidget but you're connecting with ListWidget as the parameter, the signature has to be an exact match due to the way signals and slots work in Qt.
Put handleClick under public slots: and change this line:
QObject::connect(PushButton1, SIGNAL(clicked()),&w, SLOT(handleClick(*ListWidget)));
To this:
QObject::connect(PushButton1, SIGNAL(clicked()),&w, SLOT(handleClick(*QListWidget)));
Update:
I see I missed a key point, the signatures have to match, as in parameter to parameter, so the line up there will not work.
To fix this remove the parameter completely, since PushButton1 can't send it automatically.
QObject::connect(PushButton1, SIGNAL(clicked()),&w, SLOT(handleClick()));
Also remove it here:
void MainWindow::handleClick()
To access the QListWidget you'll have to reference it directly, either by passing it to MainWindow's constructor or iterating the window's controls.

Qt - Compiler complains when invoking setLayout() on my MainWindow

I wanna learn how to create a gui by hand without the designer. I tried to add a layout to my MainWindow but when running it says
QWidget::setLayout: Attempting to set QLayout "" on MainWindow "", which already has a layout
This is my code :
//Header
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
QHBoxLayout *layout;
};
//Constructor in my *.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
layout = new QHBoxLayout;
this->setLayout(layout);
}
//The usual main function
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
What is wrong? I did what my book said. I even looked up some code on the internet which was really hard to find somehow and it was still the same. I just cannot add a layout to my window.
There's a similar question which helped me find out what's wrong. Thanks to Mat for his link to that question.
What every QMainWindow needs is a QWidget as central widget. I also created a new Project with the designer, compiled it and looked the ui_*.h files up.
So every QMainWindow should look similar to this :
//Header
class MainWindow : public QMainWindow
{
Q_OBJECT
QWidget *centralWidget;
QGridLayout* gridLayout;
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
};
//*.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
centralWidget = new QWidget(this);
this->setCentralWidget( centralWidget );
gridLayout = new QGridLayout( centralWidget );
}
Now you don't add / set the layout to the MainWindow. You add / set it to the centralWidget.