displaying instance of class in tabs in Qt - qt

Im trying to display 3 forms(calender, history, statistics) which has 3 classes into a MainWindow Class which has three tabs created using the designer. When the application runs for the first time, it displays the history form into the tab. But when it is being run the second time, the form is displayed over the tabs that they are not visible.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
CalenderForm *pCal = new CalenderForm();
lay = new QVBoxLayout(ui->tab);
lay->addWidget(pCal);
connect(ui->tabWidget,SIGNAL(currentChanged(int)),this,SLOT(a(int)));
}
void MainWindow::a(int index)
{
switch(index)
{
case 0:
callCal();
break;
case 1:
callHist();
break;
default:
break;
}
}
void MainWindow::callHist()
{
HistoryForm *pHis = new HistoryForm();
pHis->DisplayHistory();
pHis->show();
lay2 = new QVBoxLayout(ui->tab_2);
lay2->addWidget(pHis);
}

Everytime you switch the tab index, you create a new form. I am not sure if this is the cause of your problem, but it definitely is a problem.
You should ensure the forms are only created once. For example you may create them in the constructor of MainWindow and store pointers to them in member variables. You should also already assign any required layouts there.
When you switch the index, you just call the DisplayHistory() or equivalent method.
PS: If you still want to understand your code next year, you should probably find a more speaking name than "a" for that slot ;-)
[Edit]
Here is a sample header and cpp file. Be adviced that it might not compile as is and you might have to do some adjustments, but I wanna show you the general idea.
Header file
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui/QMainWindow>
// forward declarations
class CalendarForm;
class HistoryForm;
class StatisticsForm; // or whatever your 3rd form is called
class MainWindow : QMainWindow
{
public:
MainWindow(QWidget *parent);
~MainWindow();
private slots:
void currentTabChanged( int tabIndex );
private:
// these are called "member variables" as they are a member of a class
// Sample naming convention: m_ for members, p for Pointer, you can use
// whatever you prefer, as long as you use it consistently.
CalendarForm* m_pCalendar;
HistoryForm* m_pHistory;
StatisticsForm* m_pStatistics;
// not sure about this part but it is generated by Qt anyway
Ui::MainWindowClass* ui;
};
// not sure about this part but it is generated by Qt anyway
namespace Ui {
class MainWindowClass;
}
#endif // MAINWINDOW_H
CPP File:
// these includes should be present already anyway
#include "MainWindow.h"
#include "ui_mainwindow.h"
#include "CalendarForm.h"
#include "HistoryForm.h"
#include "StatisticsForm.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
m_pCalendar = new CalendarForm();
m_pHistory = new HistoryForm();
m_pStatistics = new StatisticsForm();
ui->tabWidget->addTab( m_pCalendar );
ui->tabWidget->addTab( m_pHistory );
ui->tabWidget->addTab( m_pStatistics );
connect( ui->tabWidget, SIGNAL( currentChanged ( int ) ),
this , SLOT ( currentTabChanged( int ) );
}
MainWindow::~MainWindow()
{
delete m_pCalendar;
delete m_pHistory;
delete m_pStatistics;
}
void MainWindow::currentTabChanged( int tabIndex )
{
switch( tabIndex )
{
case 0:
// update calculator if necessary
break;
case 1:
// Assumption: You need to update the view every time you activate
// the tab. If this assumption is wrong, you don't need this slot
// at all, just call the method once in the constructor.
m_pHistory->DisplayHistory();
break;
case 2:
// update statistics if necessary
break;
default:
break;
}
}

Related

Properly deleting QGraphicsScene

