Unable to focus and give input to widgets in Qt5 - c++

Issue Resolved: Q_OBJECT macro was necessary and proper signal slot declarations are also important for any other handles.
I am unable to focus on any input type widgets like QTextEdit,QListWidget etc.
Note: There are no compile time or runtime errors.
Update: QSplitter is working properly! I have a QListWidget, whose items I click but they are highlighted only when I make the next move with the splitter.
I have a MainWindow class derived from QMainWindow as declared in main_window.h:
class MainWindow : public QMainWindow{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
//some other members like menu and statusbar here
}
I have another class called Stack derived from QWidget defined in stack.h:
class Stack: public QWidget{
public:
Stack(QWidget *parent=0);
//some other members
}
Constructor of Stack as in stack.cpp :
Stack::Stack(QWidget *parent):QWidget(parent){
main = new QHBoxLayout;
handle = new QSplitter;
setupList();
setupScreens();
//above functions add the widgets to the handle splitter
main->addWidget(handle);
setLayout(main);
}
If i open up this widget in a separate window from the MainWindow using test->show(), the things work as expected/as i want.
But doing this in the MainWindow constructor, renders it unclickable.
MainWindow::MainWindow(QWidget *parent):QMainWindow(parent){
Stack *test = new Stack(this);
//test->show();
setCentralWidget(test);
}
This is strange. Why am i not able to focus any widget that can take input e.g. QTextEdit,QListWidget or click any QPushButton widget?

Please compile following code, it was working..you are getting focus and edit on QTextEdit...
stack.h
#include <QWidget>
class Stack: public QWidget
{
Q_OBJECT
public:
Stack(QWidget *parent = 0);
~Stack(void);
};
stack.cpp
#include "Stack.h"
#include<QTextEdit>
#include<QHBoxLayout>
Stack::Stack(QWidget *parent):QWidget(parent){
QHBoxLayout* main = new QHBoxLayout;
QTextEdit *test = new QTextEdit;
main->addWidget(test);
//other things added to main layout
setLayout(main);
}
Stack::~Stack(void)
{
}
mainwindow1.h
#ifndef MAINWINDOW1_H
#define MAINWINDOW1_H
#include <QtGui/QMainWindow>
//#include "ui_mainwindow1.h"
class Mainwindow1 : public QMainWindow
{
Q_OBJECT
public:
Mainwindow1(QWidget *parent = 0, Qt::WFlags flags = 0);
~Mainwindow1();
private:
//Ui::Mainwindow1Class ui;
};
#endif // MAINWINDOW1_H
mainwindow1.cpp
#include "mainwindow1.h"
#include "Stack.h"
#include <QTextEdit>
Mainwindow1::Mainwindow1(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
Stack *test = new Stack;
setCentralWidget(test);
}
Mainwindow1::~Mainwindow1()
{
}
main.cpp
#include "mainwindow1.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Mainwindow1 w;
w.show();
return a.exec();
}

If some1 would find this looking for answer on how to set focus on input widget from UI in QT5 you can just use:
ui->plainTextEdit->setFocus();

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.

Class inherited from QLabel, why custom slot is not called?

