qt c++ QChart->setGeometry does not work in MainWindow - c++

I created an object with a QChart inside and a MainWindow with 2 QPushButton, when I try to display my QChart, it takes all window. If I want to resize QChart everything works but if I try to move it nothing work (with setGeometry or with setContentMargin).
main.cpp
#include <QApplication>
#include "Mainwindow.h"
#include "MainChart.h"
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MainWindow w(1920, 1080);
MainChart chart;
chart.setGeometry(250,0,1670,1080); // >> KO
w.setCentralWidget(chart.get_view());
// w.centralWidget()->setMaximumSize(1670, 1080); >> OK
// w.centralWidget()->setContentsMargins(250,0,0,0); >> KO
w.show();
return app.exec();
}
Other files, I think that won't be useful but if need:
MainWindow.cpp
#include <QMainWindow>
#include <QWidget>
#include <QtGui>
#include <QAction>
#include <Qt>
#include <QKeySequence>
#include <QtCore>
#include <iostream>
#include "Mainwindow.h"
MainWindow::MainWindow(int _width, int _height, QMainWindow *parent)
: width(_width), height(_height), QMainWindow(parent)
{
this->setStyleSheet("MainWindow {background-color: rgb(40,40,40);}");
this->setWindowFlags( Qt::CustomizeWindowHint );
this->showFullScreen();
this->setFixedSize(width, height);
configure_new_button();
configure_exit_button();
configure_escape();
}
MainWindow::~MainWindow()
{
free(exit_btn);
free(new_btn);
free(escape);
}
void MainWindow::configure_exit_button()
{
exit_btn = new QPushButton(this);
exit_btn->connect(exit_btn, SIGNAL(clicked()),this, SLOT(exit()));
exit_btn->setGeometry(0, height - 100, 100, 100);
exit_btn->setStyleSheet("QPushButton {background-color: rgb(150,150,150);}");
QFont font = exit_btn->font();
font.setPointSize(32);
exit_btn->setFont(font);
exit_btn->setIcon(QIcon(":/Icons/close.png"));
exit_btn->setIconSize(QSize(65, 65));
exit_btn->show();
}
void MainWindow::configure_new_button()
{
new_btn = new QPushButton(this);
new_btn->setGeometry(0, 0, 100, 100);
new_btn->connect(new_btn, SIGNAL(clicked()),this, SLOT(new_entry()));
new_btn->setStyleSheet("background-color: rgb(0,0,200);" "color: black");
QFont font = new_btn->font();
font.setPointSize(32);
new_btn->setFont(font);
new_btn->setIcon(QIcon(":/Icons/nouveau.png"));
new_btn->setIconSize(QSize(65, 65));
new_btn->show();
}
void MainWindow::configure_escape()
{
escape = new QAction( "text4ESC", this );
escape->setShortcut( Qt::Key_Escape );
escape->setShortcutContext( Qt::WindowShortcut );
connect(escape, SIGNAL(triggered()), this, SLOT(exit()));
addAction(escape);
}
void MainWindow::exit()
{
close();
qApp->quit();
}
void MainWindow::new_entry()
{
std::cout << "coucou !!!" << std::endl;
}
Mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWidget>
#include <QObject>
#include <QPushButton>
#include <QEvent>
#include <QKeyEvent>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(int _width, int _height, QMainWindow *parent = 0);
~MainWindow();
void configure_exit_button();
void configure_new_button();
void configure_escape();
private slots:
void exit();
void new_entry();
private:
QPushButton *exit_btn;
QPushButton *new_btn;
QAction *escape;
int width;
int height;
};
#endif //MAINWINDOW_H
Mainchart.cpp
#include "MainChart.h"
MainChart::MainChart(QChart *Parent)
{
QBarSet *set0 = new QBarSet("Altuve");
QBarSet *set1 = new QBarSet("Martine");
QBarSet *set2 = new QBarSet("Bob");
*set0 << 256 << 954 << 752 << 148 << 596 << 214;
*set1 << 586 << 369 << 485 << 874 << 693 << 587;
*set2 << 785 << 963 << 547 << 745 << 657 << 874;
QFont font;
font.setPixelSize(18);
QBarSeries *series = new QBarSeries();
series->append(set0);
series->append(set1);
series->append(set2);
QChart *chart = new QChart();
chart->addSeries(series);
chart->setTitle("Mon Super Graphique");
chart->setTitleFont(font);
chart->setTitleBrush(QBrush(qRgb(255,255,255)));
chart->setAnimationOptions(QChart::AllAnimations);
QStringList categories;
categories << "2013" << "2014" << "2015" << "2016" << "2017";
QBarCategoryAxis *axis = new QBarCategoryAxis();
axis->append(categories);
chart->createDefaultAxes();
chart->setAxisX(axis, series);
font.setPixelSize(12);
chart->axisX()->setLabelsBrush(QBrush(qRgb(255,255,255)));
chart->axisX()->setLabelsFont(font);
chart->axisY()->setLabelsBrush(QBrush(qRgb(255,255,255)));
chart->axisY()->setLabelsFont(font);
chart->legend()->setVisible(true);
chart->legend()->setAlignment(Qt::AlignBottom);
chart->legend()->setLabelColor(qRgb(255,255,255));
chart->legend()->setFont(font);
chart->setBackgroundBrush(QBrush(QRgb(0x0)));
chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
}
MainChart::~MainChart() {}
QChartView * MainChart::get_view()
{
return chartView;
}
Mainchart.h
#ifndef NEW_MAINCHART_H
#define NEW_MAINCHART_H
#include <QtCharts/QChartView>
#include <QtCharts/QSplineSeries>
#include <QtCharts/QBarSeries>
#include <QtCharts/QBarSet>
#include <QtCharts/QBarCategoryAxis>
QT_CHARTS_USE_NAMESPACE
class MainChart : public QChart
{
public:
MainChart(QChart *Parent = 0);
~MainChart();
QChartView *get_view();
private:
QChartView *chartView;
};
#endif //NEW_MAINCHART_H

