I want to make the MainWindow receive the signals emitted from QToolButtons, and then do something in the slot function according to the index sent from QToolButtons. When I compiled the project, no error occurred. But when I clicked these toolbuttons, nothing happened and the log didn't get printed. I think there's something wrong with the signal or slot, but the program runs with no errors, so I don't know how to find the solution.
MainWindow.cpp:
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowTitle(MainWindowTitle);
setWindowIcon(QIcon(":/res/icons/logo.ico"));
signalMapper = new QSignalMapper(this);
initLayout();
}
void MainWindow::initLayout()
{
// initialize sidebar buttons
initSideBar();
// initialize QStackedWidget
/* initialize CodePage */
codePage = new CodePage(this);
ui->stackedWidget->addWidget(codePage);
ui->stackedWidget->setCurrentWidget(codePage);
/* initialize Charts */
qCharts = new ThemeWidget();
ui->stackedWidget->addWidget(qCharts);
// ui->stackedWidget->setCurrentWidget(qCharts);
}
void MainWindow::initSideBar()
{
QStringList btn_bgImages;
QStringList btn_names;
btn_bgImages << ":res/sidebar/code.png" << ":res/sidebar/pencil.png" << ":res/sidebar/visualize.png" << ":res/sidebar/graph.png";
btn_names << "Editor" << "Designer" << "Visualize" << "Charts";
for(int i = 0; i < btn_bgImages.size(); i++)
{
cTabButton* ctBtn = new cTabButton(btn_bgImages.at(i));
ctBtn->setText(btn_names.at(i));
connect(ctBtn, SIGNAL(&QAbstractButton::clicked), signalMapper, SLOT(&QSignalMapper::map));
signalMapper->setMapping(ctBtn, i);
ui->sidebar->addWidget(ctBtn, 0, Qt::AlignTop);
}
QObject::connect(signalMapper, SIGNAL(map), this, SLOT(MainWindow::switchPage));
}
void MainWindow::switchPage(int index)
{
qDebug() << "switchPage() triggered";
switch(index)
{
case 0:
qStackedWidget->setCurrentWidget(codePage);
break;
case 1:
break;
case 2:
break;
case 3:
qStackedWidget->setCurrentWidget(qCharts);
break;
default:
break;
}
}
MainWindow.h:
QT_BEGIN_NAMESPACE
namespace Ui
{
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent = nullptr);
~MainWindow();
private slots:
void switchPage(int);
private:
Ui::MainWindow* ui;
CodeEditor* configEditor;
QListView* sidebar;
QStackedWidget* qStackedWidget;
CodePage* codePage;
ThemeWidget* qCharts;
QSignalMapper* signalMapper;
void initSideBar();
void initLayout();
};
cTabButton.h
class cTabButton : public QToolButton{
Q_OBJECT
public:
cTabButton(const QString& path, QWidget *parent=0);
~cTabButton();
protected:
QString path;
bool m_mousePressed;
bool m_mouseHover;
void doPaintStuff(int topColor, int centerColor, int bottomColor);
void setButtonPressed(bool isPressed);
void enterEvent(QEnterEvent *);
void leaveEvent(QEvent *);
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
};
It looks like you are connecting to the wrong signal of QSignalMapper. Since you map to an integer, you want to connect to QSignalMapper::mappedInt:
QObject::connect(signalMapper, &QSignalMapper::mappedInt, this, &MainWindow::switchPage);
Related
main H :
`
namespace Ui {
class StrategyManageMent;
}
class StrategyManageMent : public QWidget //class MainWindow
{
Q_OBJECT
public:
explicit StrategyManageMent(QWidget *parent = nullptr);
~StrategyManageMent();
private:
Ui::StrategyManageMent *ui;
QThread *tHighAG = new QThread; //QThread *t1= new QThread;
QThread* tLowAG = new QThread;
HighAG *HighAGTh = new HighAG; //work1=HighAGTh,HighAG=Thread1
// Thread2* work2 = new Thread2;
public slots:
void receiveKlineInformation(QString symbol, OneSymbolKlineData *data);
void receiveQuoteInformation(std::shared_ptr<QuoteInfo>);
void on_addStrategy_clicked();
void on_StartStrategy_clicked();
void on_StopStrategy_clicked();
void OnTick(QString symbol, std::shared_ptr<QuoteInfo>);
signals:
void startHigh(int num); //void starting1(int num);
void startLow(int num);
void STMsendTick(std::shared_ptr<QuoteInfo>);
};
`
main cpp:
`
StrategyManageMent::StrategyManageMent(QWidget *parent) :
QWidget(parent),
ui(new Ui::StrategyManageMent)
{
ui->setupUi(this);
this->setWindowTitle("Threads");
ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "Time" << "logs" << "act");
HighAGTh->moveToThread(tHighAG);
connect(this, &StrategyManageMent::startHigh, HighAGTh, &HighAG::startHighAG);
connect(ui->StartStrategy, &QPushButton::clicked, this, [=]() {
emit startHigh(1000);
tHighAG->start();
HighAGTh->AGstart = true;
connect(this, SIGNAL(STMsendTick(std::shared_ptr<QuoteInfo>)), HighAGTh, SLOT(On_Tick(std::shared_ptr<QuoteInfo>)));
//connect(HighAGTh, SIGNAL(sendTick(std::queue<QuoteInfo>)), HighAGTh, SLOT(startHighAG(std::queue<QuoteInfo>)));
});
connect(ui->StopStrategy, &QPushButton::clicked, this, [=]() {
HighAGTh->AGstart = false;
tHighAG->quit();
tHighAG->wait();
disconnect(this, SIGNAL(STMsendTick(std::shared_ptr<QuoteInfo>)), HighAGTh, SLOT(On_Tick(std::shared_ptr<QuoteInfo>)));
});
}
void StrategyManageMent::OnTick(QString, std::shared_ptr<QuoteInfo> quote)
{
// qDebug() << "StrategyManageMent::OnTick datas:" << quote->lastPrice; //datas can be printed out here.
emit STMsendTick(quote);
}
`
Thread H:
`
class HighAG : public QObject //Thread1
{
Q_OBJECT
public:
explicit HighAG (QObject* parent = nullptr);
QString m_strategy_name;
bool AGstart = false;
struct QuoteInfo* tickdata;
std::queue<QuoteInfo> tickQue;
signals:
void working(int num);
void finish(QString elapsedTime);
void sendTick(std::queue<QuoteInfo> tickQue);
public slots:
void On_Tick(std::shared_ptr<QuoteInfo>);
void startHighAG(int num); //begin
private:
};
`
Thread cpp:
`
HighAG::HighAG (QObject* parent) : QObject(parent)
{
// std::shared_ptr<QuoteInfo> tickdata(new QuoteInfo);
}
void HighAG::startHighAG(int num)
{
qDebug() << " Thread start" << " || " << QThread::currentThread();
while (AGstart) {
{
//QMutexLocker locker(&lock);
qDebug() << "Thread running ";
qDebug() << "*****Thread startHighAG::OnTick:" << this->tickQue.back().askPrice1; //shows empty queue error here.
QThread::sleep(1);
if (!AGstart) {
break;
}
}
//emit resultReady(parameter + "running......");
}
qDebug() << "Stopped " ;
// emit finish(QString::number(time.elapsed()));
}
void HighAG::On_Tick(std::shared_ptr<QuoteInfo> quote)
{
tickQue.push(*quote);
qDebug() << "startHighAG::OnTick:" << tickQue.back().askPrice1; //datas can be printed out well.
emit sendTick(tickQue);
}
`
In the On_Tick slot, it can print out different datas coming in. means On_Tick slot working.
In thread HighAG, it print out "Thread running ", means thread is working.
However it can not print out this->tickQue.back().askPrice1; it shows queue error.
How does thread read this queue? Thanks for any help.
I want to insert a QComboBox inside a QTableWidget. When I change the Index of the CB I'll call a methode to change the status in the sqlite table. But for this, I need do pass two parameters to the methode. The ID(First element of the row), and the current index of the CB.
I generate the QTableWidget like that:
...
for(int i = 0; i < dbModel->rowCount();i++){
row = dbModel->record(i);
ui->tW_Services->setItem(i,0,new QTableWidgetItem(row.field(0).value().toString()));
ui->tW_Services->setItem(i,1,new QTableWidgetItem(row.field(1).value().toString()));
ui->tW_Services->setItem(i,2,new QTableWidgetItem(row.field(2).value().toString()));
ui->tW_Services->setItem(i,3,new QTableWidgetItem(row.field(3).value().toString()));
ui->tW_Services->setItem(i,4,new QTableWidgetItem(row.field(4).value().toString() + "€"));
ui->tW_Services->setItem(i,5,new QTableWidgetItem(row.field(5).value().toString() + "€"));
//ui->tW_Services->setItem(i,6,new QTableWidgetItem(row.field(6).value().toString()));
QComboBox* combo = new QComboBox();
combo->addItem("open");
combo->addItem("paid");
if(row.field(6).value().toString() != "paid") combo->setCurrentIndex(0);
else combo->setCurrentIndex(1);
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboChanged(int)));
ui->tW_Services->setCellWidget(i,6,combo);
}
...
and the slot looks like that:
void MainWindow::onComboChanged(int ID)
{
qDebug() << "ID:" << QString::number(ID);
}
But when I try to create the method with 2 args:
void MainWindow::onComboChanged(int ID,int index)
{
qDebug() << "ID:" << QString::number(ID);
}
and attach a second parameter and calling the slot like:
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboChanged(row.field(0).value().toInt(),int)));
I get:
qt.core.qobject.connect: QObject::connect: No such slot MainWindow::onComboChanged(row.field(0).value().toInt(),int)
A minimal reproducible example:
There's just a single pushbutton and a qtablewidget
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void onComboChanged(int ID, int index);
void onComboChanged2(int index);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QComboBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
ui->tableWidget->setColumnCount(4);
ui->tableWidget->setRowCount(3);
for(int i = 0; i < 3;i++){
ui->tableWidget->setItem(i,0,new QTableWidgetItem(QString::number(i)));
ui->tableWidget->setItem(i,1,new QTableWidgetItem("Test"));
ui->tableWidget->setItem(i,2,new QTableWidgetItem("Test 2"));
QComboBox* combo = new QComboBox();
combo->addItem("open");
combo->addItem("paid");
combo->setCurrentIndex(0);
int j = i+1;
//NOT WORKING
//connect(combo, SIGNAL(currentIndexChanged(int)),this,
// [=](int index) {this->onComboChanged(j, index);});
//WORKING
//connect(combo, SIGNAL(currentIndexChanged(int)),SLOT(onComboChanged2(int)));
ui->tableWidget->setCellWidget(i,3,combo);
}
}
void MainWindow::onComboChanged(int ID, int index)
{
qDebug() << "ID: " << ID << "index: "<< index;
}
void MainWindow::onComboChanged2(int index)
{
qDebug() << "ID: " << index;
}
Since currentIndexChanged only has one parameter, your slot cannot capture more than that. But, since the row ID does not change on emission, you can wrap onComboChanged into a lambda as shown here, which captures the row by copy:
connect(combo, &QComboBox::currentIndexChanged,
this, [=](int index) {this->onComboChanged(i, index);});
Since your code is not a minimal reproducible example, I could not test this. Let me know, if it doesn't work.
I have a question how to override the signal in Qt?
I have redefined QCheckBox() and changed stateChanged signal.
The project is bilding and working. It does not output in the "application output" errors or messages of the " signal with the slot is not connected"
BUT it doesn't link to the slot. I can't figure out what's wrong.
This code works :
connect(test_checkbox[i], SIGNAL(stateChanged(int)), two_cl , SLOT(run_NEW()));
I need to emit string in addition to the number :
connect(test_checkbox[i], SIGNAL(stateChanged(int, QString)), two_cl , SLOT(run_NEW(int, QString)));
override QCheckBox
.h
#ifndef MYDIMASCHECKBOX_H
#define MYDIMASCHECKBOX_H
#include <QCheckBox>
class MyDimasCheckBox : public QCheckBox
{
Q_OBJECT
public:
MyDimasCheckBox(QWidget *parent =0);
~MyDimasCheckBox();
QString stroka;
signals:
void stateChanged(int, QString);
};
#endif // MYDIMASCHECKBOX_H
.cpp
#include "mydimascheckbox.h"
MyDimasCheckBox::MyDimasCheckBox(QWidget *parent)
{
stroka = "dimasik :3";
emit stateChanged(int(), stroka);
}
MyDimasCheckBox::~MyDimasCheckBox()
{
}
And here is where challenge
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QDebug>
#include <QThread>
#include <QCoreApplication>
#include <iostream>
#include <vector>
#include "mydimascheckbox.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
int glob_i ;
int glob_flow;
int vector_schet;
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void start_sending(bool);
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QThread *thread = new QThread();
QVector<QThread*> vector_thread;
QList<MyDimasCheckBox*> test_checkbox;
MyDimasCheckBox *checkBox = new MyDimasCheckBox();
QWidget *checkBoxWidget = new QWidget();
QHBoxLayout *layoutCheckBox = new QHBoxLayout(checkBoxWidget);
};
class NewsThread: public QThread
{
Q_OBJECT
public slots:
void run_NEW();
void run_NEW(int, QString);
signals:
void otprawka (int);
};
#endif // MAINWINDOW_H
.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
glob_i=0;
glob_flow =0;
vector_schet =0;
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
test_checkbox.clear();
}
void MainWindow::on_pushButton_clicked()
{
glob_i++;
checkBoxWidget = new QWidget();
checkBox = new MyDimasCheckBox();
layoutCheckBox = new QHBoxLayout(checkBoxWidget);
test_checkbox.append(checkBox);
connect(checkBox, SIGNAL(toggled(bool)),this, SLOT(start_sending(bool)));
checkBox->setText(QString::number(glob_i));
layoutCheckBox->addWidget(checkBox);
layoutCheckBox->setAlignment(Qt::AlignCenter);
layoutCheckBox->setContentsMargins(0,0,0,0);
ui->tW_test->insertRow(ui->tW_test->rowCount());
ui->tW_test->setCellWidget(ui->tW_test->rowCount()-1, 1, checkBoxWidget);
qDebug() << "glob_i: " << glob_i;
}
void MainWindow::start_sending(bool Value)
{
qDebug() << "start_sending " ;
// когда нажата отрабатывает, отжата то не отрабатывает
if (Value == true)
{
NewsThread *two_cl = new NewsThread();
qDebug() << "chekbocks: "<< " TRUE" ;
for (int i =0;i < test_checkbox.length();i++ )
{
if(test_checkbox[i]->isChecked() ==Value)
{
glob_flow++;
// connect(test_checkbox[i], SIGNAL(stateChanged(int)), two_cl , SLOT(run_NEW()));
connect(test_checkbox[i], SIGNAL(stateChanged(int, QString)), two_cl , SLOT(run_NEW(int, QString)));
thread = new QThread();
vector_thread.append(thread);
vector_schet++;
qDebug() << "vector_schet : " << vector_schet ;
two_cl->moveToThread(vector_thread[vector_schet-1]);
vector_thread[vector_schet-1]->start();
}
}
}
else {
qDebug() << "chekbocks:" << " False";
glob_flow--;
qDebug() << "vector_schet : " << vector_schet ;
vector_thread[vector_schet-1]->exit();
}
}
void NewsThread::run_NEW()
{
qDebug() << "run_NEW()";
for(;;){
for (int i=0; i<500; i++){
qDebug()<< "Число :" << i <<"number \"flow\" :" ;
usleep(100000);
}
}
}
void NewsThread::run_NEW(int i, QString str){
qDebug() << "run_NEW(int i, QString str) ";
for(;;){
for (int i=0; i<500; i++){
qDebug() << " i : " << i;
qDebug() << " str : " << str;
qDebug()<< "Число :" << i <<"number \"flow\" :" ;
usleep(100000);
}
}
}
You cannot replace a signal with another signal in a subclass. You can, however, emit an additional signal with the original signal in a self-connected slot:
class MyDimasCheckBox : public QCheckBox
{
Q_OBJECT
public:
MyDimasCheckBox(QWidget *parent =0);
~MyDimasCheckBox();
QString stroka;
private slots:
// Emits the new signal
void doEmitStateChanged(int i);
signals:
void stateChanged(int, QString);
};
MyDimasCheckBox::MyDimasCheckBox(QWidget *parent) : QCheckBox(parent) {
// Connect original signal to slot
connect(this, SIGNAL(stateChanged(int)), this, SLOT(doEmitStateChanged(int)));
}
void MyDimasCheckBox::doEmitStateChanged(int i) {
emit stateChanged(i, stroka);
}
With the new connection syntax, you can omit the slot and use a lambda:
connect(this, qOverload<int>(&QCheckBox::stateChanged),
// "this" context-object for QThread-Affinity
this, [=](int i) { emit this->stateChanged(i, this->stroka); });
Overriding signal is a bad practice [1]:
"APIs with overridden signals are hard to use, unexpected and bug-prone. To make it worse, Qt even allows you to override a signal with a non-signal, and vice-versa."
https://www.kdab.com/nailing-13-signal-slot-mistakes-clazy-1-3/
I have a program that is meant to find a certain amount of numbers with odds/evens. I keep track of this and display in in my GUI from a worker thread. This works, but while it is working the program freezes. The program is still calculating, but it stops updating the GUI. Here is my relevant code:
MainWindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QThread>
class CounterThread : public QThread
{
Q_OBJECT
public:
CounterThread();
void run();
signals:
void setProgress(int value);
void setOdd0(int value);
void setOdd1(int value);
void setOdd2(int value);
void setOdd3(int value);
void setOdd4(int value);
void setOdd5(int value);
void setOdd6(int value);
};
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
CounterThread *cThread;
};
#endif // MAINWINDOW_H
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qDebug>
#include <QLCDNumber>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
cThread = new CounterThread();
connect(cThread, SIGNAL(setOdd0(int)), ui->lcdNumberodd0, SLOT(display(int)));
connect(cThread, SIGNAL(setOdd1(int)), ui->lcdNumberodd0, SLOT(display(int)));
connect(cThread, SIGNAL(setOdd2(int)), ui->lcdNumberodd0, SLOT(display(int)));
connect(cThread, SIGNAL(setOdd3(int)), ui->lcdNumberodd0, SLOT(display(int)));
connect(cThread, SIGNAL(setOdd4(int)), ui->lcdNumberodd0, SLOT(display(int)));
connect(cThread, SIGNAL(setOdd5(int)), ui->lcdNumberodd0, SLOT(display(int)));
connect(cThread, SIGNAL(setOdd6(int)), ui->lcdNumberodd0, SLOT(display(int)));
connect(cThread, SIGNAL(setProgress(int)), ui->progressBar, SLOT(setValue(int)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
ui->progressBar->setMaximum(13983816);
cThread->start();
ui->progressBar->setValue(ui->progressBar->maximum());
}
CounterThread::CounterThread()
{
}
void CounterThread::run()
{
int odd0 = 0;
int odd1 = 0;
int odd2 = 0;
int odd3 = 0;
int odd4 = 0;
int odd5 = 0;
int odd6 = 0;
for (int x = 99999; x < 999999; x++)
{
int oddNumbers = 0;
for(int i = 0; i < QString::number(x).length(); i++)
{
if (QString(QString::number(x)[i]).toInt() % 2 != 0)
oddNumbers++;
}
setProgress(x);
switch (oddNumbers)
{
case 0:
odd0++;
setOdd0(odd0);
break;
case 1:
odd1++;
setOdd1(odd1);
break;
case 2:
odd2++;
setOdd2(odd2);
break;
case 3:
odd3++;
setOdd3(odd3);
break;
case 4:
odd4++;
setOdd4(odd4);
break;
case 5:
odd5++;
setOdd5(odd5);
break;
case 6:
odd6++;
setOdd6(odd6);
break;
}
}
}
Your worker thread's run() function modifies an object owned by the main thread (e.g. the UI thread.) The many calls to setProgress() will quickly fill the event queue on the GUI and cause other events to not be serviced responsively.
The correct way to set up worker threads in Qt has been discussed elsewhere on Stackoverflow, for example:
Qt4: while loop in seperate thread blocks GUI
I am implementing a code to add different entities on a button click.I am getting a problem to add Text in graphics view. Following is the code snippet that I am implementing. What needs to be done?
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPaintEvent>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QPainter>
#include "line.h"
#include "circle.h"
#include "ellipse.h"
#include "point.h"
#include "arc.h"
#include "text.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void wheelEvent(QWheelEvent* event);
private:
Ui::MainWindow *ui;
bool mFirstClick;
bool mPaintFlag;
int mStartX;
int mStartY;
int mEndX;
int mEndY;
QGraphicsScene *scene;
QPainter *painter;
point *item;
line *item1;
circle *item2;
ellipse *item3;
arc *item4;
private slots:
void drawPoint();
void drawLine();
void drawCircle();
void drawEllipse();
void drawArc();
void drawText();
void on_actionSave_triggered();
void on_actionOpen_triggered();
void on_actionQuit_2_triggered();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMouseEvent>
#include<QFileDialog>
#include<QMessageBox>
#include<QTextEdit>
#include<QString>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle(tr("GD CAD"));
scene = new QGraphicsScene;
for(int x = 0; x <= ui->graphicsView->width(); x += 10){
scene->addLine(x,0,x,ui->graphicsView->height(),QPen(Qt::green));
}
for(int y = 0; y <= ui->graphicsView->height(); y += 10){
scene->addLine(0,y,ui->graphicsView->width(),y,QPen(Qt::green));
}
for(int x = 10; x <= ui->graphicsView->width(); x += 100){
scene->addLine(x,0,x,ui->graphicsView->height(),QPen(Qt::darkGreen));
}
for(int y = 10; y <= ui->graphicsView->height(); y += 100){
scene->addLine(0,y,ui->graphicsView->width(),y,QPen(Qt::darkGreen));
}
ui->graphicsView->setScene(scene);
connect(ui->pointButton, SIGNAL(clicked()), this, SLOT(drawPoint()));
connect(ui->lineButton, SIGNAL(clicked()), this, SLOT(drawLine()));
connect(ui->circleButton, SIGNAL(clicked()), this, SLOT(drawCircle()));
connect(ui->ellipseButton, SIGNAL(clicked()), this, SLOT(drawEllipse()));
connect(ui->arcButton, SIGNAL(clicked()),this, SLOT(drawArc()));
connect(ui->text,SIGNAL(clicked()),this,SLOT(drawText()));
connect(ui->actionPoints, SIGNAL(triggered()), this, SLOT(drawPoint()));
connect(ui->actionLine, SIGNAL(triggered()), this, SLOT(drawLine()));
connect(ui->actionCircle, SIGNAL(triggered()), this, SLOT(drawCircle()));
connect(ui->actionEllipse, SIGNAL(triggered()), this, SLOT(drawEllipse()));
}
void MainWindow::drawPoint(){
ui->graphicsView->setScene(scene);
item = new point;
scene->addItem(item);
qDebug() << "Point Created";
connect(item, SIGNAL(DrawFinished()), this, SLOT(drawPoint()));
}
void MainWindow::drawLine(){
ui->graphicsView->setScene(scene);
item1 = new line;
scene->addItem(item1);
qDebug() << "Line Created";
connect(item1, SIGNAL(DrawFinished()), this, SLOT(drawLine()));
}
void MainWindow::drawCircle(){
ui->graphicsView->setScene(scene);
item2 = new circle;
scene->addItem(item2);
qDebug() << "Circle Created";
connect(item2, SIGNAL(DrawFinished()), this, SLOT(drawCircle()));
}
void MainWindow::drawArc(){
ui->graphicsView->setScene(scene);
item4 = new arc;
scene->addItem(item4);
qDebug() << "Circle Created";
connect(item4, SIGNAL(DrawFinished()), this, SLOT(drawArc()));
}
void MainWindow::drawEllipse(){
ui->graphicsView->setScene(scene);
item3 = new ellipse;
scene->addItem(item3);
qDebug() << "Ellipse Created";
connect(item3, SIGNAL(DrawFinished()), this, SLOT(drawEllipse()));
}
void MainWindow::wheelEvent(QWheelEvent* event) {
ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
// Scale the view / do the zoom
double scaleFactor = 1.15;
if(event->delta() > 0) {
// Zoom in
ui->graphicsView->scale(scaleFactor, scaleFactor);
} else {
// Zooming out
ui->graphicsView->scale(1.0 / scaleFactor, 1.0 / scaleFactor);
}
}
void MainWindow::on_actionOpen_triggered()
{
QString filename=QFileDialog::getOpenFileName(
this,
tr("Open File"),
QString(),
tr("file Name(*.dwg|*.DWG|*.dxf)")
);
if (!filename.isEmpty()) {
QFile file(filename);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::critical(this,
tr("Error"), tr("Could not open file"));
return;
}
}
}
void MainWindow::on_actionSave_triggered()
{
QString filename=QFileDialog::getSaveFileName(
this,
tr("Save File"),
QString(),
tr("file Name(*.txt)")
);
if(!filename.isEmpty()) {
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
return;
} else {
QTextStream stream(&file);
QTextEdit *textEdit;
stream << textEdit->toPlainText();
stream.flush();
file.close();
}
}
}
void MainWindow::on_actionQuit_2_triggered(){
MainWindow *window;
window->close();
}
void MainWindow::drawText(){
ui->graphicsView->setScene(scene);
text *item5 = new text;
scene->addItem(item5);
qDebug() << "text created";
connect(item5, SIGNAL(DrawFinished()), this, SLOT(drawText()));
}
MainWindow::~MainWindow()
{
delete ui;
}
text.h
#ifndef TEXT_H
#define TEXT_H
#include <QGraphicsTextItem>
#include <QPen>
#include<QFocusEvent>
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsSceneMouseEvent>
#include<QGraphicsTextItem>
#include<QFont>
#include"mainwindow.h"
#include"ui_mainwindow.h"
class text:public QGraphicsTextItem
{
Q_OBJECT
public:
enum { Type = UserType + 3 };
enum Mode { InsertText };
void setFont(const QFont &font);
text(QGraphicsItem *parent = 0);
int type() const { return Type; }
public slots:
void setMode(Mode mode);
signals:
void lostFocus(text *item);
void selectedChange(QGraphicsItem *item);
void textInserted(QGraphicsTextItem *item);
void itemSelected(QGraphicsItem *item);
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
void focusOutEvent(QFocusEvent *event);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
private:
Mode myMode;
QFont myFont;};
#endif // TEXT_H
text.cpp
#include "text.h"
#include"mainwindow.h"
#include"ui_mainwindow.h"
text::text(QGraphicsItem *parent):QGraphicsTextItem(parent)
{
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemIsSelectable);
}
QVariant text::itemChange(GraphicsItemChange change,
const QVariant &value)
{
if (change == QGraphicsItem::ItemSelectedHasChanged)
emit selectedChange(this);
return value;
}
void text::focusOutEvent(QFocusEvent *event)
{
setTextInteractionFlags(Qt::NoTextInteraction);
emit lostFocus(this);
QGraphicsTextItem::focusOutEvent(event);
}
void text::setMode(Mode mode)
{
myMode = mode;
}
void text::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
if (textInteractionFlags() == Qt::NoTextInteraction)
setTextInteractionFlags(Qt::TextEditorInteraction);
QGraphicsTextItem::mouseDoubleClickEvent(event);
}
void text::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
if (mouseEvent->button() != Qt::LeftButton)
return;
switch(myMode){
case InsertText:
text *textItem;
textItem = new text();
// textItem->setFont(myFont);
textItem->setPlainText("hello");
textItem->setTextInteractionFlags(Qt::TextEditorInteraction);
textItem->setZValue(1000.0);
connect(textItem, SIGNAL(lostFocus(DiagramTextItem*)),
this, SLOT(editorLostFocus(DiagramTextItem*)));
connect(textItem, SIGNAL(selectedChange(QGraphicsItem*)),
this, SIGNAL(itemSelected(QGraphicsItem*)));
//addItem(textItem);
// textItem->setDefaultTextColor(myTextColor);
textItem->setPos(mouseEvent->scenePos());
emit textInserted(textItem);
//! [8] //! [9]
default:
;
}
// QGraphicsScene::mousePressEvent(mouseEvent);
}
Hm, if i am not mistaken, it does look like you are setting all kinds of properties of the text item, like Interaction-flags, z-value, color and so on -- everything but not the actual text. The text would be empty and therefore your QGraphicsTextItem will be invisible.
Use setPlainText(), setHtml() or setDocument() on your text item.
There are two places where text-items are created; one is in the mainwindow.cpp:
void MainWindow::drawText(){
ui->graphicsView->setScene(scene);
text *item5 = new text;
scene->addItem(item5);
qDebug() << "text created";
connect(item5, SIGNAL(DrawFinished()), this, SLOT(drawText()));
}
The text is created and added to the scene (with addItem()), but it does not have an actual content; set its content:
item5->setPlainText ("Mickey");
The second text-item is created from inside the text (which is a subclass of a QGraphicsTextItem) class itself:
void text::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
...
switch(myMode){
case InsertText:
text *textItem;
textItem = new text();
// textItem->setFont(myFont);
textItem->setPlainText("hello");
It is created correctly, and given a text, but not added to the scene. Add it to the scene, for instance by making it a child of the current text item:
textItem->setParentItem (this);