C++ - Adding item to QListWidget from QPushButton - c++

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.

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.

Can't use slots in connect qt

When I run my project I can't use train_button to add lines in text. Because of I got this error:
QObject::connect: No such slot QTextEdit::onClick()
I try to solve it, but searched only information about adding Q_OBJECT, but I got this. My project is standart Qt Widget Application.
.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QTextEdit>
#include <QString>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void onClick(){
text->append("first\nsecond");
}
private:
QPushButton *train_button;
QTextEdit *text;
Ui::MainWindow *ui;
//QString a = "sdfsdfsdfsdf";
};
# endif // MAINWINDOW_H
.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow){
ui->setupUi(this);
this->setFixedSize(800,600);
text = new QTextEdit(this);
train_button = new QPushButton(this);
text->setGeometry(50,50,500,500);
text->setPlaceholderText("Here we go ...");
train_button->setText("example");
train_button->setGeometry(600,50,100,50);
train_button->setStyleSheet( "background-color: rgb(0, 255, 0);border-style: inset;border-width: 0px;border-radius: 5px;border-color: beige;font: bold 14px;min-width: 10em; padding: 2px;" );
connect(train_button,SIGNAL(clicked()),text,SLOT(onClick();));
}
MainWindow::~MainWindow()
{
delete train_button;
delete solver_button;
delete text;
delete ui;
}
I use QMake version 3.0 using Qt version 5.2.1.
The error is quite clear:
No such slot QTextEdit::onClick()
The documentation is clear as well. QTextEdit has no onClick slot anywhere.
It's not clear what you're trying to do. In any case, you aren't doing it correctly: you cannot connect an inexistent slot to a signal.
By looking at your code, I see that you defined onClick as a member function of MainWindow.
Therefore probably this is what you want:
connect(train_button, &QPushButton::clicked, this, &MainWindow::onClick);
That is, probably you want to attach a slot of the class MainWindow to the button, not a slot of a QTextEdit.

QPushButton - How to append strings of text in a Line Edit box via PushButton

I'm starting to learn Qt and coding. I have a basic project in mind, for practice purposes.
Here is a pic of my small UI:
Bear with me please because I am just starting in cpp.
I would like the QPushButton to append this string -> "text" inside the text box after I click it.
Clicking twice would result in having "texttext" and so on.
I have seen this question answered:
QT creating push buttons that add text to a text edit box
The solution mentioned there seems to be what I need, I just don't understand how to integrate it to my project.
Is there anyone that would be able to help out ?
I have these files so far:
test.pro:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = test
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
mainwindow.h :
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void addTextTolable();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
and mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(this- >addTextToLabel()));
}
void MainWindow::addTextTolable()
{
ui->textEdit->appendPlainText("test");
}
MainWindow::~MainWindow()
{
delete ui;
}
This is the last error I have
mainwindow.cpp:-1: In member function 'void MainWindow::addTextTolable()':
mainwindow.cpp:14: error: 'class QTextEdit' has no member named 'appendPlainText'
ui->textEdit->appendPlainText("test");
^
Welcome to C++ and Qt coding! It's a lot of fun, but there are a lot of things going on. I'll try my best to modify your existing stuff to explain. Classes inherited from QObject send signals to each other through Qt's signal/slot architecture. So, this is what you'll do.
1.) Declare a slot function in the mainwindow header file. This is just a normal function declaration, except placed under a slots: tab.
2.) Connect the signal from the QPushButton's "clicked(bool)" to the mainwindow slot, usually in the MainWindow constructor
So here's the modified code.
mainwindow.h :
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
/*IMPORTANT NOTE: Q_OBJECT must appear in the beginning of the header of any object you want to use signals/slots for*/
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
/*Declare the function to be called when the QPushButton is clicked*/
private slots:
void addTextToLabel();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
and mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
/*It's very important to note that doing anything with the ui object must be done AFTER ui->setupUi(this) is called. The program will segfault otherwise*/
/*General connect syntax:
connect(object that will emit signal, SIGNAL(signal emitted), object that will receive the signal, SLOT(slot function));
/*the pushButton is owned by the ui object*/
connect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(addTextToLabel());
}
/*Now define the slot function*/
void MainWindow::addTextToLabel()
{
/*I actually can't tell from the UI whether the text box is a plainTextEdit or textEdit, so substitute the name of the text box (found in the QDesigner window)*/
ui->textEdit->appendText("test");
}
MainWindow::~MainWindow()
{
delete ui;
}
Give that a shot and let me know if anything goes awry or you have any more questions.

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 :)

Changing the currentIndex() of a tab widget when a different item is selected from a drop-down box

I'm new to C++ and I'm just start to port a program that was originally in python/Qt to C++/Qt in order to take advantage of a better terminal widget that I can embed in my program. Right now I'm a bit stuck, I'm trying to setup where if a different item from a drop-down box is selected the currentIndex() of a tab widget is changed accordingly.
Heres my code so far:
//main.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
heres the mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QTimer *timer;
void startMyTimer()
{
timer = new QTimer();
timer->setInterval(1);
timer->start();
QObject::connect(timer,SIGNAL(timeout()),this,SLOT(changeIndex()));
}
private:
Ui::MainWindow *ui;
void changeIndex();
};
#endif // MAINWINDOW_H
And lastly heres the mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
changeIndex();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::changeIndex()
{
if (ui->comboBox->currentText() == "add-apt-repository")
{
ui->stackedWidget->setCurrentIndex(0);
ui->checkBox->setCheckState(Qt::Checked);
}
if (ui->comboBox->currentText() == "apt-get")
{
ui->stackedWidget->setCurrentIndex(1);
ui->checkBox->setCheckState(Qt::Checked);
}
if (ui->comboBox->currentText() == "aptitude")
{
ui->stackedWidget->setCurrentIndex(2);
ui->checkBox->setCheckState(Qt::Checked);
}
if (ui->comboBox->currentText() == "bzr")
{
ui->stackedWidget->setCurrentIndex(3);
ui->checkBox->setCheckState(Qt::Unchecked);
}
if (ui->comboBox->currentText() == "cd")
{
ui->stackedWidget->setCurrentIndex(4);
ui->checkBox->setCheckState(Qt::Unchecked);
}
if (ui->comboBox->currentText() == "chmod")
{
ui->stackedWidget->setCurrentIndex(5);
ui->checkBox->setCheckState(Qt::Checked);
}
}
I've looked at a bunch of QTimer examples but I'm at a loss.
I also tried doing if (ui->comboBox->changeEvent()) but I was probably using that wrong as well.
First, you probably have to mark changeIndex() as a slot, like this:
class MainWindow : public QMainWindow
{
Q_OBJECT
// ...
private slots:
void changeIndex();
private:
Ui::MainWindow *ui;
}
This also requires you to invoke the Qt meta object compiler. If you use qmake, that's already done for you. Otherwise, it depends on your build system.
Second, is there any particular reason for using the timer? You can also connect to one of the combo box's currentIndexChanged signals.
Drop the timer, it's of no use here.
Instead, make changeIndex() a slot by putting it into a "private slots:" section:
public slots:
void changeIndex();
Then connect the combobox's currentIndexChanged signal to your slot, in the MainWindow constructor:
connect( ui->combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(changeIndex()) );