I have a separate qml that I call inside my main window. Inside this qml I want to show the following chart as it is. Is something like this possible? I will be grateful if you could help me. Thanks in advance.
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QUrl("qrc:/QmlSources/main.qml")));
return app.exec();
I can open the chart in a separate window with RealTimeMultiChart realTimeMultiChart; realTimeMultiChart.exec();
//
// Constructor
//
RealTimeMultiChart::RealTimeMultiChart(QWidget *parent) :
QDialog(parent)
{
//
// Set up the GUI
//
setFixedSize(772, 60 + 3 * chartHeight + xAxisHeight);
setWindowTitle("Real-Time MultiChart with Zoom/Scroll and Track Line");
QFrame *frame = new QFrame(this);
frame->setGeometry(4, 4, 120, height() - 8);
frame->setFrameShape(QFrame::StyledPanel);
// Chart Viewer
m_ChartViewer = new QChartViewer(this);
m_ChartViewer->setGeometry(128, 4, 640, 350);
connect(m_ChartViewer, SIGNAL(viewPortChanged()), SLOT(onViewPortChanged()));
connect(m_ChartViewer, SIGNAL(mouseMovePlotArea(QMouseEvent*)),
SLOT(onMouseMovePlotArea(QMouseEvent*)));
// Horizontal scroll bar
m_HScrollBar = new QScrollBar(Qt::Horizontal, this);
m_HScrollBar->setGeometry(128, height() - 18, 640, 18);
connect(m_HScrollBar, SIGNAL(valueChanged(int)), SLOT(onHScrollBarChanged(int)));
// Clear data arrays to Chart::NoValue
for (int i = 0; i < sampleSize; ++i)
m_timeStamps[i] = m_dataSeriesA[i] = m_dataSeriesB[i] = m_dataSeriesC[i] = Chart::NoValue;
m_currentIndex = 0;
// Set m_nextDataTime to the current time. It is used by the real time random number
// generator so it knows what timestamp should be used for the next data point.
m_nextDataTime = QDateTime::currentDateTime();
// Initially set the mouse to drag to scroll mode.
pointerPB->click();
// Enable mouse wheel zooming by setting the zoom ratio to 1.1 per wheel event
m_ChartViewer->setMouseWheelZoomRatio(1.1);
// Set up the data acquisition mechanism. In this demo, we just use a timer to get a
// sample every 250ms.
QTimer *dataRateTimer = new QTimer(this);
dataRateTimer->start(DataInterval);
connect(dataRateTimer, SIGNAL(timeout()), SLOT(onDataTimer()));
// Set up the chart update timer
m_ChartUpdateTimer = new QTimer(this);
connect(m_ChartUpdateTimer, SIGNAL(timeout()), SLOT(onChartUpdateTimer()));
// Can start now
m_ChartUpdateTimer->start();
}
graphic i want to add
Related
I simulated a dynamical device like mass spring damper.the QT Solves the equation of motion in Real Time and displays the output. I want to use an Qapplication object,to display Data and the outputs in "Real time". whole problem and display output is inside a loop.Everything is going well, but when the program reaches to command return a.exec() for display output,the GUI window Has come up and remain in the firest iteration." I expect don't gets stuck there and At each loop the program runs And at the end of loop update the GUI window in "Real time".
here is my code:
#include "QtWidgets/QApplication"
#include "QtWidgets/QGraphicsScene"
#include "QObject"
#include "QTimer"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Motion* ball = new Motion();
// create a scene
QGraphicsScene * scene = new QGraphicsScene();
QGraphicsRectItem* rect = new QGraphicsRectItem();
//show the view
view->show();
The Loop I talked about that.
for (int i = 0; i<int(j); i++)
{
Sleeper::msleep(50);
double t = time->getTime() + i*0.05;
states2 = world.openLoopSys;
for (int i=0; i<12; i++)
{
states1(i) = states2(i);
}
ball->run();
return a.exec(); // gets stuck there !!!
}
The Motion class is:
#include "motion.h"
Motion::Motion()
{
// create an item to put into the scene
setRect(0,0,20,30);
setPos(x(),y());
pos_x = 0;
pos_y = 0;
}
void Motion::run()
{
// connect
QTimer * timer = new QTimer();
connect(this,SIGNAL(timeout()),this,SLOT(move()));
timer->start(50);
}
void Motion::move()
{
setPos(x(),y()-5);
// setPos(0.01*pos_x,-0.01*pos_y);
}
How can I solve this problem?
I have a custom QGraphicsWidgets which paints a few items and also contains some children proxy widgets:
//Constructor adds a child proxy button
TestWidget::TestWidget(QJsonObject testDefinition, QJsonObject testStatus, QString parentSequenceID, QGraphicsWidget *parent):
m_parentID(parentSequenceID),
m_testStatus(testStatus),
m_testDefinition(testDefinition)
{
Q_UNUSED(parent);
m_name = m_testDefinition[displayNameStr].toString();
m_status = m_testStatus[resultStr].toObject()[resultStr].toString();
m_id = m_testDefinition[idStr].toString();
m_layout = new QGraphicsLinearLayout(Qt::Vertical, this);
//Add the pause/resume button
auto *proxyPauseAbortButton = new QGraphicsProxyWidget(this);
proxyPauseAbortButton->setWidget(new QPushButton(tr("Pause")));
proxyPauseAbortButton->moveBy(20, 40);
//Add the progress bar
auto * proxyTestProgressBar = new QGraphicsProxyWidget(this);
QProgressBar * testProgressBar = new QProgressBar();
testProgressBar->setOrientation(Qt::Horizontal);
testProgressBar->setRange(0, 100); // Let's say it goes from 0 to 100
testProgressBar->setValue(10); // With a current value of 10
proxyTestProgressBar->setWidget(testProgressBar);
proxyTestProgressBar->moveBy(20, 80);
//Add the html view
auto * proxyTestHtmlView = new QGraphicsProxyWidget(this);
QWebEngineView * testHtmlView = new QWebEngineView();
testHtmlView->load(QUrl(QStringLiteral("https://www.google.com/")));
proxyTestHtmlView->setWidget(testHtmlView);
proxyTestHtmlView->moveBy(20, 120);
}
//Paint function draws a border, shapes, and text
void TestWidget::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget /*= 0*/)
{
Q_UNUSED(widget);
Q_UNUSED(option);
QRectF frame(QPointF(0,0), geometry().size());
QGradientStops stops;
//Draw border
painter->drawRoundedRect(boundingRect(), 5.0, 5.0);
//Name of the test
painter->drawText(40, 20, m_name);
//Status of test
QFont font = painter->font() ;
font.setPointSize(14);
painter->setFont(font);
painter->drawText(600, 20, m_status);
//Arrow button
QPolygonF poly;
poly << QPointF(5, 10) << QPointF(25, 10) << QPointF(15, 20 )<< QPointF(5, 10);
painter->setBrush(Qt::black);
painter->drawPolygon(poly, Qt::OddEvenFill);
}
My question is how would you add each component (drawing/widget) to a layout, and at what time would it be appropriate to do so? The term widgets refers to the QPushButton, QProgressBar, and QWebEngineView. Drawings refers to the shapes and text in the paint function.
Here is a sketch of how I would like the custom widget to look like:
I would like to programmatically scroll a scene to the left / right, but I am not sure how to do that properly. Note that I do not want to have (visible) scroll bars.
I use a standard QGraphicsView + QGraphicsScene + QGraphicsItem setup. I have downsized it to the minimum, with one single QGraphicsItem (a QGraphicsRectItem) in the scene.
I have managed to achieve programmatic scrolling by setting my view like this:
// view setup
view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
and then, in another part of the code:
// programmatic scrolling
QScrollBar* const sb = view->horizontalScrollBar();
sb->setRange(0, 1000); // some values for experimenting
sb->setValue(sb->value() + 100 or -100); // some increment for experimenting
This works, but... scrolling through invisible scrollbars doesn't feel right.
I tried this more straightforward approach:
// programmatic scrolling - doesn't quite work
view->viewport()->scroll(100 or -100, 0); // some increment for experimenting
This code does scroll, but when the rectangle goes off the left edge of the view, and I reverse the scrolling direction (increment changed from 100 to -100 in the call to scroll()), the uncovered part of the rectangle is not repainted. The reason is that QGraphicsRectItem::paint() is not called in that case (it is called when using the scrollbar method).
So, is there a way to get viewport()->scroll() work? Or some other simple way to achieve programmatic scrolling? Or is the artificial scrollbar method just the way to go?
Moving the view assumes that it's smaller than its scene. If they're the same size, it won't move.
QGraphicsView can be set to centerOn any position in scene coordinates. Use a timer to call centerOn to move the view one frame at a time.
Here's a working example: -
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QTimer>
class MyView : public QGraphicsView
{
private:
public:
MyView(QGraphicsScene* pScene)
: QGraphicsView(pScene, NULL)
{}
void AnimateBy(int x)
{
float updateFrequency = (1000/30.0); // ~30 frames per second
QPointF currScenePos = sceneRect().center();
int curX = currScenePos.x();
int endPos = curX + x;
int distanceToAnimate = (endPos - curX);
// speed = dist / time
float updatePosInterval = (float)distanceToAnimate / updateFrequency;
printf("updatePosInterval: %f \n", updatePosInterval);
static float newXPos = sceneRect().center().x();
QTimer* pTimer = new QTimer;
QObject::connect(pTimer, &QTimer::timeout, [=](){
newXPos += updatePosInterval;
centerOn(newXPos, sceneRect().center().y());
// check for end position or time, then....
if(newXPos >= endPos)
{
pTimer->stop();
pTimer->deleteLater();
}
});
pTimer->start(updateFrequency);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene(0, 0, 10000, 20000);
MyView* view = new MyView(&scene);
QGraphicsRectItem* pRect = new QGraphicsRectItem(0, 0, 100, 100);
pRect->setPos(scene.width()/2, scene.height()/2);
scene.addItem(pRect);
// timer to wait for the window to appear, before starting to move
QTimer* pTimer = new QTimer;
pTimer->setSingleShot(true);
QObject::connect(pTimer, &QTimer::timeout,[=](){
view->centerOn(pRect); // centre on the rectangle
view->AnimateBy(100);
pTimer->deleteLater();
});
pTimer->start(1000);
view->show();
return a.exec();
}
So, we create the animation by moving the view frame-by-frame using the call to centerOn.
For simplicity, the code just deals with moving in one axis. To move in 2 axis, use 2D vector maths to calculate the interval position.
Try to change the view transformation with the QGraphicsView::translate() or QGraphicsView::setTransform().
But keep in mind that you can't move the viewport "outside" the scene, so make sure that your scene rectangle is large enough.
If I got your question correctly, there is a dojo classes library with such class as PanWebView that allow QWebView to scroll smoothly with mouse without any scrollbars. Take a look at sources. It supports panning and can be suitable for mobile apps, but maybe it'll help you too.
PanWebView class looks like this
#include <QWebView>
#include <QWebFrame>
#include <QMouseEvent>
#include <QApplication>
class PanWebView : public QWebView
{
Q_OBJECT
private:
bool pressed;
bool scrolling;
QPoint position;
QPoint offset;
QList<QEvent*> ignored;
public:
PanWebView(QWidget *parent = 0): QWebView(parent), pressed(false), scrolling(false) {
QWebFrame *frame = page()->mainFrame();
frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
}
protected:
void mousePressEvent(QMouseEvent *mouseEvent) {
if (ignored.removeAll(mouseEvent))
return QWebView::mousePressEvent(mouseEvent);
if (!pressed && !scrolling && mouseEvent->modifiers() == Qt::NoModifier)
if (mouseEvent->buttons() == Qt::LeftButton) {
pressed = true;
scrolling = false;
position = mouseEvent->pos();
QWebFrame *frame = page()->mainFrame();
int x = frame->evaluateJavaScript("window.scrollX").toInt();
int y = frame->evaluateJavaScript("window.scrollY").toInt();
offset = QPoint(x, y);
QApplication::setOverrideCursor(Qt::OpenHandCursor);
return;
}
return QWebView::mousePressEvent(mouseEvent);
}
void mouseReleaseEvent(QMouseEvent *mouseEvent) {
if (ignored.removeAll(mouseEvent))
return QWebView::mouseReleaseEvent(mouseEvent);
if (scrolling) {
pressed = false;
scrolling = false;
QApplication::restoreOverrideCursor();
return;
}
if (pressed) {
pressed = false;
scrolling = false;
QMouseEvent *event1 = new QMouseEvent(QEvent::MouseButtonPress,
position, Qt::LeftButton,
Qt::LeftButton, Qt::NoModifier);
QMouseEvent *event2 = new QMouseEvent(*mouseEvent);
ignored << event1;
ignored << event2;
QApplication::postEvent(this, event1);
QApplication::postEvent(this, event2);
QApplication::restoreOverrideCursor();
return;
}
return QWebView::mouseReleaseEvent(mouseEvent);
}
void mouseMoveEvent(QMouseEvent *mouseEvent) {
if (scrolling) {
QPoint delta = mouseEvent->pos() - position;
QPoint p = offset - delta;
QWebFrame *frame = page()->mainFrame();
frame- >evaluateJavaScript(QString("window.scrollTo(%1,%2);").arg(p.x()).arg(p.y()));
return;
}
if (pressed) {
pressed = false;
scrolling = true;
return;
}
return QWebView::mouseMoveEvent(mouseEvent);
}
};
And usage:
PanWebView web;
web.setUrl(QUrl("http://news.google.com"));
web.setWindowTitle("Web View - use mouse to drag and pan around");
web.show();
Also did you check this and this topics? I think it can be usefull.
I am attaching some parts of my code,
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "colorrecognition.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//this->setStyleSheet("background-color: black;"); // set the background
//capture = 0;
// frame = 0;
//interface
//tabWidget = new QTabWidget;
//start capturing a video
//capture = cvCaptureFromCAM(0);
//capture = cvCaptureFromAVI("videoExample.avi");
//frame = cvQueryFrame(capture);
tabWidget = new QTabWidget(ui->centralWidget);
tabWidget->setObjectName(QString::fromUtf8("tabWidget"));
tabWidget->setGeometry(QRect(20, 0, 801, 571));
tabWidget->addTab(new ColorRecognition(), tr("Color Recognition"));
Contour contour1;
}
MainWindow::~MainWindow()
{
delete ui;
}
//========================================================
ColorRecognition::ColorRecognition(QWidget *parent){
storage1 = cvCreateMemStorage(0);
storage2 = cvCreateMemStorage(0);
/*QFrame* frame1 = new QFrame(this);
frame1->setObjectName(QString::fromUtf8("frame1"));
frame1->setGeometry(QRect(20, 20, 761, 501));
frame1->setFrameShape(QFrame::StyledPanel);
frame1->setFrameShadow(QFrame::Raised);*/
//start capturing a video
capture = cvCaptureFromCAM(0);
//capture = cvCaptureFromAVI("videoExample.avi");
//print an error message in case you can't grab the frame
if (!cvGrabFrame(capture)) { // capture a frame
printf("couldn't grab a frame");
}
//First screen --- Color Identification ---
//QObject::connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(color_Recoginition()));
//set timer for 50ms intervals
QTimer* m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(color()));
m_timer->start(100);
}
void ColorRecognition::paintEvent(QPaintEvent* e) {
QPainter painter(this);
painter.drawImage(10,10, qt_img);
}
void ColorRecognition::color(){
frame = cvQueryFrame(capture);
//CvSize imageSize = cvSize(frame->width,frame->height);
//IplImage* resultImage = cvCreateImage(imageSize, 8, 3);
//qDebug("Befroe manipulation");
cvCvtColor(frame, frame, CV_BGR2RGB);
//CvSize imageSize = cvSize(frame->width, frame->height);
IplImage **thresholdedImage = contour1.GetThresholdedImage(frame);
//insert the resulted frame from the above function into the find contour function
cvFindContours(thresholdedImage[0], storage1, &contours1, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
cvFindContours(thresholdedImage[1], storage2, &contours2, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
contour1.drawContour(contours1, storage1, frame, CV_RGB(255, 0, 0));
contour1.drawContour(contours2, storage2, frame, CV_RGB(0, 255, 0));
qt_img = QImage((unsigned char *)frame->imageDataOrigin,frame->width,frame->height,QImage::Format_RGB888);
//release temp memory
//cvReleaseMemStorage(&storage1);
//cvReleaseMemStorage(&storage2);
//cvReleaseMemStorage(&contours1->storage); // check if that is correct
//cvReleaseMemStorage(&contours2->storage);*/
//resultImage = contour1.colorIdentification(frame);
//cvCvtColor(resultImage, resultImage, CV_BGR2RGB);
//qDebug("After manipulation");
this->update();
}
the problem is that when I run this code I don't get anything on the screen, however when I run the code out Qt (only in OpenCV) the code was working with no problems
Can anyone know what is the deal ?
so I figured out what went wrong in my code, it is really a silly mistake -->
I was passing the frame image immediately to the function I have done
frame = cvQueryFrame(capture);
so what solved my problem was copying the frame image into an IplImage and then it worked perfectly -->
cvCopy(frame, resultImage);
Iam a absolute Beginner in QT..
i am trying to create window that has only text and one push button when you press it, you will get another window that has menu for program ..
but Unfortunately, i didn't know how can i create new window and connect it with main window!
so, i need to helping you
Here is a sample of main.cpp that do exactly that (you will have to modify the new window though).
#include <QtGui>
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
QWidget *firstWindow = new QWidget();
QLabel *text = new QLabel("Here is some text one the first window.");
QPushButton *button = new QPushButton("Button on the first window that display the other window");
QBoxLayout *layout = new QVBoxLayout();
layout->addWidget(text);
layout->addWidget(button);
firstWindow->setLayout(layout);
QWidget *secondWindow = new QWidget();
// add some things on the second window
// on button click, close the first window and show the second one
connect(button, SIGNAL(clicked(bool)), secondWindow, SLOT(show()));
connect(button, SIGNAL(clicked(bool)), firstWindow, SLOT(close()));
// display the first window at the start of the application.
firstWindow->show();
return app.exec();
}