I think you want to look at using layouts. I'm not entirely positive, but making the chart the window's central widget means it's going to take up all the space -- just the way it's behaving.
It sounds like what you should do is create a widget and consider it a container. It becomes your central widget, and then you add things to it. But without a layout, you're going to get weird resize behavior.
It's really far better to grow accustomed to handling layouts using a layout rather than hard-coded size & locations. You have to use widgets as containers to make things work, but everything I've tried to do I've been able to do.

Related

Qt 6.3 live play not working properly after re-plug camera

When I re-plug the camera from USB port and fire up my program, the preview pane will black out and nothing works. However, if I fire up my program for the second time, the qt preview pane will live play smoothly.
How can I fix preview pane not working at first startup after connecting the camera?
INFO:
Mac mini
OS: macOS m1, montery 12.3.1
Platform: Qt 6.3
Port: USB3.0
IMG format: Motion JPEG
Code snippet:
main.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsVideoItem>
#include <QCamera>
#include <QMediaCaptureSession>
#include <QMediaDevices>
#include <QCameraDevice>
#include <QList>
#include <QAudioInput>
#include <QCloseEvent>
#include <QPushButton>
#include <QImageCapture>
#include "opencv2/opencv.hpp"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
void showEvent(QShowEvent* event);
void closeEvent(QCloseEvent* event);
private:
Ui::MainWindow *ui;
QGraphicsView* pGraphyView;
QGraphicsScene* pGraphyScene;
QGraphicsVideoItem* pGraphyVideoItem;
QCamera* pCamera;
QMediaCaptureSession captureSession;
QAudioInput* pAudioInput;
QImageCapture* pImageCapture;
cv::Mat srcImage;
cv::Mat dstImage;
};
#endif // MAINWINDOW_H
main.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
//=====================================================================
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
pGraphyView = 0;
pGraphyScene = 0;
pGraphyVideoItem = 0;
pCamera = 0;
}
//=====================================================================
MainWindow::~MainWindow()
{
delete ui;
}
//=====================================================================
void MainWindow::showEvent(QShowEvent* event)
{
pAudioInput = new QAudioInput;
captureSession.setAudioInput(pAudioInput);
QStringList str_list;
QString str_id;
QString str_vid;
QString str_pid;
const QList<QCameraDevice> cameras = QMediaDevices::videoInputs();
qDebug() << "camera count = " << cameras.size();
for (const QCameraDevice &cameraDevice : cameras)
{
str_id = cameraDevice.id();
str_vid = str_id.mid(9,4);
str_pid = str_id.right(4);
qDebug() << "id = " << str_id;
qDebug() << "vid = 0x" << str_vid;
qDebug() << "pid = 0x" << str_pid;
if(str_vid == "a168")
{
pCamera = new QCamera(cameraDevice);
captureSession.setCamera(pCamera);
pGraphyScene = new QGraphicsScene(0,0,640,480);
pGraphyView = new QGraphicsView(this);
pGraphyView->setScene(pGraphyScene);
this->setCentralWidget((QWidget*)pGraphyView);
pGraphyVideoItem = new QGraphicsVideoItem;
pGraphyVideoItem->setSize(QSizeF(640,480));
pGraphyVideoItem->setPos(0,0);
pGraphyScene->addItem(pGraphyVideoItem);
captureSession.setVideoOutput(pGraphyVideoItem);
pCamera->start(); // live play.
break;
}
}
}
//=====================================================================
void MainWindow::closeEvent(QCloseEvent* event)
{
if(pAudioInput)
{
delete pAudioInput;
pAudioInput = 0;
}
if(pGraphyVideoItem)
{
delete pGraphyVideoItem;
pGraphyVideoItem = 0;
}
if(pGraphyScene)
{
delete pGraphyScene;
pGraphyScene = 0;
}
if(pGraphyView)
{
delete pGraphyView;
pGraphyView = 0;
}
event->accept();
}
I tried using macOS' facetime to check if the camera itself is functionable, and it did. The facetime live play smoothly.
I guess it's something related to Qt 6.3.

