Qt. How to handle double click event - c++

I cannot to handle double click event. I try to do this using following code
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected slots:
void OnDc(const QModelIndex&);
private:
Ui::MainWindow *ui;
};
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(this, SIGNAL(doubleClicked(const QModelIndex& )), this, SLOT(OnDc(const QModelIndex&)));
}
void MainWindow::OnDc(const QModelIndex&)
{
...
}
OnDc is not calling when double click happens.
What did I do wrong?

You should use void QWidget::mouseDoubleClickEvent ( QMouseEvent * event ) [virtual protected]
You can override QMainWindow::mouseDoubleClickEvent
void MainWindow::mouseDoubleClickEvent( QMouseEvent * e )
{
if ( e->button() == Qt::LeftButton )
{
...
}
// You may have to call the parent's method for other cases
QMainWindow::mouseDoubleClickEvent( e );
}

Related

How to support HTML for QGroupBox?

I need to create a group box that supports HTML text when we set
MyGroupBox *gb = new MyGroupBox();
gb->setTitle("<u> This is underlined text</u>");
I have tried some searches but no results. In my head right now I think only about to set style for my groupbox. Something like this:
MyGroupBox.cpp
MyGroupBox::MyGroupBox( QWidget *p_parent ) : QGroupBox( p_parent )
{
setStyle( &m_style );
}
TitleStyle.hpp
class TitleStyle : public QProxyStyle
{
public:
TitleStyle() = default;
virtual void drawComplexControl( ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr ) const override;
};
TitleStyle.cpp
void TitleStyle::drawComplexControl( ComplexControl p_control, const QStyleOptionComplex *p_option, QPainter *p_painter, const QWidget *p_widget ) const
{
if ( p_control == CC_GroupBox )
{
if ( const QStyleOptionGroupBox *title = qstyleoption_cast<const QStyleOptionGroupBox *>( p_option ) )
{
QTextDocument td;
td.setHtml( title->text );
td.drawContents( p_painter );
}
}
else
{
QProxyStyle::drawComplexControl( p_control, p_option, p_painter, p_widget );
}
}
This still does not work. I know my drawComplexControl is weird, but that is what in my mind now. Can anyone tell me if I am going in the right direction? If yes, how could I change the class TitleStyle. If not, how could I do?
Solution:
It took me a while to find my mistake. With the code above, the title should be rich text supported already.
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QProxyStyle>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class TitleStyle : public QProxyStyle
{
public:
TitleStyle() = default;
virtual void drawComplexControl( ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr ) const override;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
TitleStyle m_style;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTextDocument>
void TitleStyle::drawComplexControl( ComplexControl p_control, const QStyleOptionComplex *p_option, QPainter *p_painter, const QWidget *p_widget ) const
{
if ( p_control == CC_GroupBox )
{
if ( const QStyleOptionGroupBox *title = qstyleoption_cast<const QStyleOptionGroupBox *>( p_option ) )
{
QTextDocument td;
td.setHtml( title->text );
td.drawContents( p_painter );
}
}
else
{
QProxyStyle::drawComplexControl( p_control, p_option, p_painter, p_widget );
}
}
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->groupBox->setStyle(&m_style);
ui->groupBox->setTitle("<b><u>This is an underlined title</u></b>");
}
MainWindow::~MainWindow()
{
delete ui;
}
Result:
Actually I have found my mistake in other positions. With this code, the title should be rich text supported already. I have tried with Qt Creator and it worked. I update my solution above.

Qt How to connect the rubberBandChanged signal