I created a small prototype which contains a QGraphicsView that I bind to a GraphicsScene to which I can add or remove QGraphicsTextItem. Here is the the cpp file that does the job
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGraphicsScene>
#include <QGraphicsTextItem>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QGraphicsScene* scene = new QGraphicsScene();
ui->graphicsView->setScene(scene);
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(addGraphicsItem()));
connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(removeGraphicsItem()));
}
MainWindow::~MainWindow()
{
auto scene = ui->graphicsView->scene();
ui->graphicsView->setScene(nullptr);
delete scene;
delete ui;
}
void MainWindow::addGraphicsItem()
{
QGraphicsTextItem* item = new QGraphicsTextItem("jgfkdljkdj");
_items.push_back(item);
ui->graphicsView->scene()->addItem(_items.back());
}
void MainWindow::removeGraphicsItem()
{
auto item = _items.back();
ui->graphicsView->scene()->removeItem(item);
_items.erase(_items.end()-1);
delete item;
}
I have trouble to understand how to manage safely my memory when creating/deleting the scene and/or its underlying items. Reading many posts about this such as this one, I came up to the aformentionned code but I have the feeling that it is overkilling code and that Qt might do the job without it. Is that really the way to do especially in MainWindow::removeGraphicsItem slot when removing and deleting one item from the scene and MainWindow::~MainWindow destructor when deleting the scene ?
The simplest thing to do is to let the language and the framework manage the memory for you.
Store QGraphicsScene by value, and leverage the fact that the scene is a resource manager, tightly coupled to the items. It manages the lifetime of the items and guarantees that no items will outlive the scene, i.e. it will take care of disposing of any items that weren't disposed before its destructor runs.
To remove an item from the scene, or from a parent item, simply delete it. The item will inform the scene and any parents that it's about to vanish, and the scene will remove it from its list of items. That's how QObject memory management works as well.
You may also wish to use QGraphicsScene::items or QGraphicsItemGroup::childItems instead of managing the object list manually. Using a manual list requires paying attention to synchronizing the list's contents with object lifetimes. A scene or an item group does it automatically.
If were to write it, I'd do it as follows. I also show how to mix different item lifetimes in a scene, and how to hold items by value.
// mainwindow.h
#pragma once
#include "ui_mainwindow.h"
#include <QGraphicsScene>
class MainWindow : public QMainWindow {
Q_OBJECT
Ui::MainWindow ui;
QGraphicsScene m_scene;
QGraphicsTextItem m_text{tr("foo")};
QGraphicsItemGroup m_dynamicItems;
template <typename T, typename ...Ar> T* newItem(Ar&&... args);
public:
MainWindow(QWidget *parent = {});
Q_SLOT void addItem();
Q_SLOT void removeItem();
Q_SLOT void removeAllItems();
};
// mainwindow.cpp
#include "mainwindow.h"
#include <utility>
template <typename T, typename ...Ar>
T* MainWindow::newItem(Ar&&... args) {
return new T{&this->m_dynamicItems, std::forward<Ar>(args)...};
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
ui.setupUi(this);
ui.graphicsView->setScene(&m_scene);
m_scene.addItem(&m_text);
m_scene.addItem(&m_dynamicItems);
auto const clicked = &QPushButton::clicked;
connect(ui.pushButton, clicked, this, &MainWindow::addItem);
connect(ui.pushButton2, clicked, this, &MainWindow::removeItem);
}
void MainWindow::addItem() {
newItem<QGraphicsTextItem>(tr("jfslkdfjd"));
}
void MainWindow::removeItem() {
auto const &items = std::as_const(m_dynamicItems.childItems());
if (!items.isEmpty())
delete items.back();
}
void MainWindow::removeAllItems() {
for (auto *item : std::as_const(m_dynamicItems.childItems()))
delete item;
// or (deprecated but you may run into such code)
qDeleteAll(std::as_const(m_dynamicItems.childItems()));
}

QT push button / stop button