Qt 6.3 live play not working properly with YUY2

I can't get the qt preview pane to work. It's always black after I plug in the camera.
INFO:
Mac mini
OS: macOS m1, montery 12.3.1
Platform: Qt 6.3
Port: USB3.0
Img format: YUY2
Code snippets:
main.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsVideoItem>
#include <QCamera>
#include <QMediaCaptureSession>
#include <QMediaDevices>
#include <QCameraDevice>
#include <QList>
#include <QAudioInput>
#include <QCloseEvent>
#include <QPushButton>
#include <QImageCapture>
#include "opencv2/opencv.hpp"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
void showEvent(QShowEvent* event);
void closeEvent(QCloseEvent* event);
private:
Ui::MainWindow *ui;
QGraphicsView* pGraphyView;
QGraphicsScene* pGraphyScene;
QGraphicsVideoItem* pGraphyVideoItem;
QCamera* pCamera;
QMediaCaptureSession captureSession;
QAudioInput* pAudioInput;
QImageCapture* pImageCapture;
cv::Mat srcImage;
cv::Mat dstImage;
};
#endif // MAINWINDOW_H
main.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
//=====================================================================
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
pGraphyView = 0;
pGraphyScene = 0;
pGraphyVideoItem = 0;
pCamera = 0;
}
//=====================================================================
MainWindow::~MainWindow()
{
delete ui;
}
//=====================================================================
void MainWindow::showEvent(QShowEvent* event)
{
pAudioInput = new QAudioInput;
captureSession.setAudioInput(pAudioInput);
QStringList str_list;
QString str_id;
QString str_vid;
QString str_pid;
const QList<QCameraDevice> cameras = QMediaDevices::videoInputs();
qDebug() << "camera count = " << cameras.size();
for (const QCameraDevice &cameraDevice : cameras)
{
str_id = cameraDevice.id();
str_vid = str_id.mid(9,4);
str_pid = str_id.right(4);
qDebug() << "id = " << str_id;
qDebug() << "vid = 0x" << str_vid;
qDebug() << "pid = 0x" << str_pid;
if(str_vid == "a168")
{
pCamera = new QCamera(cameraDevice);
captureSession.setCamera(pCamera);
pGraphyScene = new QGraphicsScene(0,0,640,480);
pGraphyView = new QGraphicsView(this);
pGraphyView->setScene(pGraphyScene);
this->setCentralWidget((QWidget*)pGraphyView);
pGraphyVideoItem = new QGraphicsVideoItem;
pGraphyVideoItem->setSize(QSizeF(640,480));
pGraphyVideoItem->setPos(0,0);
pGraphyScene->addItem(pGraphyVideoItem);
captureSession.setVideoOutput(pGraphyVideoItem);
pCamera->start(); // live play.
break;
}
}
}
//=====================================================================
void MainWindow::closeEvent(QCloseEvent* event)
{
if(pAudioInput)
{
delete pAudioInput;
pAudioInput = 0;
}
if(pGraphyVideoItem)
{
delete pGraphyVideoItem;
pGraphyVideoItem = 0;
}
if(pGraphyScene)
{
delete pGraphyScene;
pGraphyScene = 0;
}
if(pGraphyView)
{
delete pGraphyView;
pGraphyView = 0;
}
event->accept();
}
I tried using macOS' facetime to check if the camera itself is functionable, and it did. The facetime live play smoothly.
I guess it's something related to Qt 6.3.