I try to link the rubberBandChanged signal from QChartView class to a specific function in MainWindow class.
MainWindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void rubberZoomAdapt(QRect, QPointF, QPointF);
private:
Ui::MainWindow *ui;
QChartView* qcvChart;
Chart* chart;
};
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
qcvChart(new QChartView),
chart(new Chart)
{
ui->setupUi(this);
//Connexion
QObject::connect(qobject_cast<QGraphicsView*>(this->qcvChart),
&QGraphicsView::rubberBandChanged,
this,
&MainWindow::rubberZoomAdapt);
this->qcvChart->setChart(this->chart);
this->qcvChart->setRubberBand(QChartView::HorizontalRubberBand);
}
void MainWindow::rubberZoomAdapt(QRect r, QPointF fp, QPointF tp)
{
static int i = 0;
qDebug() << "(rubberZoomAdapt) RubberBand Event: " << QString::number(i++);
}
When I use the rubberBand in my chart, I never enter in the rubberZoomAdapt().
Any idee to fix this ?
Thanks.
The problem is that although QChartView inherits from QGraphicsView it does not use the same QRubberBand so the rubberBandChanged signal is never issued.
The solution is to look for the QRubberBand since it is a child of QChartView and filter it through the resizeEvent event, and then create our own signal:
*.h
...
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
bool eventFilter(QObject *watched, QEvent *event) override;
public slots:
void rubberZoomAdapt(QPointF fp, QPointF tp);
signals:
void rubberBandChanged(QPointF fp, QPointF tp);
private:
Ui::MainWindow *ui;
QChartView* qcvChart;
QChart* chart;
QRubberBand *rubberBand;
};
...
*.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
qcvChart(new QChartView),
chart(new QChart)
{
ui->setupUi(this);
qcvChart->setChart(chart);
qcvChart->setRubberBand(QChartView::HorizontalRubberBand);
rubberBand = qcvChart->findChild<QRubberBand *>();
rubberBand->installEventFilter(this);
connect(this, &MainWindow::rubberBandChanged,this, &MainWindow::rubberZoomAdapt);
setCentralWidget(qcvChart);
...
}
...
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if(watched == rubberBand && event->type() == QEvent::Resize){
QPointF fp = chart->mapToValue(rubberBand->geometry().topLeft());
QPointF tp = chart->mapToValue(rubberBand->geometry().bottomRight());
emit rubberBandChanged(fp, tp);
}
return QMainWindow::eventFilter(watched, event);
}
void MainWindow::rubberZoomAdapt(QPointF fp, QPointF tp)
{
qDebug() << "(rubberZoomAdapt) RubberBand Event: "<<fp<<tp;
}
The complete example can be found in the following link

Signal and slot wrong value sending(Qt c++)