I have a push button that I'd like to change to a stop button when clicked. Currently the button's text says "auto fire", it runs an endless loop and it's text changes to "stop auto fire" when clicked. My problem is breaking the endless loop by clicking/pressing this button again after the text changes.
Code so far:
void Cpp_Fire::on_auto_fire_clicked()
{
while(true)
{
ui->auto_fire->setText("Stop Auto Fire");
on_manual_fire_clicked();
}
}
I tried inserting a different slot into the loop above that runs when after the button is pressed (it runs when the button is released to be precise) but I couldn't get it to work.
I know this could be done with signals/slots and a separate stop button but I'm unfamiliar with that method and I prefer the method I described.
The problem with your endless loop is that nothing else gets a chance to work.
One approach you could use is to use a QTimer with a short interval to call the on_manual_fire_clicked() method, then have the on_auto_fire_clicked() method be responsible for changing the text on the button and enabling / disabling the timer.
The ui should get enough time to respond to clicks etc if you do it that way.
edit:
For more info on using QTimer have a look at this page:
How to use QTimer
or this tutorial:
http://www.bogotobogo.com/Qt/Qt5_QTimer.php
Here's some code:
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_clicked();
void timerslot();
private:
Ui::MainWindow *ui;
QTimer* myTimer;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QTimer>
#include<QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
myTimer = new QTimer(this);
myTimer->setInterval(500);
myTimer->setSingleShot(false);
connect(myTimer, SIGNAL(timeout()), this, SLOT(timerslot()));
myTimer->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::timerslot()
{
qDebug() << "timeslot";
}
void MainWindow::on_pushButton_clicked()
{
if ( this->myTimer->isActive() == true ) {
this->myTimer->stop();
ui->pushButton->setText("Start");
} else {
this->myTimer->start(500);
ui->pushButton->setText("Stop");
}
}
I hope you get the idea and can convert it to your needs.
I fully agree Michael's answer.
This will also affect the repaint! (Try to put some windows over your application, while in endless-loop: you should see repaint problems).
Don't use endless-loops, specially not within slots!
Try QTimer, or move object to a QThread.
While in such loop: Give GUI-Thread some time. You can call QCoreApplication::processEvents().. But be careful with this.
A simple (still poor) solution with QTimer could be:
(I found, Michael entered an example in his answer. - Use it.).
//have a QTimer 'timer' in the class, and a connect signal
//timer.timeout() to 'onSingleShotFired()'
void Cpp_Fire::on_auto_fire_clicked()
{
if ( ui->auto_fire->text() == "Stop Auto Fire" )
{
timer.stop();
ui->auto_fire->setText("Start Auto Fire");
}
else
{
//MSEC_AUTOFIRE_DELAY is the delay between the autofire-shots
timer.start( MSEC_AUTOFIRE_DELAY );
ui->auto_fire->setText("Stop Auto Fire");
}
}

QModelIndexList from a QTreeView giving debug assertion