How to display a QChartView inside a QStackedWidget?

I want my form to have a QStackedWidget with 2 (at least) pages and each of them has a QChartView.
In the form editor, through the 'promote' menu, I made a QChartView from QGraphicView. (screenshoot (so far there is only 1 QChartView on it - so that i can see which page is open)).
From the main window, when one of the buttons is pressed, I want to open the above windows in a loop:
void Widget::ShowStudioCharts() noexcept
{
for(auto & e : this->userInfoVector){
Form *pForm = new Form();
pForm->provideStudioData(&e.studiosStats, e.nickname);
pForm->processStudioStats();
pForm->show();
}
}
I tried to do it like this:
Form.h
#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include <QPieSeries>
#include <QChart>
#include <QChartView>
#include <QGridLayout>
#include <vector>
#include <map>
#include <QStackedWidget>
#include <QtGlobal>
#include <QRectF>
#include <QRect>
#include <QPushButton>
namespace Ui {
class Form;
}
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = nullptr);
~Form();
void provideStudioData(std::map<std::string, std::size_t> *studiosStats, const std::string &nickname) noexcept;
void processStudioStats() noexcept;
private slots:
void on_pushButton_2_clicked();
private:
std::vector<std::map<std::string, size_t>*> stats;
std::vector<std::string> nicknames;
Ui::Form *ui;
};
#endif // FORM_H
Form.cpp
#include "form.h"
#include "ui_form.h"
#include <QPieSeries>
#include <QPieSlice>
#include <QChart>
using namespace QtCharts;
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
{
ui->setupUi(this);
}
Form::~Form()
{
delete ui;
}
void Form::provideStudioData(std::map<std::string, size_t> *studiosStats, const std::string &nickname) noexcept
{
this->stats.push_back(studiosStats);
this->nicknames.push_back(nickname);
}
void Form::processStudioStats() noexcept
{
srand(time(0));
QPieSeries *series = new QPieSeries();
// for (const auto & e : this->stats ){
// //QBarSet *set0 = new QBarSet("1");
// for ( const auto & a : *e){
// //*set0 << a.second;
// qDebug( (a.first + " " + std::to_string(a.second)).c_str());
// }
// }
for ( const auto & a : *this->stats[0]){
QPieSlice * slice = new QPieSlice();
slice->setColor(QColor(rand()%255, rand()%255, rand()%255));
slice->setValue(a.second);
slice->setLabel(a.first.c_str());
series->append(slice);
}
QChart *chart = new QChart();
chart->setAnimationOptions(QChart::AnimationOption::AllAnimations);
chart->addSeries(series);
//chart->setPlotArea(QRectF(200,0,1400,1100));
//chart->legend()->detachFromChart();
chart->legend()->setBackgroundVisible(true);
chart->legend()->setBrush(QBrush(QColor(128, 128, 128, 128)));
chart->legend()->setPen(QPen(QColor(192, 192, 192, 192)));
//chart->legend()->setGeometry(QRectF(20,20,200,1000));
chart->setTitle(QString::fromStdString(this->nicknames[0]));
this->setWindowTitle(QString::fromStdString(this->nicknames[0]));
chart->legend()->setAlignment(Qt::AlignLeft);
ui->graphicsView = new QChartView(chart);
ui->graphicsView->show();
//ui->stackedWidget->show();
}
void Form::on_pushButton_2_clicked()
{
if(0 == this->ui->stackedWidget->currentIndex())
this->ui->stackedWidget->setCurrentIndex(1);
else if(1 == this->ui->stackedWidget->currentIndex())
this->ui->stackedWidget->setCurrentIndex(0);
}
The code is compiled, windows are opened. But the problem is that my chart is displayed in another window above the opened one.
This is obviously the result of
ui->graphicsView->show();
But if i remove this line, then the graph is not visible at all.
Help please, thanks in advance.
Doing ui->graphicsView = new QChartView(chart); does not replace the QChartView, you are just assigning the pointer. The solution is to reuse the existing QChartView so it changes to: ui->graphicsView->setChart(chart);.