I made class inherited from QLabel. This class also have public slot, that should change label caption. I "call" this SLOT with clicked() SIGNAL of button.
So nothing happened when I press the button.
#include <QApplication>
#include <QLabel>
#include <QPushButton>
class Label : public QLabel
{
public:
Label(QString a) : QLabel(a){}
public slots:
void change()
{
this->setNum(2);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton* button = new QPushButton("Button");
Label* lbl = new Label("Label");
button->show();
lbl->show();
QObject::connect(button, SIGNAL(clicked(bool)), lbl, SLOT(change()));
return a.exec();
}
What should I do to change caption from slot?
In order for the signals and slots to be recognized, the classes must use the Q_OBJECT macro in the private part.
Another thing to do is to include "main.moc", for more information on this point read this.
#include <QApplication>
#include <QLabel>
#include <QPushButton>
class Label : public QLabel
{
Q_OBJECT
public:
Label(const QString &text, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
QLabel(text, parent, f){}
public slots:
void change()
{
setNum(2);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton* button = new QPushButton("Button");
Label* lbl = new Label("Label");
button->show();
lbl->show();
QObject::connect(button, SIGNAL(clicked()), lbl, SLOT(change()));
return a.exec();
}
#include "main.moc"
At the end of making these changes you must execute the following:
Press clean all in the Build menu.
then run qmake in the same menu.
And you just compose your project.
Add Q_OBJECT after
class Label : public QLabel
{
and then you should
either place your Label class declaration to a .h file or write #include "main.moc" after main function declaration.
try to get the return value from your connect call an check it for true or false.
Add Q_OBJECT Macro to the beginning of your derived class.
Add some debug output to your slot like
qDebug()<<"This is my slot.";
Maybe this would help to get a little further.
Best regards

Parent issue (?) while using derived Qt widget class

The following is the smallest example I could make to present the isuue.
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *vLayout = new QVBoxLayout(this);
QGroupBox *gb = new QGroupBox;
// MyGroupBox *gb = new MyGroupBox;
vLayout->addWidget(gb);
QPushButton *btB = new QPushButton;
vLayout->addWidget(btB);
}
The code above produces the image above, it's just a group box and a button in vertical layout.
If I replace QGropBox by MyGroupBox then it doesn't show there anymore. The code below produces the image below.
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *vLayout = new QVBoxLayout(this);
// QGroupBox *gb = new QGroupBox;
MyGroupBox *gb = new MyGroupBox;
vLayout->addWidget(gb);
QPushButton *btB = new QPushButton;
vLayout->addWidget(btB);
}
Where mygroupbox.h (the constructor body is empty in the .cpp file):
#include <QWidget>
class MyGroupBox : public QWidget
{
Q_OBJECT
public:
explicit MyGroupBox(QWidget *parent = 0);
signals:
public slots:
};
Why the group box isn't showing there? How to make it appear?
This is why it doesn't appear:
class MyGroupBox : public QWidget
Your "group box" is basically just a QWidget. Inherit from QGroupBox instead.
As an aside, a minimal example could look like the below. Not a single declaration/statement/expression can be removed. The button aids in visualizing the problem, so it should be left in. The use of a failure trigger variable highlights exactly what condition triggers the failure: the code self-documents and you almost need no narrative to explain it. The question could be as concise as the test case below and one sentence "Why is the group box's border not visible when fail is true?". Most likely, had you followed the minimization fully through, you'd realize yourself what the problem was - it becomes rather obvious. It's not so when MyGroupBox is declared in another file!
The technique of putting it all into a single main.cpp file is critical in spotting the problem: all of the code is physically next to each other, making it much easier to spot mistakes! When you minimize, usually the first things that have to go are separate files: cram it all into one file, and then relentlessly remove absolutely everything that's not directly needed in reproducing the issue.
#include <QtWidgets>
struct MyGroupBox : public QWidget {};
int main(int argc, char ** argv) {
bool fail = true;
QApplication app{argc, argv};
QWidget widget;
QVBoxLayout layout{&widget};
QGroupBox groupBox;
MyGroupBox myGroupBox;
QPushButton button;
layout.addWidget(fail ? static_cast<QWidget*>(&myGroupBox) : &groupBox);
layout.addWidget(&button);
widget.show();
return app.exec();
}
This concise style is not only for trivial test cases. In your real code, the Widget's header and implementation could look as follows:
// Widget.h
#include <QtWidgets>
#include "MyGroupBox.h"
class Widget : public QWidget {
Q_OBJECT
QVBoxLayout layout{this};
MyGroupBox groupBox;
QPushButton button{tr("Click Me!")};
public:
explicit Widget(QWidget * parent = nullptr);
};
// Widget.cpp
#include "Widget.h"
Widget::Widget(QWidget * parent) :
QWidget{parent} {
layout.addWidget(&groupBox);
layout.addWidget(&button);
}
If you insist on shielding the interface from implementation details, don't use pointers to widgets etc., use a PIMPL.
// Widget.h
#include <QWidget>
class WidgetPrivate;
class Widget : public QWidget {
Q_OBJECT
Q_DECLARE_PRIVATE(Widget)
QScopedPointer<WidgetPrivate> const d_ptr;
public:
explicit Widget(QWidget * parent = nullptr);
};
// Widget.cpp
#include "Widget.h" // should always come first!
#include "MyGroupBox.h"
class WidgetPrivate {
Q_DECLARE_PUBLIC(Widget)
Widget * const q_ptr;
public:
QVBoxLayout layout{q_func()};
QGroupBox groupBox;
MyGroupBox myGroupBox;
QPushButton button{"Click Me!"};
WidgetPrivate(Widget * q) : q_ptr(q) {
layout.addWidget(&groupBox);
layout.addWidget(&button);
}
};
Widget::Widget(QWidget * parent) :
QWidget{parent}, d_ptr{new WidgetPrivate{this}}
{}

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.

How can I put this qt program into one source code file

I want to have this code in one file, but can't figure out how to. I know it might not be good practice to do so but I am trying to learn qt, and would find it easier to understand the information if it were in one file.
This is the main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
This is the mainwindow.cpp
#include "mainwindow.h"
#include <QCoreApplication>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
this is the mainwindow.h
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
By just copying everything in one file.
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
It is usually not a good idea to define new classes in same file as your main. Generally you want new classes each in their own file or you would want to put several related classes together in a seperate file. There are a tonne of resources you can google related to best practices for this. I'd suggest you spend some time reading.
But since you asked... below is how you would do it for your example. If you do not define your class above the main, the compiler will complain because it won't know what a "MainWindow" is.
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
#include essentially takes the contents of whatever file you choose and copy/pastes it at that location. The compiler then starts at the top of the file and works its way down to the bottom.
Knowing that, you should be able to just copy-paste the contents of the files in the order they are included.
mainwindow.h
mainwindow.cpp
main.cpp
The short answer is don't do this, you should define a class in its own header file and #include it to the main when you want to run it in the main. This allows you to reuse the class as you see fit throughout the program, its one of the tenets of Object Oriented programming, reusable code. For example
class A
{
public:
A();
~A();
void somePublicMethod();
private:
void somePrivateMethod();
};
If you include that class in your main when you compile that class to object code(assuming you know about implementing that class in a .cpp file) then when all the object files are linked to create the program the linker basically makes one big file with all the object code included in file to be fully compiled. I suggest you read up more on compiling and linking, essentially it boils down to three phases, preprocessing, compiling and linking. Learn more about Object Oriented programming and read up why it's a bad idea to just shove them all into one file. Every class should be in its own self contained .h file(unless its a tightly coupled class) so you can include them as you see fit. Hope this helps, have fun with Qt :)