In one of my projects on Qt, I have this requirement of selecting multiple items from a folder like view (tree-view), and populate the selected items in another widget. To display available items for multi-selection, I'm using a QTreeView, and populating element hierarchy like the following
m_StandardModel = new QStandardItemModel ;
QStandardItem *rootNode = m_StandardModel->invisibleRootItem();
//defining a couple of items
QStandardItem *item1 = new QStandardItem(tr("ITEM1"));
QStandardItem *item2 = new QStandardItem(tr("ITEM2"));
QStandardItem *item3 = new QStandardItem(tr("ITEM3"));
QStandardItem *item4 = new QStandardItem(tr("ITEM4"));
rootNode->appendRow(item1 );
rootNode->appendRow(item2 );
rootNode->appendRow(item3 );
rootNode->appendRow(item4 );
//register the model
ui->treeView->setModel(m_StandardModel);
ui->treeView->expandAll();
//enabling multiselection behaviour
QItemSelectionModel *selectionModel= ui->treeView->selectionModel();
ui->treeView->setSelectionMode(QAbstractItemView::MultiSelection);
Everything's fine till here. I'm able to display my items in tree-view and also able to multiselect items. The problem occurs when I'm trying to use these multiple selected items from tree view.
In my UI, I have connected a button's clicked() signal to my slot, which handles the iteration and manipulation of selected items. Here's the function that's being called:
//User selects a number of features listed on the left pane and clicks this button to disable them
void MainWindow::on_pushButton_2_clicked()
{
QModelIndexList selectedItems = ui->treeView->selectionModel()->selectedIndexes();
QStringList items;
foreach(QModelIndex index, selectedItems)
{
QStandardItemModel* itemModel = dynamic_cast<QStandardItemModel*>(ui->treeView->model());
if(itemModel)
{
QStandardItem* item = itemModel->itemFromIndex(index);
items<< item->data().toString();
}
}
}
Debugging till the function end is perfect. But as soon as I exit this function (shown above), I get a DEBUG ASSERTION !! like the following
HEAP[myprog.exe]: Invalid address specified to RtlValidateHeap( 00390000, 01946798 )
The call stack is showing that this assertion is reached because of destruction of local QModelIndexList that I've created in the function.
Following is the call stack at the time of debug assertion:
Any idea, what I might be missing? I have tried a number of times, but yet unable to figure out the real problem. Is there a better way of doing what is being done here?
I'm using QT 4.8.4, and am building/debugging my application in DEBUG configuration on Windows 7.
I tried your code in a Windows application and I don't see your behaviour, maybe you have extra code in other part of the program that generates that behaviour. The code I tested is the following (I only modified the way to get the data, ot get the display role item->data(Qt::DisplayRole).toString()):
The cpp file:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_StandardModel = new QStandardItemModel ;
QStandardItem *rootNode = m_StandardModel->invisibleRootItem();
//defining a couple of items
QStandardItem *item1 = new QStandardItem(tr("ITEM1"));
QStandardItem *item2 = new QStandardItem(tr("ITEM2"));
QStandardItem *item3 = new QStandardItem(tr("ITEM3"));
QStandardItem *item4 = new QStandardItem(tr("ITEM4"));
rootNode->appendRow(item1 );
rootNode->appendRow(item2 );
rootNode->appendRow(item3 );
rootNode->appendRow(item4 );
//register the model
ui->treeView->setModel(m_StandardModel);
ui->treeView->expandAll();
//enabling multiselection behaviour
QItemSelectionModel *selectionModel= ui->treeView->selectionModel();
ui->treeView->setSelectionMode(QAbstractItemView::MultiSelection);
connect(ui->pushButton, SIGNAL(clicked()),
this, SLOT(on_pushButton_clicked()) );
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked(){
QModelIndexList selectedItems = ui->treeView->selectionModel()->selectedIndexes();
QStringList items;
foreach(QModelIndex index, selectedItems)
{
QStandardItemModel* itemModel = dynamic_cast<QStandardItemModel*>(ui->treeView->model());
if(itemModel)
{
QStandardItem* item = itemModel->itemFromIndex(index);
items << item->data(Qt::DisplayRole).toString();
}
}
}
The header file:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QStandardItemModel * m_StandardModel ;
};
#endif // MAINWINDOW_H
Maybe you can publish the hole source code to see the behaviour you are having.

Qt debug pointer not following expected flow in 2nd and successive iterations