Scrolling list of labels on Qt

I'm trying to create a scrollbar for my labels. For the moment, if the users create too many labels, the sizes of the button and of the text zone are reduced, that's why I wanted to create a scrollbar then if there is too many labels, they will not change the aspect of the window.
This is my actual code :
#include <iostream>
#include <QApplication>
#include <QPushButton>
#include <QLineEdit>
#include <QWidget>
#include <QFormLayout>
#include "LibQt.hpp"
LibQt::LibQt() : QWidget()
{
this->size_x = 500;
this->size_y = 500;
QWidget::setWindowTitle("The Plazza");
setFixedSize(this->size_x, this->size_y);
manageOrder();
}
LibQt::~LibQt()
{
}
void LibQt::keyPressEvent(QKeyEvent* event)
{
if (event->key() == Qt::Key_Escape)
QCoreApplication::quit();
else
QWidget::keyPressEvent(event);
}
void LibQt::manageOrder()
{
this->converLayout = new QFormLayout;
this->testline = new QLineEdit;
this->m_button = new QPushButton("Send");
this->m_button->setCursor(Qt::PointingHandCursor);
this->m_button->setFont(QFont("Comic Sans MS", 14));
this->converLayout->addRow("Order : ", this->testline);
this->converLayout->addWidget(this->m_button);
QObject::connect(m_button, SIGNAL(clicked()), this, SLOT(ClearAndGetTxt()));
CreateLabel("test");
CreateLabel("test2");
}
void LibQt::CreateLabel(std::string text)
{
QString qstr = QString::fromStdString(text);
this->label = new QLabel(qstr);
this->converLayout->addWidget(this->label);
this->setLayout(converLayout);
}
std::string LibQt::ClearAndGetTxt()
{
QString txt = this->testline->text();
if (!txt.isEmpty())
{
this->usertxt = txt.toStdString();
std::cout << this->usertxt << std::endl;
this->testline->clear();
CreateLabel(this->usertxt);
return (this->usertxt);
}
return (this->usertxt);
}
std::string LibQt::getUsertxt()
{
return (this->usertxt);
}
And this is the .hpp :
#ifndef _LIBQT_HPP_
#define _LIBQT_HPP_
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QFormLayout>
#include <QLabel>
#include <QLineEdit>
#include <QKeyEvent>
class LibQt : public QWidget
{
Q_OBJECT
public:
LibQt();
~LibQt();
void manageOrder();
std::string getUsertxt();
void keyPressEvent(QKeyEvent *event);
void keyPressEventEnter(QKeyEvent *event);
void CreateLabel(std::string text);
public slots:
std::string ClearAndGetTxt();
protected:
int size_x;
int size_y;
QPushButton *m_button;
QLineEdit *testline;
std::string usertxt;
QLabel *label;
QFormLayout *converLayout;
};
#endif /* _LIBQT_HPP_ */
there are different solutions depending on what precisely do you want
QTextEdit is Qt widget class for scrollable text. By turning off text interaction flags, frame style and unsetting background color you will basically get scrollable QLabel
QScrollArea as a more generic solution

