I have a QTabWidget which contains a QPlainTextEdit. I have managed to add action to the QTabWidget so that whenever a new tab opens, a new QPlainTextEdit is also added in the new tab. See code.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPlainTextEdit>
#include <QMessageBox>
#include <QAction>
#include <QTextCursor>
#include <iostream>
#include <QKeyEvent>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle("Tilde");
current_tab = 1;
on_action_New_triggered();
ui->tabWidget->setTabsClosable(true);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_action_New_triggered()
{
QString newTab = "Tab " + QString::number(current_tab);
ui->tabWidget->addTab(new QPlainTextEdit, newTab);
ui->tabWidget->setCurrentIndex(current_tab - 1);
current_tab++;
editor = qobject_cast<QPlainTextEdit *>(ui->tabWidget->currentWidget());
editor->setFocus();
/*connect(editor->document(), SIGNAL(cursorPositionChanged(QTextCursor)),
this, SLOT(on_editor_cursorPositionChanged()));*/
}
void MainWindow::on_actionNew_document_triggered()
{
on_action_New_triggered();
}
void MainWindow::on_action_Exit_triggered()
{
QMessageBox msg;
msg.addButton(QMessageBox::Yes);
msg.addButton(QMessageBox::No);
msg.setText("Exit program?");
int selection = msg.exec();
if (selection == QMessageBox::Yes)
qApp->exit(0);
}
// highlight current line
void MainWindow::on_editor_cursorPositionChanged()
{
QTextEdit::ExtraSelection highlight;
highlight.cursor = editor->textCursor();
highlight.format.setProperty(QTextFormat::FullWidthSelection, true);
highlight.format.setBackground( QColor(240, 246, 217) );
QList<QTextEdit::ExtraSelection> extras;
extras << highlight;
editor->setExtraSelections(extras);
}
The commented code gives compiler error:
QMetaObject::connectSlotsByName: No matching signal for
on_editor_cursorPositionChanged()
I have added the function in the header file.
Header file:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPlainTextEdit>
#include <QTextCursor>
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_action_New_triggered();
void on_actionNew_document_triggered();
void on_action_Exit_triggered();
void on_editor_cursorPositionChanged();
private:
Ui::MainWindow *ui;
QPlainTextEdit *editor;
qint8 current_tab;
};
#endif // MAINWINDOW_H
Could it be that your signature for the SLOT is wrong?
/*connect(editor->document(), SIGNAL(cursorPositionChanged(QTextCursor)),
this, SLOT(on_editor_cursorPositionChanged()));*/
Should be?
connect(editor->document(), SIGNAL(cursorPositionChanged(QTextCursor)),
this, SLOT(on_editor_cursorPositionChanged(QTextCursor)));
Also, the naming convention you are using for that slot might be conflicting here with your manual connection. Qt may be trying to use the connectSlotsByName mechanism on your SLOT by matching the name: on_<member>_<signal>
In this case, the current signature of that SLOT on_editor_cursorPositionChanged() would match with the QPlainTextEdit editor member. And then you are manually connecting the document to it with the wrong signature. You probably should create another slot that is named more normally docCursorPosChanged(QTextCursor)
Related
I would like to make some modifications of the main window from another file.
I created another ui file Form1Window (which open when a button is cliked in the MainWindow).
I want to call from the class Form1Window a function named test() of the MainWindow class
I succeed in calling function test() but I can't execute the whole content of the function (I can display a message but can't execute the part where I want to clear an edittext)
MainWindow.h
#include "form1window.h"
public slots:
void nettoyer();
private slots:
void openFrom1();
private:
Ui::MainWindow *ui;
From1Window *uiFrom1;
};
MainWindow.cpp
void MainWindow::openFrom1()
{
uiFrom1 = new From1Window(this);
uiFrom1->show();
}
void MainWindow::nettoyer(){
QMessageBox msgBox;
msgBox.setText("test");
msgBox.setIcon(QMessageBox::Information);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.exec();
ui->auteur->clear();
//THIS LINE HAS NO EFFECT WHEN CALLED FROM THE OTHER CLASS
}
form1window.cpp
#include "mainwindow.h"
#include "ui_form1window.h"
void From1Window::on_supprimer_clicked()
{
MainWindow *a=new MainWindow ();
a->test();
close();
}
I've read about the role of the pointer of MainWindow class (C++ /Qt Proper way to access ui from another class in qt //Edited) and I've also tried connect()
Thank for your help
//THIS LINE HAS NO EFFECT WHEN CALLED FROM THE OTHER CLASS
this->ui->auteur->clear();
The line will never executed unless you dismiss QMessageBox. This is because you triggered QMessageBox with exec() function. This function has its own event queue and does not return until finishes. You may set QMessageBox as modal and display it with show() method. In that case QMessageBox will not block execution of the the flow.
This problem can also happen with QDialog(s) if you display them with exec().
I provide you a simple two window signal/slot example:
main.cpp
#include "mainwindow.h"
#include "form.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Form f;
f.show();
return a.exec();
}
form.h
#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include <QPushButton>
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = 0);
~Form();
private:
QPushButton *pb;
};
#endif // FORM_H
form.cpp
#include "form.h"
#include "mainwindow.h"
#include <QDebug>
Form::Form(QWidget *parent) : QWidget(parent)
{
MainWindow *mw = new MainWindow();
pb = new QPushButton("clickME", this);
QObject::connect(pb, SIGNAL(clicked()), mw, SLOT(test()));
mw->show();
}
Form::~Form()
{
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void test();
private:
QLabel *l;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
l = new QLabel("test", this);
}
MainWindow::~MainWindow()
{
}
void MainWindow::test() {
qDebug() << "test called!" << endl;
l->setText("text changed");
}
This works for me.
output
I'm using Qt 5 on a Windows and building a GUI App with multiple QDialog classes. I am trying to connect a signal from a QDialog in a triggered action of the QMainWindow class after instances of both have been created. I have read the documentation on Qt here: http://doc.qt.io/qt-4.8/signalsandslots.html and here: https://wiki.qt.io/New_Signal_Slot_Syntax. I have also read through many questions on stackoverflow that have helped correct some of the initial errors I was getting, but haven't helped me solve this problem.
The error I keep getting is:
"expected primary-expression before ',' token"
I have tried both the old syntax for connect
connect(sender, SIGNAL (valueChanged(QString,QString)),
receiver, SLOT (updateValue(QString)) );
and the new syntax (which is shown in the .cpp file below)
connect(sender, &Sender::valueChanged,
receiver, &Receiver::updateValue );
The MainWindow is created in the main.cpp and the 2nd dialog is created on_action_someAction_triggered(), so I know that the instances I am referencing exist. Is there a better way for me to connect the SIGNAL and the SLOT?
Here is the code I am working with (minus the extra unrelated code).
mainwindow .h:
#include <QMainWindow>
#include "shipdia.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void loadSelectedShip(QString shipName);
private slots:
void on_actionNew_Ship_triggered();
private:
Ui::MainWindow *ui;
shipdia *sDialog;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTextStream>
#include <QObject>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionNew_Ship_triggered()
{
sDialog = new shipdia(this);
QObject::connect(&shipdia, //this is were I attempt to
&shipdia::sendShip, //connect the signal/slot
this,&MainWindow::loadSelectedShip); //but always get an error
sDialog ->show();
}
void MainWindow::loadSelectedShip(QString shipName)
{
... do something ... //this code works, but the signal is never received
}
qdialog.h
#ifndef SHIPDIA_H
#define SHIPDIA_H
#include "functions.h"
#include <QDialog>
namespace Ui {
class shipdia;
}
class shipdia : public QDialog
{
Q_OBJECT
public:
explicit shipdia(QWidget *parent = 0);
~shipdia();
private slots:
void on_pushButton_2_clicked();
signals:
void sendShip(QString shipName);
private:
Ui::shipdia *ui;
};
#endif // SHIPDIA_H
qdialog.cpp
#include "shipdia.h"
#include "ui_shipdia.h"
#include <QObject>
#include <QMessageBox>
#include <QTextStream>
#include <QDir>
shipdia::shipdia(QWidget *parent) :
QDialog(parent),
ui(new Ui::shipdia)
{
ui->setupUi(this);
}
shipdia::~shipdia()
{
delete ui;
}
void shipdia::sendSelectedShip(QString shipName)
{
emit sendShip(shipName); //I previously just emitted sendSelectedShip,
//but separating the function did not fix it.
}
void shipdia::on_pushButton_2_clicked()
{
//Code below functions up to next comment
QString shipName = ui->line_23->text();
shipName = QDir::currentPath() + "/shipFolder/" + shipName + ".txt";
QFile shipFile(shipName);
QStringList stringList;
if (shipFile.open(QIODevice::ReadOnly))
{
QTextStream in(&shipFile);
while(!in.atEnd())
{
QString line = in.readLine();
if(line.isNull())
break;
else
stringList.append(line);
}
shipFile.close();
}
//Code above functions ^
sendSelectedShip(shipName); //this line does not produce an error
}
I think, the code should be
sDialog = new shipdia(this);
QObject::connect(sDialog,
&shipdia::sendShip,this,&MainWindow::loadSelectedShip);
and it should be placed in the constructor of the MainWindow, right after ui->setupUi(this); and the on_actionNew_Ship_triggered() function should look like this:
void MainWindow::on_actionNew_Ship_triggered()
{
sDialog ->show();
}
In your original code, a new instance of shipdia will be created everytime the on_actionNew_Ship_triggered() is called. That should be avoided.
Hope this helps.
I am trying to connect a signal from a second QMainWindow to the mainwindow. It doesn't say anything about a problem connection when the program is launched, but It doesn't work. I am not very familiar with C++ and Qt so maybe is something simple.
My code consists on a Mainwindow used as a SCADA with Start, stop, On, off buttons. In the second qmainwindow I created a terminal where you can type, start,stop... There, I would like to emit a signal to my MainWindow which is in charge of controlling the multiple threads and windows. The problem is that I cannot connect to my slot. I present here a simple overview of this two pieces of code.
Terminal. h
#ifndef TERMINAL__H
#define TERMINAL__H
#include <QMainWindow>
#include <QTextEdit>
#include <QLineEdit>
#include <QObject>
namespace Ui {
class Terminal_;
}
class Terminal_ : public QMainWindow
{
Q_OBJECT
public:
explicit Terminal_(QWidget *parent = 0);
~Terminal_();
signals:
void turnonPLC_terminal();
public slots:
void newline();
private:
Ui::Terminal_ *ui;
QTextEdit* mTerminal;
QLineEdit* mInput;
};
#endif // TERMINAL__H
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "terminal_.h"
#include "terminal_help.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Terminal_ *terminal;
public slots:
void turnon_terminal();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "terminal_.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
terminal = new Terminal_(this);
connect(terminal, SIGNAL(turnonPLC_terminal()), this, SLOT(turnon_terminal()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::turnon_terminal(){
turnonPLC=1;
}
terminal_.cpp
#include "terminal_.h"
#include "ui_terminal_.h"
#include <QDockWidget>
#include <QWidget>
#include <QLineEdit>
QString on=("on");
Terminal_::Terminal_(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Terminal_)
{
ui->setupUi(this);
mTerminal = new QTextEdit();
setCentralWidget(mTerminal);
mInput = new QLineEdit();
QDockWidget* qdw = new QDockWidget;
qdw->setWidget(mInput);
addDockWidget(Qt::BottomDockWidgetArea, qdw);
connect (mInput, SIGNAL(returnPressed()),
this, SLOT(newline()));
}
Terminal_::~Terminal_()
{
delete ui;
}
void Terminal_::newline(){
QString command = mInput->text();
if (command==on){
emit turnonPLC_terminal();
}
}
Thanks
The signal-slots part in the code works perfectly. (compiled and tested with some small modifications)
After entering "on" (not On as written in question)
Terminal_::newline() slot called, turnonPLC_terminal() is fired and finally
void MainWindow::turnon_terminal() is called.
However, there are some small details the header file is called terminal_.h, not Terminal.h turnonPLC is not defined. terminal is created by not displayed (no show-call).
I guess, there are simply some many small logic errors. Try to use debugger or trace the chain of expected calls with qDebug.
Ok I think is time to get some help, I have been practicing with signals and slots in Qt and I got stocked. What I want is to be able to change a label in mainwindow when a button in a QDialog is clicked. I have been searching and apparently the only way to do this is basically using signals and slots, here is what I have...
I have a mainwindow.ui with a button called "pushButton_OpenWindow" and a QLabel label_ShowText", I also have a externaldialog.ui that contains a QLineEdit called lineEdit_ExternalInput" and a QPushButton called "pushButton_SendText", and what I want is to change "label_ShowText" to whatever value "lineEdit_ExternalInput" is when pushButton_SendText" is clicked but it doesn't work, when I click the button nothing happens no errors, no warnings nothing.
Here is the code that doesn't work...
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 = 0);
~MainWindow();
private slots:
void on_pushButton_OpenWindow_clicked();
void textValue(const QString &newText);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "externaldialog.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ExternalDialog *externalDialog = new ExternalDialog;
// connecting signals and slots
QObject::connect(externalDialog, SIGNAL(textChanged(QString)), this, SLOT(textValue(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_OpenWindow_clicked()
{
ExternalDialog mDialog;
mDialog.setModal(true);
mDialog.exec();
}
void MainWindow::textValue(const QString &newText)
{
ui->label_ShowText->setText(newText);
qDebug()<<"Message from textValue Function \n";
}
externaldialog.h
#ifndef EXTERNALDIALOG_H
#define EXTERNALDIALOG_H
#include <QDialog>
namespace Ui {
class ExternalDialog;
}
class ExternalDialog : public QDialog
{
Q_OBJECT
public:
explicit ExternalDialog(QWidget *parent = 0);
~ExternalDialog();
private:
Ui::ExternalDialog *ui;
signals:
void textChanged(const QString&);
public slots:
void on_pushButton_SendText_clicked();
};
#endif // EXTERNALDIALOG_H
externaldialog.cpp
#include "externaldialog.h"
#include "ui_externaldialog.h"
#include <QDebug>
ExternalDialog::ExternalDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ExternalDialog)
{
ui->setupUi(this);
}
ExternalDialog::~ExternalDialog()
{
delete ui;
}
void ExternalDialog::on_pushButton_SendText_clicked()
{
emit textChanged(ui->lineEdit_ExternalInput->text());
qDebug()<<"Sent Message";
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Any idea what I'm I doing wrong? Any suggestion will be appreciated. Sorry I posted the whole code but sometimes is better to see the whole picture.
Thanks a lot
change function MainWindow::on_pushButton_OpenWindow_clicked() into this
void MainWindow::on_pushButton_OpenWindow_clicked()
{
externalDialog->setModal(true);
externalDialog->exec();
}
You have just create a new unconnected dialog in the original function.
This question should hopefully be easy to answer. I created a few buttons in my MainWindow using Qt Creator, and when I go to write the functions for the buttons, the compiler says they were not declared in this scope. What do I need to #include for these objects to be declared? The compiler error for the following would be 'baseDir' was not declared in this scope. baseDir is the objectName for a lineEdit in my window.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "ui_mainwindow.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void getDir();
void createProj();
private slots:
void on_findDir_clicked();
void on_create_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "functions.h"
#include <QtGui/QApplication>
#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_findDir_clicked()
{
QString path;
path = QFileDialog::getOpenFileName(
this,
"Choose a file to open",
QString::null,
QString::null );
baseDir->setText( path );
}
The items you define in your .ui file are not added directly to your main window class, they are added to its ui membre.
Try with:
ui->baseDir->setText( path );
Look at the ui_mainwindow.h file that is generated during the build if you're curious.