I want to display a "generating image..." kind of modal dialog, other than the main GUI. This "generating image..." dialog should be temporary, and be displayed and disappear without user intervention.
For displaying this dialog, the Qt code should check for existence of a .txt file in a specific location in the PC's hard disk. If the .txt file exists, then the dialog should pop-up.
For making this dialog disappear, the Qt code should check whether that .txt file contains the string "OK" in the first line. The dialog should disappear only when this "OK" is found, until then it should continue to display "generating image..."
A good way to do this is to use signal slot mechanism. I would like to know, what functions should be used as SIGNALS in both the cases, of displaying and removing the dialog.
So far, I could manage a simple code, illustrating a "generating image..." using signal slot mechanism, but with setValue() and pressing a push button(i.e. involving user intervention), and not with the checking of .txt file or the "OK" string inside that .txt file(user non-intervention).
Please advise me, whether my logic can be implemented? If yes, how? Also, what SIGNALs should be used?
************************UPDATED SECTION(as of Feb 24th '14):****************************************************
I have revised the code according to Dmitry Sazonov's suggestions. I am able to display the loading GIF whenever a new file is created/deleted in a designated directory. Now I want to close this loading qDialog, when the usbResponse.txt file has "ok" inside it. I tried using signal slot, to implement hide(), but could not get it.
I do not get errors, but the qDialog window does not close as expected. I tried both, secDialog.close() and secDialog.hide(), but the window didn't close. Perhaps because the secDialog object is not the same in both the SLOTs. So I also made secDialog, a global object, but I received an error as follows:-
QWidget: Must construct a QApplication before a QWidget
I looked it up: https://qt-project.org/forums/viewthread/12838
Changed the build modes, accordingly, but that didn't help either. Please tell me how do I close my qDialogs, when I find the "ok" in usbResponse.txt file.
************************UPDATED SECTION(as of Mar 14th '14):****************************************************
I could close the qDialog containing the GIF using hide(). I have done a total overhaul of the code. As mentioned above, the qDialog containing the GIF should appear whenever a text file called usbResponse.txt exists at a designated location. Also taking #Dmitry Sazonov's advice, I am able to close the GIF whenever that txt file i.e. usbResponse.txt is modified, using FileSystemWatcher.
I'm continuously scanning for the existence of the .txt using threads. When I find the file, I display the loading GIF. When the .txt is modified the GIF should disappear. This works fine for the first iteration, i.e. when
(the following are observations after debugging)
the usbResponse.txt exists => GIF is displayed
when usbResponse.txt is modified => GIF is hidden & the .txt is deleted.
THe problem, in next iteraiton,(i.e. all iterations after the first)
the usbResponse.txt is created => the GIF is displayed.
when usbResponse.txt is modified, the debug pointer continues to remain in
afterFileHasBeenFound()
whereas it should have gone in
closeModified(const QString &str)
What is my mistake here?
Here is my code:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFile>
#include <QDebug>
#include <QFileSystemWatcher>
#include "dialog.h"
#include "mythread.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void afterFileHasBeenFound();
void closeModified(const QString &str);
private slots:
private:
Ui::MainWindow *ui;
Dialog *pDialog;
MyThread *mThread;
};
#endif // MAINWINDOW_H
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QMovie>
#include <QLabel>
#define GIF_PATH "E:\\QT1\\timeStampPopUp\\timeStampPopUp\\loading.gif"
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
void displayLoadingGif();
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QtCore>
#include <QDebug>
#define FILE_PATH "E:\\QT1\\dialogClose2\\dialogClose2\\usbResponse.txt"
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
void run();
QString name;
int exec();
void checkFile();
signals:
void testSignal(QString message);
void fileFoundDisplayGif();
public slots:
};
#endif // MYTHREAD_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
displayLoadingGif();
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::displayLoadingGif()
{
QMovie *pMovie = new QMovie(GIF_PATH);
ui->loadingGifLabel->setMovie(pMovie);
pMovie->start();
}
mythread.cpp
#include "mythread.h"
MyThread::MyThread(QObject *parent) :
QThread(parent)
{
}
void MyThread::run()
{
exec();
}
int MyThread::exec()
{
while(1)
{
checkFile();
emit(testSignal("hello world!!"));
sleep(1);
}
}
void MyThread::checkFile()
{
QFile file(FILE_PATH);
if(file.exists())
{
qDebug()<<"exists";
emit(fileFoundDisplayGif());
}
else
qDebug()<<"doesn't exist";
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
mThread = new MyThread(this);
mThread->name = "mThread";
connect(mThread, SIGNAL(fileFoundDisplayGif()), this, SLOT(afterFileHasBeenFound()), Qt::QueuedConnection);
mThread->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::afterFileHasBeenFound()
{
if(pDialog != NULL)
return;
pDialog = new Dialog();
pDialog->setModal(true);
pDialog->show();
}
void MainWindow::closeModified(const QString &str)
{
Q_UNUSED(str)
if(pDialog != NULL)
{
pDialog->hide();
}
QFile file(FILE_PATH);
file.remove();
pDialog = NULL;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFileSystemWatcher fileWatcher;
fileWatcher.addPath(FILE_PATH);
QStringList fileList = fileWatcher.files();
Q_FOREACH(QString file, fileList)
qDebug() << "File name " << file;
MainWindow* mc = new MainWindow;
QObject::connect(&fileWatcher, SIGNAL(fileChanged(QString)), mc, SLOT(closeModified(QString)));
mc->show();
return a.exec();
}
Do not use timers for checking file. Use QFileSystemWatcher for traking file modifications.
Implement a slot that will check file content on modification. And call hide() method, when your "OK" text appeared.
IMHO: your solution is to messy. There are a lot of other syncronization mechanisms between processed. Can you modify code of tool that generates image? Should it really work as another process?

Qt call to update not triggering call to paintEvent() while drawing data from serial port to scrollArea

I am newbie to Qt 5.1.0. My problem with Qt is showed directly as follows. Data from serial port is received by readdata(), then call the draw() in mainwindow.cpp to deliver the data to newpaint() in paint.cpp. Two classes are created in this project:class mainwindow is mainly responsible for receiving data from serial port,class paint is for drawing the data (actually the data is coordinates of a mathematical function) on the scroll area widget which is on the mainwindow.
But in paint.cpp, paintevent is not invoked by update().UpdateEnabled() returns true depicting that the problem doesn't exist in the use of update().
Main part is pasted below.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
QPainterPath linepath;
linepath.moveTo(0,0);
ui->setupUi(this);
paintwiget=new paint(linepath,ui->scrollArea);
ui->scrollArea->setWidget(paintwiget);
paintwiget->show();
ui->closeserial->setEnabled(false);
ui->sendData->setEnabled(false);
serial=new QSerialPort(this);
connect(serial,SIGNAL(readyRead()),this,SLOT(readData()));
}
void paint::newpaint(qreal *aa1, int len1)
{
if (!aa.isEmpty())
aa.clear();
int i;
for (i=0;i<len1;i++)
aa.append(aa1[i]);
// qDebug()<<aa.size();
//qDebug()<<"aa[0:3]"<<aa[0]<<" "<<aa[1]<<" "<<aa[2]<<" "<<aa[3];
len=len1;
// this->setVisible(true);
qDebug()<<this->isVisible();//now returns true
this->update();
//qDebug()<<"okla";
}
void paint::paintEvent(QPaintEvent *)
{
qDebug()<<"ok~~";
QPointF currentpoi;
QPainter painter(this);
int ii=0;
qDebug()<<len;
for (ii=0;ii<len/2;ii++)
{
currentpoi=path.currentPosition();
qDebug()<<"currentpoi"<<currentpoi;
path.moveTo(currentpoi);
path.lineTo(aa[2*ii],aa[2*ii+1]);
// painter.setRenderHint(QPainter::Antialiasing);
painter.drawPath(path);
}
}
paint.h
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QTabWidget>
//#include <mainwindow.h>
class paint : public QWidget
{
public:
explicit paint(QPainterPath &path,QWidget *parent=0);
void newpaint(qreal *,int);
QVector <qreal>aa;
int len;
QWidget *parent;
private:
QPointF point;
QPainterPath path;
protected:
void paintEvent(QPaintEvent *event);
};
Hard to say for sure that this is the only issues you are facing, but there are at least three issues:
Issue 1
The following code tells me that you have a member of MainWindow called paint * paintwiget:
void MainWindow::draw(qreal *aa,int len)
{
// ...
paintwiget->newpaint(dist,len);
}
Then, this code tells me that you are creating a new temporary variable of the same name:
MainWindow::MainWindow(QWidget *parent)
{
// ...
paint *paintwiget=new paint(linepath,ui->scrollArea->viewport());
}
The compiler should have probably given you a warning for this. Replace this line by:
paintwiget = new paint(linepath,ui->scrollArea->viewport());
(notice the lack of paint *), and tell me if this solves the problem.
Issue 2
You have to change this:
void paint::newpaint(qreal *aa, int len)
{
// ...
aa[i]=aa[i];
len=len;
}
by this:
void paint::newpaint(qreal *aa_new, int len_new)
{
// ...
aa[i]=aa_new[i];
len=len_new;
}
Otherwise, your aa[i]=aa[i] has no effect: it replaces the parameter of the method by itself, instead of replacing your member by the parameter of the method. Using a parameter with the same name than a member "hides" the member: you can't access it anymore, either at the left hand side or the right hand side of an assignment.
Issue 3
I'm not quite sure what you are doing with scrollArea->viewport() in the constructor of paint, but something tells me you are doing it wrong. The constructor of paint should NOT use it, but instead, you should do:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPainterPath linepath;
paintwiget = new paint(linepath); // Do NOT pass viewport in parameter
ui->scrollArea->setWidget(paintwiget);
paintwiget->show();
// ...
}

Resources