calculate BMI program

This is a program that calculates the BMI by inputting weight and height
#ifndef BMIVIEWER_H
#define BMIVIEWER_H
#include <QWidget>
#include <QGridLayout>
#include <QLineEdit>
#include <QLabel>
#include <QPushButton>
#include <QLCDNumber>
#include <QErrorMessage>
#include <QString>
#include <QMessageBox>
class BmiViewer : public QWidget {
Q_OBJECT
public:
BmiViewer();
void calculateBmi();
private:
QLineEdit* heightEntry;
QLineEdit* weightEntry;
QLCDNumber* result;
QErrorMessage* error;
};
#endif // BMIVIEWER_H
bmiviewer.cpp
#include "bmiviewer.h"
BmiViewer::BmiViewer(){
setWindowTitle("MMI Calculator");
QGridLayout* layout = new QGridLayout;
QLabel* inputWeightRequest = new QLabel ("Enter weight in Kg:");
weightEntry = new QLineEdit;
QLabel* inputHeightRequest = new QLabel ("Enter height in meters:");
heightEntry = new QLineEdit;
QPushButton* calc = new QPushButton ("Calculate");
QLabel* labelbmi = new QLabel ("BMI");
result = new QLCDNumber;
result->setSegmentStyle(QLCDNumber::Flat);
result->setDigitCount(8);
layout->addWidget (inputWeightRequest, 0,0);
layout->addWidget (weightEntry, 0,1);
layout->addWidget (inputHeightRequest, 1,0);
layout->addWidget (heightEntry, 1,1);
layout->addWidget (calc, 2,1);
layout->addWidget (labelbmi, 3,0);
layout->addWidget (result, 3,1);
setLayout(layout);
//connect signals and slots
connect(calc,SIGNAL(clicked()),this, SLOT(calculateBmi()));
}
void BmiViewer::calculateBmi(){
int wanswer=0;
int hanswer=0;
double bmi;
QString iStr = weightEntry->text();
QString iStrh = heightEntry->text();
bool ok;
wanswer = iStr.toInt(&ok);
hanswer = iStrh.toInt(&ok);
if (!ok) {
error = new QErrorMessage(this);
error->showMessage("Please enter a valid integer");
return;
}
//calculate BMI
bmi=wanswer/(hanswer*hanswer);
result->display(bmi);
}
main.cpp
#include <QApplication>
#include "bmiviewer.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
BmiViewer w;
w.show();
return a.exec();
}
When I compile it it outputs: Object::connect: No such slot BmiViewer::calculateBmi() in bmiviewer.cpp:29
It displays the interface but no calculations are done.
Add the line
public slots:
before
void calculateBmi();
You never declared the bmi function a slot and so it can't be connected to.