I have written a small program to send data from one form(MainWindow) to another(Dialog) upon a button click. When the button is clicked the value written in the lineEdit of MainWindow is to be displayed on a label in Dialog form!
When I click the button a value is displayed on the label but it is not the same as the value entered in the line edit!
following are the respective codes in the 2 header and 2 cpp files!
MainWindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
signals:
void sendIntData(int data);
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
}
MainWIndow.cpp
void MainWindow::on_pushButton_clicked()
{
Dialog *dialog1=new Dialog(this);
dialog1->setModal(true);
dialog1->exec();
int o=ui->lineEdit->text().toInt();
connect(this, SIGNAL(sendIntData(int)),dialog1, SLOT(setIntData(int)));
emit sendIntData(o);
}
Dialog.h
class Dialog : public QDialog
{
Q_OBJECT
public slots:
void setIntData(int data);
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
}
Dialog.cpp
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::DIalog)
{
ui->setupUi(this);
QString value=QString::number(index);
ui->label->setText(value);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::setIntData(int data)
{
index=data;
}
eg-When I click 3 and press the button I get a value 7237481! How can I correct this?
Replace connect and emit in on_pushButton_clicked()
void MainWindow::on_pushButton_clicked()
{
Dialog *dialog1=new Dialog(this);
dialog1->setModal(true);
dialog1->exec();
int o=ui->lineEdit->text().toInt();
connect(this, SIGNAL(sendIntData(int)),dialog1, SLOT(setIntData(int)));
emit sendIntData(o);
}
If only once we convey our dialogue, the importance of signal and slot is not necessary.
It is possible to give this value to the constructor or to do the initialize function and to give it the values.
//way 1:
void MainWindow::on_pushButton_clicked(){
Dialog *dlg = new Dialog();
connect(this, SIGNAL(SendData(int)), dlg, SLOT(slotData(int)));
emit SendData(ui->lineEdit->text().toInt());
dlg->exec();
}
void Dialog::slotData(int arg1)
{
ui->label->setText(QString::number(arg1));
}
//way 2:
void MainWindow::on_pushButton_clicked(){
Dialog* dlg = new Dialog(ui->lineEdit->text().toInt());
dlg->exec();
}
//way 3:
#include "dialog.h"
#include "ui_dialog.h"
#include "QDebug"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::initialize(int value)
{
ui->label->setText(QString::number(value));
}
void MainWindow::on_pushButton_clicked(){
Dialog *dlg = new Dialog();
dlg->initialize(ui->lineEdit->text().toInt());
dlg->exec();
}
I think you are showing int value which not initialized.
emit signal:
int o=ui->lineEdit->text().toInt();
connect(this, SIGNAL(sendIntData(int)),dialog1, SLOT(setIntData(int)));
emit sendIntData(o);
Show value:
void Dialog::setIntData(int data)
{
ui->label->setText(QString::number(data));
}

QListWidget cannot add an item dynamically

In my Qt application, I want to add a new item dynamically into a listview. Besides I also used Signal & Slot to transfer data between forms so I have created 2 following forms:
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void ReceivedData(QString item);
private slots:
void on_btnAdd_clicked();
void on_btnCancel_clicked();
private:
Ui::MainWindow *ui;
void SetUpListName();
};
addform.h
class AddForm : public QDialog
{
Q_OBJECT
public:
explicit AddForm(QWidget *parent = 0);
~AddForm();
signals:
void SendData(QString item);
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::AddForm *ui;
MainWindow *main_window;
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
SetUpListName();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::SetUpListName()
{
// Add 5 new elements
for (int i = 0; i < 5; i++) {
QString item = "Item " + QString::number(i);
ui->lwListItem->addItem(item);
}
}
void MainWindow::on_btnAdd_clicked()
{
// Open Add Form
AddForm add;
add.setModal(true);
add.exec();
}
void MainWindow::on_btnCancel_clicked()
{
this->close();
}
void MainWindow::ReceivedData(QString item)
{
// Check to receive data
qDebug() << "Item: " << item;
// Add a new item to list items
ui->lwListItem->addItem(item);
}
addform.cpp
AddForm::AddForm(QWidget *parent) :
QDialog(parent),
ui(new Ui::AddForm)
{
ui->setupUi(this);
main_window = new MainWindow();
connect(this, SIGNAL(SendData(QString)), main_window, SLOT(ReceivedData(QString)));
}
AddForm::~AddForm()
{
delete ui;
}
void AddForm::on_pushButton_clicked()
{
// Send data via Signal & Slot
emit SendData(ui->txtName->text());
}
void AddForm::on_pushButton_2_clicked()
{
this->close();
}
When I run the application, I got the data from Add form but the list view doesn’t add this item.
Does someone have any solutions?
Thanks!
P/S: You can download my source code at here
You are connecting the signal to the wrong object's slot. In the constructor of AddForm, you are creating a new MainWindow and connecting the signal to it's slot which means that the signal does not reach your real MainWindow, and the ReceivedData slot is adding the item to the wrong QListWidget. What you should do is this:
void MainWindow::on_btnAdd_clicked()
{
// Open Add Form
AddForm add;
connect(&add, SIGNAL(SendData(QString)), this, SLOT(ReceivedData(QString)));
add.setModal(true);
add.exec();
}
and remove the creation of a new MainWindow and corresponding connect call from the constructor of AddForm.

What is the proper way to set QProgressBar to update from the logic layer?

If I want to update a QProgressBar on the view layers from a loop on the logic layer (such as each iteration will update the progress bar), what is the proper way to do that?
Thanks
class LogicClass : public QObject
{
Q_OBJECT
public:
explicit LogicClass(QObject *parent = 0);
int max(){ return 100; }
int min(){ return 0; }
void emit50(){ emit signalProgress(50); }
signals:
void signalProgress(int);
public slots:
};
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
LogicClass logic;
ui->progressBar->setMaximum( logic.max() );
ui->progressBar->setMinimum( logic.min() );
connect( &logic, SIGNAL( signalProgress(int) ), ui->progressBar, SLOT( setValue(int) ) );
logic.emit50();
}
QProgressBar has some public slots that are used for setting min and max values and current value. Increasing the current value causes the progress bar to move. You can emit a signal from the logic layer that is connected to "void setValue ( int value )" slot of QProgressBar.
http://doc.qt.digia.com/qt/qprogressbar.html