I'm trying to learn C++ using Qt for some basic visual applications. I want to make something simple at start, when I push a button, I want to display a text message somewhere. Here is my code:
main.h
#ifndef MYAPP_H
#define MYAPP_H
#include <QWidget>
class QLabel;
class QString;
class MyApp : public QWidget{
public:
MyApp(QWidget *parent = 0);
protected slots:
void showIt();
private:
QString *text_msg;
QLabel *message;
};
#endif
main.cpp
#include <QApplication>
#include <QFont>
#include <QPushButton>
#include <QWidget>
#include <QLabel>
#include <QVBoxLayout>
#include <QFrame>
#include <QString>
#include <vector>
#include <string>
#include <map>
#include "main.h"
#include <fstream>
using std::map;
using std::vector;
using std::string;
using std::ofstream;
/* implementation */
MyApp::MyApp(QWidget *parent):QWidget(parent){
QString text_msg;
text_msg = "This is my first message written in C++! \n It was printed with Qt!";
setFixedSize(400, 280);
QPushButton *quit = new QPushButton(tr("Quit"), this);
quit->setGeometry(62, 40, 75, 50);
quit->setFont(QFont("Times", 18, QFont::Bold));
QPushButton *show_msg = new QPushButton(tr("Show!"), this);
show_msg->setGeometry(30,15,75,45);
show_msg->setFont(QFont("Times", 18, QFont::Bold));
//message = new QLabel();
QLabel *message = new QLabel(this);
//message->setFrameStyle(QFrame::Panel | QFrame::Sunken);
//message->setText(text_msg);
//message->setText("asdf");
connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
connect(show_msg, SIGNAL(clicked()), qApp, SLOT(showIt()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(message);
layout->addWidget(show_msg);
layout->addWidget(quit);
setLayout(layout);
ofstream myfile;
myfile.open ("example");
myfile << "Writing this to a file.\n";
myfile.close();
}
void MyApp::showIt(){
//*text_msg = "xyz";
ofstream myfile;
myfile.open ("example");
myfile << "12121212121.\n";
myfile.close();
message->setText("1234");
}
int main(int argc, char *argv[])
{
/* assign messages for output
bool result;
string key = "first", message="this is a sample text";
result = Messages::add_message(key, message);
*/
/* end */
QApplication app(argc, argv);
MyApp my_simple_app;
my_simple_app.show();
return app.exec();
}
I don't understand why the program doesn't run the slot member function. I put there a some code that should print in a file some text to know if the code inside that function will be executed and the problem is at the QLabel message, but the member function are not executed.
Anyone can help me?
Thank you.
There are 3 things that I needed to change to your code to make it work:
Firstly, in main.h you need to use the Q_OBJECT macro:
class MyApp : public QWidget {
Q_OBJECT
Secondly, in main.cxx, you need to change the connect call to the correct receiver (this instead of myApp):
connect(show_msg, SIGNAL(clicked()), this, SLOT(showIt()));
Thirdly, in main.cxx, you need to uncomment the code that creates the message label as a class member:
message = new QLabel(this);
The most important part is connecting the signal to the slot for a given object like this:
connect(object_emitting, SIGNAL(clicked()),object_receiving, SLOT(showIt()));
connect(show_msg, SIGNAL(clicked()), qApp, SLOT(showIt())); in this stainment change qApp to this and try again
that means
connect(show_msg, SIGNAL(clicked()), this, SLOT(showIt()));
im not suer if there is different between privat slots: and protected slots: but usuely I use privat slots: also u can change it and try :)
Related
Consider following main.cpp (the only file of the whole Qt-project):
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>
#include <QObject>
#pragma once
class collectedFunctions : public QObject
{
Q_OBJECT
public:
collectedFunctions(QObject* parent = 0) {};
~collectedFunctions() {};
public slots:
void setFunc() {
//Calculate 2+2 and change text of the label accordingly
}
};
#include "main.moc"
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
QWidget window;
window.resize(200, 200);
window.setWindowTitle("Test-GUI");
QVBoxLayout layout(&window);
QPushButton button(&window);
button.setText("Test");
button.show();
QLabel *label = new QLabel(&window);
label->setText("Hello");
collectedFunctions testingFuncs;
QObject::connect(&button, &QPushButton::clicked, &testingFuncs, &collectedFunctions::setFunc);
layout.addWidget(&button);
layout.addWidget(label);
window.show();
return app.exec();
}
My goal with this code is to create a slot that runs a function which the programmer defines (similar to the pyqt-implementation of the signals and slots system). The code above successfully compiles, not throwing any errors and so far meeting my expectations. Yet as soon I want to manipulate a widget (which in this case is the label), the setfunc-slot does not find the defined label. How can I manipulate a widget using this slot (e.g. using setText() at a label or addItems() at a combobox) or generally have them being recognized in the slot.
Update:
Thanks to the solution of this question, I figured that I could simply use a lambda instead of the Q_OBJECT makro, so I removed the header-code and then changed the connect from the Button to following:
QObject::connect(&button, &QPushButton::clicked, [&label](){
int num = 2 + 2;
string text = "2+2 = ";
text += std::to_string(num);
QString qtext = QString::fromStdString(text);
label->setText(qtext); });
you shouldn't use the Q_OBJECT macro in main.cpp.
The Q_OBJECT macro must appear in the private section of a class
definition that declares its own signals and slots or that uses other
services provided by Qt's meta-object system.
The moc tool reads a C++ header file. If it finds one or more class
declarations that contain the Q_OBJECT macro, it produces a C++ source
file containing the meta-object code for those classes. Among other
things, meta-object code is required for the signals and slots
mechanism, the run-time type information, and the dynamic property
system.
The C++ source file generated by moc must be compiled and linked with
the implementation of the class.
When you have your class defined in .cpp file instead of .h file moc fails to process it properly.
you need a separate file for class:
in collectedfunctions.h
#pragma once
#include <QObject>
class collectedFunctions: public QObject
{
Q_OBJECT
public:
collectedFunctions(QObject *parent = 0);
~collectedFunctions();
public slots:
void setFunc();
};
and in collectedfunctions.cpp
#include "collectedfunctions.h"
#include <QDebug>
collectedFunctions::collectedFunctions(QObject *parent)
{
}
collectedFunctions::~collectedFunctions()
{
}
void collectedFunctions::setFunc()
{
qDebug() << "2+2 = " << 2 + 2;
}
and in your main.cpp
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>
#include "collectedfunctions.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
window.resize(200, 200);
window.setWindowTitle("Test-GUI");
QVBoxLayout layout(&window);
QPushButton button(&window);
button.setText("Test");
button.show();
QLabel *label = new QLabel(&window);
label->setText("Hello");
collectedFunctions testingFuncs;
QObject::connect(&button, &QPushButton::clicked, &testingFuncs, &collectedFunctions::setFunc);
layout.addWidget(&button);
layout.addWidget(label);
window.show();
return app.exec();
}
don't forget to add QT +=core gui widgets in your .pro file.
Result:
If you want to change QLabel Text :
in collectedfunctions.h
#pragma once
#include <QObject>
class collectedFunctions: public QObject
{
Q_OBJECT
public:
explicit collectedFunctions(QObject *parent = 0);
~collectedFunctions();
signals:
void updateLable(int num);
public slots:
void setFunc();
private:
int num = 0;
};
and in collectedfunctions.cpp
#include "collectedfunctions.h"
#include <QDebug>
collectedFunctions::collectedFunctions(QObject *parent)
{
}
collectedFunctions::~collectedFunctions()
{
}
void collectedFunctions::setFunc()
{
qDebug() << "2+2 = " << 2 + 2;
num++;
emit updateLable(num);
}
and in your main.cpp
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>
#include "collectedfunctions.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
window.resize(200, 200);
window.setWindowTitle("Test-GUI");
QVBoxLayout layout(&window);
QPushButton button(&window);
button.setText("Test");
button.show();
QLabel *label = new QLabel(&window);
label->setText("Hello");
collectedFunctions testingFuncs;
QObject::connect(&button, &QPushButton::clicked, &testingFuncs, &collectedFunctions::setFunc);
QObject::connect(&testingFuncs, &collectedFunctions::updateLable, [&label](int num)
{
qDebug() << "Number = " << num;
label->setText(QString::number(num));
});
layout.addWidget(&button);
layout.addWidget(label);
window.show();
return app.exec();
}
you can see:
I'd like to process the stream of my webcam frame by frame with QT6. I've checked the internet but since QTMultimedia was heavily reworked with QT6, and since QT6 is pretty new, all the documentation/questions available are outdated.
So, In order to achieve my goal, I'm using a QMediaCaptureSession with a camera set on QMediaDevices::defaultVideoInput(). I checked that this was working by setting the video output of the QMediaCaptureSession to a QVideoWidget with m_session.setVideoOutput(ui->videowidget);, and it's working fine, except that I can't process the frames (basically, it's rendering my webcam on the QVideoWidget).
Now, to process the frames, I have to use a QVideoSink as far as I understand the documentation here and there. So I replaced m_session.setVideoOutput(ui->videowidget); with m_session.setVideoSink(&mysink);, where mysink is a QVideoSink.
Then, since I want to process the frames, I'm connecting the videoFrameChanged signal of mysink to a function processVideoFrame where I want to do 2 things :
process the current frame
render the result on the UI, ideally on ui->videowidget
This is the point where I'm struggling. I do not understand how to use the paint function of the class QVideoFrame to render the processed frame on the QVideoWidget. More precisely :
I do not understand how I'm supposed to instantiate the QPainter. I tried a straightforward new QPainter(ui->videowidget) but it ends up in a QWidget::paintEngine: Should no longer be called exception and nothing is rendered
I do not understand what is actually representing the second parameter rect of QVideoFrame::paint?
I made a MWE, code is below.
mwe_videosinkpainting.h
#ifndef MWE_VIDEOSINKPAINTING_H
#define MWE_VIDEOSINKPAINTING_H
#include <QMainWindow>
#include <QMediaCaptureSession>
#include <QMediaDevices>
#include <QCamera>
#include <QVideoSink>
#include <QPainter>
QT_BEGIN_NAMESPACE
namespace Ui { class MWE_VideoSinkPainting; }
QT_END_NAMESPACE
class MWE_VideoSinkPainting : public QMainWindow
{
Q_OBJECT
public:
MWE_VideoSinkPainting(QWidget *parent = nullptr);
~MWE_VideoSinkPainting();
private slots:
void processVideoFrame();
private:
Ui::MWE_VideoSinkPainting *ui;
QVideoSink mysink;
QMediaCaptureSession m_session;
QScopedPointer<QCamera> m_camera;
};
#endif // MWE_VIDEOSINKPAINTING_H
mwe_videosinking.cpp
#include "mwe_videosinkpainting.h"
#include "ui_mwe_videosinkpainting.h"
MWE_VideoSinkPainting::MWE_VideoSinkPainting(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MWE_VideoSinkPainting)
{
ui->setupUi(this);
m_camera.reset(new QCamera(QMediaDevices::defaultVideoInput()));
m_session.setCamera(m_camera.data());
//m_session.setVideoOutput(ui->videowidget);
connect(&mysink, &QVideoSink::videoFrameChanged, this, &MWE_VideoSinkPainting::processVideoFrame);
m_session.setVideoSink(&mysink);
m_camera->start();
}
MWE_VideoSinkPainting::~MWE_VideoSinkPainting()
{
delete ui;
}
void MWE_VideoSinkPainting::processVideoFrame()
{
QVideoFrame videoframe = mysink.videoFrame();
if(videoframe.map(QVideoFrame::ReadOnly))
{
//This is the part I'm struggling to understand and achieve
videoframe.paint(new QPainter(ui->videowidget), QRectF(0.0f,0.0f,100.0f,100.0f), QVideoFrame::PaintOptions());
videoframe.unmap();
}
}
main.cpp
#include "mwe_videosinkpainting.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MWE_VideoSinkPainting w;
w.show();
return a.exec();
}
ui_mwe_videosinkpainting.h (just so that you have the whole code, it has no value for the question)
#ifndef UI_MWE_VIDEOSINKPAINTING_H
#define UI_MWE_VIDEOSINKPAINTING_H
#include <QtCore/QVariant>
#include <QtMultimediaWidgets/QVideoWidget>
#include <QtWidgets/QApplication>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MWE_VideoSinkPainting
{
public:
QWidget *centralwidget;
QGridLayout *gridLayout;
QVideoWidget *videowidget;
QHBoxLayout *horizontalLayout;
QMenuBar *menubar;
QStatusBar *statusbar;
void setupUi(QMainWindow *MWE_VideoSinkPainting)
{
if (MWE_VideoSinkPainting->objectName().isEmpty())
MWE_VideoSinkPainting->setObjectName(QString::fromUtf8("MWE_VideoSinkPainting"));
MWE_VideoSinkPainting->resize(800, 600);
centralwidget = new QWidget(MWE_VideoSinkPainting);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
gridLayout = new QGridLayout(centralwidget);
gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
videowidget = new QVideoWidget(centralwidget);
videowidget->setObjectName(QString::fromUtf8("videowidget"));
horizontalLayout = new QHBoxLayout(videowidget);
horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
gridLayout->addWidget(videowidget, 0, 0, 1, 1);
MWE_VideoSinkPainting->setCentralWidget(centralwidget);
menubar = new QMenuBar(MWE_VideoSinkPainting);
menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 800, 21));
MWE_VideoSinkPainting->setMenuBar(menubar);
statusbar = new QStatusBar(MWE_VideoSinkPainting);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
MWE_VideoSinkPainting->setStatusBar(statusbar);
retranslateUi(MWE_VideoSinkPainting);
QMetaObject::connectSlotsByName(MWE_VideoSinkPainting);
} // setupUi
void retranslateUi(QMainWindow *MWE_VideoSinkPainting)
{
MWE_VideoSinkPainting->setWindowTitle(QCoreApplication::translate("MWE_VideoSinkPainting", "MWE_VideoSinkPainting", nullptr));
} // retranslateUi
};
namespace Ui {
class MWE_VideoSinkPainting: public Ui_MWE_VideoSinkPainting {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MWE_VIDEOSINKPAINTING_H
The answer is quite straightforward : you can use setVideoSink AND setVideoOutput.
The code I gave in OP is good, you just have to uncomment setVideoOutput(ui->videowidget); of mwe_videosinking.cpp and to call setVideoSink BEFORE calling setVideoOutput
Since I cannot format code in a comment...
So, you mean change this...
ui->setupUi(this);
m_camera.reset(new QCamera(QMediaDevices::defaultVideoInput()));
m_session.setCamera(m_camera.data());
//m_session.setVideoOutput(ui->videowidget);
connect(&mysink, &QVideoSink::videoFrameChanged, this, &MWE_VideoSinkPainting::processVideoFrame);
m_session.setVideoSink(&mysink);
m_camera->start();
...to this?
ui->setupUi(this);
m_camera.reset(new QCamera(QMediaDevices::defaultVideoInput()));
m_session.setCamera(m_camera.data());
m_session.setVideoSink(&mysink);
m_session.setVideoOutput(ui->videowidget);
connect(&mysink, &QVideoSink::videoFrameChanged, this, &MWE_VideoSinkPainting::processVideoFrame);
m_camera->start();
I did this and I am still only getting black in my videoWidget.
I used the QT Designer to create a simple dialog and put a pushbutton on it. Then I added a custom slot on pressed() signal called test_button(). I see the generated code and can see that there is a setupUI function that has the following in it:
QObject::connect(pushButton, SIGNAL(clicked()), TestUIClass, SLOT(test_button()));
I have a testui.cpp and a testui.h:
#include <QtWidgets/QMainWindow>
#include "ui_testui.h"
class TestUI : public QMainWindow
{
Q_OBJECT
public:
TestUI(QWidget *parent = 0);
~TestUI();
virtual void test_button();
private:
Ui::TestUIClass ui;
};
This is the testui.cpp
#include "testui.h"
#include <QMessageBox>
TestUI::TestUI(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}
TestUI::~TestUI()
{
}
void TestUI::test_button()
{
QMessageBox msgBox;
msgBox.setText("The document has been modified.");
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
}
My understanding is this is all I have to do, but I cant get the message box to come up.
/********************************************************************************
** Form generated from reading UI file 'testui.ui'
**
** Created by: Qt User Interface Compiler version 5.9.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_TESTUI_H
#define UI_TESTUI_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QToolBar>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_TestUIClass
{
public:
QWidget *centralWidget;
QPushButton *pushButton;
QMenuBar *menuBar;
QToolBar *mainToolBar;
QStatusBar *statusBar;
void setupUi(QMainWindow *TestUIClass)
{
if (TestUIClass->objectName().isEmpty())
TestUIClass->setObjectName(QStringLiteral("TestUIClass"));
TestUIClass->resize(600, 400);
centralWidget = new QWidget(TestUIClass);
centralWidget->setObjectName(QStringLiteral("centralWidget"));
pushButton = new QPushButton(centralWidget);
pushButton->setObjectName(QStringLiteral("pushButton"));
pushButton->setGeometry(QRect(120, 70, 187, 57));
TestUIClass->setCentralWidget(centralWidget);
menuBar = new QMenuBar(TestUIClass);
menuBar->setObjectName(QStringLiteral("menuBar"));
menuBar->setGeometry(QRect(0, 0, 600, 47));
TestClass->setMenuBar(menuBar);
mainToolBar = new QToolBar(TestUIClass);
mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
TestUIClass->addToolBar(Qt::TopToolBarArea, mainToolBar);
statusBar = new QStatusBar(EyeGazeUIClass);
statusBar->setObjectName(QStringLiteral("statusBar"));
TestUIClass->setStatusBar(statusBar);
retranslateUi(TestUIClass);
QObject::connect(pushButton, SIGNAL(clicked()), TestUIClass, SLOT(test_button()));
QMetaObject::connectSlotsByName(TestUIClass);
} // setupUi
void retranslateUi(QMainWindow *TestUIClass)
{
TestUIClass->setWindowTitle(QApplication::translate("TestUIClass", "TestUI", Q_NULLPTR));
pushButton->setText(QApplication::translate("TestUIClass", "PushButton", Q_NULLPTR));
} // retranslateUi
};
namespace Ui {
class TestUIClass: public Ui_TestUIClass {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_TestUI_H
First, you need to tell Qt that your slots actually are slots:
public slots: // or protected/private
void test_button();
There is no need for having the slot virtual...
Second, slots for 'clicked' signal are expected to accept a boolean parameter:
void test_button(bool);
For a normal push button, you can ignore the value, though.
Finally, but that's just a hint: Qt introduced with version 5 a new syntax for connecting signals/slots:
QObject::connect(pushButton, &QPushButton::clicked, theUI, &TestUIClass::test_button);
I prefer it, but it is up to you which one you use...
I have modified the Text Finder example which I got from a Qt Tutorial and made a Text Viewer. In this program, the user types in the address of the file and clicks the Search button. The program then displays the content of the text file. Below is my code.
text_finder.cpp:
#include "text_finder.h"
#include "ui_text_finder.h"
#include <QHBoxLayout>
#include <QFile>
#include <QTextStream>
#include <QFileDialog>
Text_Finder::Text_Finder(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Text_Finder)
{
ui->setupUi(this);
}
Text_Finder::~Text_Finder()
{
delete ui;
}
void Text_Finder::loadFile(QFile file){ // I have to pass the file name as parameter.
QFile inputFile(file);
inputFile.open(QIODevice::ReadOnly);
QTextStream in(&inputFile);
QString line = in.readAll();
inputFile.close();
ui->read->setText(line);
QTextCursor cursor = ui->read->textCursor();
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor, 1);
}
void Text_Finder::on_search_clicked()
{
// Code that gets the path from the text box.
loadFile();//Parameters not passed yet.
}
I have not yet entered the code which gets the name of the file from the address of the text box. I will have to pass the file to the loadFile() function which will enter the contents into the Text Edit in the center of the program. I want a solution to get the name of the file of which the user enters. For example, the user might enter, "/home/user/input.txt". The program should get the contents of that file and forward it to loadFile(). An solution with an explanation on how the various parts work is needed. I am using Qt Creator on Ubuntu 15.04 (Beta).
If i understand you correctly, the user types the full path or address of the file in the text box and you want to get just the name of the file out of the full path the user entered.
EDIT: I realized using 'QFileDialog' was the ideal way to get the file name. So this
is how i redesigned the whole code;
text_finder.h
#ifndef TEXT_FINDER_H
#define TEXT_FINDER_H
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QTextEdit>
#include <QFile>
#include <QTextStream>
#include <QFileDialog>
class Text_Finder : public QWidget{
Q_OBJECT
public:
Text_Finder(QWidget *parent = 0);
~Text_Finder();
public slots:
void on_search_clicked();
void open();
//void loadFile(QString const &filename);
private:
void loadFile(QString const &filename);
QLineEdit *txtFileName;
QTextEdit *txtFileContents;
QString fileName;
QPushButton *search;
QPushButton *openFile;
};
#endif
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
};
#endif // MAINWINDOW_H
text_finder.cpp
#include "text_finder.h"
Text_Finder::Text_Finder(QWidget *parent) : QWidget(parent) {
openFile = new QPushButton("Open File");
connect(openFile, SIGNAL(clicked()), this, SLOT(open()));
txtFileName = new QLineEdit;
search = new QPushButton("&Search");
txtFileContents = new QTextEdit;
QHBoxLayout *dialogAndViewLayout = new QHBoxLayout;
dialogAndViewLayout->addWidget(openFile);
dialogAndViewLayout->addWidget(txtFileName);
dialogAndViewLayout->addStretch();
dialogAndViewLayout->addWidget(search);
QVBoxLayout *layout = new QVBoxLayout;
layout->addLayout(dialogAndViewLayout);
layout->addWidget(txtFileContents);
connect(search, SIGNAL(clicked()), this, SLOT(on_search_clicked()));
setLayout(layout);
}
Text_Finder::~Text_Finder(){
delete txtFileName;
delete txtFileContents;
delete search;
delete openFile;
}
void Text_Finder::loadFile(QString const &filename){
QFile inputFile(filename);
inputFile.open(QIODevice::ReadWrite | QIODevice::Text);
QTextStream textStream(&inputFile);
QString contents = textStream.readAll();
inputFile.close();
txtFileContents->setPlainText(contents);
}
void Text_Finder::on_search_clicked() {
loadFile(fileName);
}
/*this slot opens a file dialog. After the file has been selected, it sets
the file to the text text edit box*/
void Text_Finder::open() {
fileName = QFileDialog::getOpenFileName(this, "Open text", "/home/",
"");
txtFileName->setText(fileName);
}
mainwindow.cpp
#include "mainwindow.h"
#include "text_finder.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
Text_Finder *textFinder = new Text_Finder;
setCentralWidget(textFinder);
}
MainWindow::~MainWindow() {
}
Finally
main.cpp
#include "text_finder.h"
#include <QApplication>
int main(int argc, char **argv){
QApplication app(argc, argv);
Text_Finder *window = new Text_Finder;
window->show();
return app.exec();
}
Unless you're going to do some programmatic editing, you do not need to use QTextCursor at all.
I suggest you have a browse through the reference manual before trying to carry on since it's clear that you are not familiar with the bare-basics of the graphical widgets you're using.
If you're only reading in a file name and then displaying the contents in plain text format, this is all you need to do. (I'm assuming your filename is entered into a QLineEdit widget and ui->read is a QTextEdit widget)
void Text_Finder::loadFile(QString const &filename){ // I have to pass the file name as parameter.
QFile inputFile(filename);
inputFile.open(QIODevice::ReadOnly);
QTextStream in(&inputFile);
QString contents = in.readAll();
inputFile.close();
ui->read->setPlainText(contents);
}
void Text_Finder::on_search_clicked()
{
QString filename = ui->filename->text();
loadFile(filename);
}
EDIT:
I've created a fully-functional remake of your code, incorporating the changes I suggested. I have compiled and tested it and it is working as per your description.
Note: In the absence of your UI file, I've created the user interface manually.
text_finder.h
#ifndef TEXT_FINDER_H
#define TEXT_FINDER_H
#include <QMainWindow>
class QLineEdit;
class QTextEdit;
class Text_Finder : public QMainWindow{
Q_OBJECT
public:
Text_Finder(QWidget *parent = 0);
~Text_Finder();
public slots:
void on_search_clicked();
private:
void loadFile(QString const &filename);
QLineEdit *txtFileName;
QTextEdit *txtFileContents;
};
#endif // TEXT_FINDER_H
main.cpp
#include "text_finder.h"
#include <QApplication>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QTextEdit>
#include <QFile>
#include <QTextStream>
Text_Finder::Text_Finder(QWidget *parent) :
QMainWindow(parent)
{
QWidget *ui = new QWidget(this);
QHBoxLayout *hLayout = new QHBoxLayout;
txtFileName = new QLineEdit(this);
QPushButton *loadButton = new QPushButton("Load File", this);
connect(loadButton, &QPushButton::clicked, this, &Text_Finder::on_search_clicked);
hLayout->addWidget(txtFileName);
hLayout->addWidget(loadButton);
QVBoxLayout *vLayout = new QVBoxLayout(this);
vLayout->addLayout(hLayout);
txtFileContents = new QTextEdit(this);
vLayout->addWidget(txtFileContents);
ui->setLayout(vLayout);
setCentralWidget(ui);
}
Text_Finder::~Text_Finder(){
// It's not necessary to explicitly delete any widgets.
// QObject implements the Composite Pattern, which takes care of all this automatically
}
void Text_Finder::loadFile(QString const &filename){
QFile inputFile(filename);
inputFile.open(QIODevice::ReadOnly);
QTextStream in(&inputFile);
QString contents = in.readAll();
inputFile.close();
txtFileContents->setPlainText(contents);
}
void Text_Finder::on_search_clicked()
{
QString filename = txtFileName->text();
loadFile(filename);
}
int main(int argc, char **argv){
QApplication app(argc, argv);
Text_Finder w;
w.show();
return app.exec();
}
HINT for future questions: You will get better answers quicker if you include an SSCCE in your question. What I've included in this edit is a suitable example.
Alright so is there any way to make this program randomly change the variables x and y every time the button is clicked i am new to programming...
#include <QtGui/QApplication>
#include "mainwindow.h"
#include <QtGUI>
#include <QWidget>
#include <cstdlib>
#include <ctime>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget *window = new QWidget;
srand(time(0));
int x = 1+(rand()%900);
int y = 1+(rand()%400);
QPushButton *MainInter = new QPushButton("Push me!",window);
QPropertyAnimation *animation = new QPropertyAnimation(MainInter, "pos");
animation->setDuration(0);
animation->setEndValue(QPoint(x,y));
Object::connect(MainInter,SIGNAL(released()),animation,SLOT(start()));
window->resize(900,500);
window->show();
return a.exec();
}
What you can do is, instead of connecting the released() signal of your button directly to your animations start() SLOT, you would create your own custom SLOT. Then you connect the button to it, handle the action, and call the animation.
First read up on how to create a custom QWidget, instead of creating top level object in your main(). Simple example here
A custom widget might look like this:
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class QPushButton;
class QPropertyAnimation;
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget *parent = 0);
private:
QPushButton *button;
QPropertyAnimation *animation;
public slots:
void randomizeAnim();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QPushButton>
#include <QPropertyAnimation>
#include <ctime>
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent)
{
button = new QPushButton("Push me!", this);
animation = new QPropertyAnimation(button, "pos");
animation->setDuration(0);
QObject::connect(button, SIGNAL(released()), this, SLOT(randomizeAnim()));
}
void MyWidget::randomizeAnim()
{
srand(time(0));
int x = 1+(rand()%900);
int y = 1+(rand()%400);
animation->setEndValue(QPoint(x,y));
animation->start();
}
And now your main.cpp can be reduced to the boilerplate code:
#include <QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget *window = new MyWidget;
window->resize(900,500);
window->show();
return a.exec();
}
Every time you click, your custom slot will handle the action and do the animation.