I wish derived class from QComboBox with following additional feature:
When user clicks to QLiineEdit of this combo box, the effect have to be the same as click to arrow on the right side of combo box (showPopup() method).
My attemption is:
File lineedit.h
#ifndef LINEEDIT_H
#define LINEEDIT_H
#include <QLineEdit>
class LineEdit : public QLineEdit {
Q_OBJECT
public:
LineEdit(QWidget *parent = nullptr);
signals:
void pressed();
protected:
void mousePressEvent(QMouseEvent *event) override;
};
#endif // LINEEDIT_H
File lineedit.cpp
#include "lineedit.h"
#include <QMouseEvent>
LineEdit::LineEdit(QWidget *parent) : QLineEdit(parent) {}
void LineEdit::mousePressEvent(QMouseEvent *event) {
QLineEdit::mousePressEvent(event);
emit pressed();
event->accept();
}
File combobox.h
#ifndef COMBOBOX_H
#define COMBOBOX_H
#include <QComboBox>
class ComboBox : public QComboBox {
Q_OBJECT
public:
ComboBox(QWidget *parent = nullptr);
private slots:
void lineEditPressed();
};
#endif // COMBOBOX_H
File combobox.cpp
#include "combobox.h"
#include "lineedit.h"
ComboBox::ComboBox(QWidget *parent) : QComboBox(parent) {
setLineEdit(new LineEdit);
connect(lineEdit(), SIGNAL(pressed()), this, SLOT(lineEditPressed()));
}
void ComboBox::lineEditPressed() { showPopup(); }
But, when I press lineEdit, it shows popup, but after releasing mouse button it vanishes.
Please, revise the documentation of the event handler. As you show pop-up menu in this function, then the release event will conflict hastily. I can't predict your implementation of showPopup(), but please don't create a pop-up menu inside it. You may show, hide, assign, but NEVER create.
Related
My UI MainWindow has a QListWidget and , upon clicking of its items ,a corresponding QDialog box must pop up , which prompts the user to enter some values in QDialog box, The values entered into line_edits of QDialog box must stored into a QString variable and this variable should be accessed/used in a function of MainWindow,
for Example: I have a QListWidget, with 3 items "New York","Glasgow","Mumbai", and when i double click item named "New York", a pop-up shows up asking me this
and after i enter 3 and Hilton , the item in QListWidget which was initially "New York" must be changed to
"New York -3 , The safehouse is in Hilton"
my code for MainWindow.cpp is
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtCore>
#include <QtGui>
#include <sstream>
#include <QtWidgets/qmessagebox.h>
#include <QtWidgets/qlistwidget.h>
using namespace std;
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->My_listwidget->addItem("New York");
ui->My_listwidget->addItem("Glasgow");
ui->My_listwidget->addItem("Mumbai");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_My_listwidget_itemDoubleClicked(QListWidgetItem* item)
{
QString test = item->text();
std::string test_s = test.toStdString();
if (test_s.find("New York") != std::string::npos) // check if item contains text "New York"
{
WinApp winApp;
winApp.setModal(true); //Displaying the window here
winApp.exec();
}
if (test_s.find("Glasgow") != std::string::npos)
{
// show another dialog box asking some questions
}
if (test_s.find("Mumbai") != std::string::npos)
{
// show another dialog box asking some questions
}
}
My code for mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtWidgets/QMainWindow>
#include "ExecutionContext.h"
#include <QtWidgets/qlistwidget.h>
//#include "secdialog.h"
#include <qregexp.h>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT //Used to handle events
public:
MainWindow(QWidget* parent = 0);
~MainWindow(); //Destructor used to free resources
private slots:
void on_xml_scripts_textbox_itemDoubleClicked(QListWidgetItem* item);
Ui::MainWindow* ui; // pointing to UI class
private:
};
#endif // MAINWINDOW_H
my code for WinApp.h , winapp is the name of my dialog
#include <QtWidgets/qdialog.h>
#include "ui_WinApp.h"
class WinApp : public QDialog, public Ui::WinApp
{
Q_OBJECT
public:
WinApp(QWidget *parent = Q_NULLPTR);
~WinApp();
private slots:
private:
Ui::WinApp ui;
};
WinApp.cpp
#include "WinApp.h"
WinApp::WinApp(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
}
WinApp::~WinApp()
{
}
you need to add in the WinApp dialog class the test getter, it should be something like:
QString getFavouriteHotel() const {
return ui.<favourite-hotel-label>.text()
}
In the MainWindow after the line winApp.exec(); I suggest adding an if to check if the user accepted or declined the dialog (docs). If the user accepted the dialog then you can retrieve the text with the getters you just added.
Tips: avoid using exec, as said in the docs use the open
-- UPDATE -- QDialog accept --
Always check the docs
connect(&WinApp, &QDialog::finished, this, [this](int result) {
if(result == QDialog::Accepted){
// do aswomness
return
}
});
Have the function initiating the QDialog object pass the QString argument in the constructor and override accept().
#include <QtWidgets/qdialog.h>
#include "ui_WinApp.h"
class WinApp : public QDialog, public Ui::WinApp
{
Q_OBJECT
public:
WinApp(QString& stringToModify, QWidget *parent = Q_NULLPTR);
~WinApp();
private slots:
void accept() override;
private:
Ui::WinApp ui;
};
and define the acccept() slot which will get the QString from lineEdit and update the stringToModify with it.
void WinApp::accept(){
//do stuff with QString
this->close();
}
I'm new to QtCreator and created a button on the mainwindow that opens a dialog. In the dialog i added QLineEdit and a button. When i click on this button, i want the input text to be displayed on a Qlabel in the mainwindow.
I found another question which is basicly the same, but for me it has to work the other way around.
So In the header of MainWindow.h i have added to public:
void setLabelText(QString str);
I created the getter/setter function and added it to MainWindow.cpp:
void MainWindow::setLabelText(QString str)
{
ui->label->setText(str);//it is label dialog
}
And in the windowdialog.cpp i have added under button click() slot:
void WindowDialog::on_pushButton_clicked()
{
QString str = ui->lineEdit->text();
MainWindow MainWindow;
MainWindow.setLabelText(str);
}
It compiles without errors. Yet when i click on the button in the dialog, it won't print the results in the mainwindow... I have been trying to find another examples about how to do this, but couldn't really find one yet. So what am i missing? Or how do i make this work?
You can use signals and slots for this. https://doc.qt.io/qt-5/signalsandslots.html
you would need to connect the signal to a slot by using this command
connect(dlg,&DialogWindow::transmit,this,&MainWindow::update);
anytime you want to call the update function you would just need to emit the signal.
emit transmit(ui->lineEdit->text());
I created a dialog window class in this example.
Dialog.h
#ifndef DIALOGWINDOW_H
#define DIALOGWINDOW_H
#include <QDialog>
QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE
class DialogWindow : public QDialog
{
Q_OBJECT
public:
DialogWindow(QWidget *parent = nullptr);
~DialogWindow();
signals:
void transmit(QString txt);
private slots:
void on_buttonBox_accepted();
private:
Ui::Dialog *ui;
};
#endif // DIALOGWINDOW_H
Dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
DialogWindow::DialogWindow(QWidget *parent)
: QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
DialogWindow::~DialogWindow()
{
}
void DialogWindow::on_buttonBox_accepted()
{
emit transmit(ui->lineEdit->text());
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "dialog.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 on_pushButton_clicked();
void update(QString txt);
private:
Ui::MainWindow *ui;
DialogWindow *dlg;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
dlg = new DialogWindow(NULL);
connect(dlg,&DialogWindow::transmit,this,&MainWindow::update);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
dlg->show();
}
void MainWindow::update(QString txt)
{
ui->label->setText(txt);
}
In this line MainWindow MainWindow;, you create a new MainWindow, but you want to set the text on your existing MainWindow.
Instead you might want to pass a reference or pointer to the MainWindow to the dialog, once you create it.
If you pass your MainWindow as the parent of the QDialog, you could do it this way:
void WindowDialog::on_pushButton_clicked()
{
QString str = ui->lineEdit->text();
static_cast<MainWindow*>(parent())->setLabelText(str);
}
A safer version using dynamic_cast:
void WindowDialog::on_pushButton_clicked()
{
QString str = ui->lineEdit->text();
MainWindow* window = dynamic_cast<MainWindow*>(parent());
if (!window) {
throw std::runtime_error{"Parent was not a MainWindow"};
}
window->setLabelText(str);
}
I would like to map a radio buttons to a QDataWidgetMapper as per this forum thread. I am not sure though how to hook up the delegate mentioned. Could anyone explain this?
I already have .ui files that contain the radio buttons, among QLineEdits etc. Those are already hooked via a QDataWidgetMapper to a QSqlTableModel. Can I use the solution mentioned in the url above to add the existing radio buttons in the .ui field to the button group, and get the state into the DB?
My radio buttons are actually binary selections, so storing boolean values in the db would be sufficient. I do not want to use a checkbox because radio buttons make the selection more easily comprehensible to the user, in this case.
So far I have added includes to the example .h file
#include <QWidget>
#include <QButtonGroup>
#include <QVBoxLayout>
#include <QAbstractButton>
and created the .cpp file.
#include "buttongroup.h"
ButtonGroup::ButtonGroup(QWidget *parent) :
QWidget(parent)
{
m_buttonGroup=new QButtonGroup(this);
m_layout=new QVBoxLayout(this);
connect(m_buttonGroup,SIGNAL(buttonClicked(int)),this,SIGNAL(buttonClicked(int)));
setLayout(m_layout);
}
int ButtonGroup::getCheckedId()
{
int id=m_buttonGroup->id(m_buttonGroup->checkedButton());
return id;
}
void ButtonGroup::checkId(int id)
{
m_buttonGroup->button(id)->setChecked(true);
}
void ButtonGroup::addButton(QAbstractButton *button, int id)
{
m_buttonGroup->addButton(button,id);
m_layout->addWidget(button);
//connect(button,SIGNAL(clicked()),this,SIGNAL(buttonClicked()));
}
The delegate needs to be connected to the mapper.
I have created a sample project that works at http://scanrobot.fi/wp-content/uploads/2015/06/qradiobutton-qsqltablemodel.zip
Also at: https://github.com/savolai/qt_qradiobutton_qdatawidgetmapper_example
Here is the essence of what I needed to understand in practice:
QDataWidgetMapper* mapper = new QDataWidgetMapper(this);
mapper->setModel(model);
mapper->toLast();
QRadioButton *b1=new QRadioButton("a",this);
QRadioButton *b2=new QRadioButton("b",this);
RadioButtonDelegate *delegate=new RadioButtonDelegate(this);
ButtonGroup *group=new ButtonGroup(this);
mapper->addMapping(group,model->fieldIndex("radio"));
// set the delegate as the item delegate of mapper
mapper->setItemDelegate(delegate);
// connect value change in group to delegate so it can send appropriate signals
connect(group,SIGNAL(buttonClicked(int)),delegate,SLOT(commitMyData()));
group->addButton(b1,1);
group->addButton(b2,0);
Source for buttongroup.cpp:
#include "buttongroup.h"
ButtonGroup::ButtonGroup(QWidget *parent) :
QWidget(parent)
{
m_buttonGroup=new QButtonGroup(this);
connect(m_buttonGroup,SIGNAL(buttonClicked(int)),this,SIGNAL(buttonClicked(int)));
}
int ButtonGroup::getCheckedId()
{
int id=m_buttonGroup->id(m_buttonGroup->checkedButton());
return id;
}
void ButtonGroup::checkId(int id)
{
m_buttonGroup->button(id)->setChecked(true);
}
void ButtonGroup::addButton(QAbstractButton *button, int id)
{
m_buttonGroup->addButton(button,id);
}
buttongroup.h (nothing very new here compared to the original url):
#ifndef BUTTONGROUP_H
#define BUTTONGROUP_H
#include <QWidget>
#include <QButtonGroup>
#include <QVBoxLayout>
#include <QAbstractButton>
#include <QRadioButton>
class ButtonGroup : public QWidget
{
Q_OBJECT
public:
explicit ButtonGroup(QWidget *parent = 0);
Q_PROPERTY(int checkedId READ getCheckedId WRITE checkId USER true)
int getCheckedId();
void checkId(int id);
void addButton(QAbstractButton *button, int id);
signals:
void buttonClicked(int);
private:
QButtonGroup *m_buttonGroup;
QVBoxLayout *m_layout;
};
#endif // BUTTONGROUP_H
radiobuttondelegate.h (nothing very new here either):
#ifndef RADIOBUTTONDELEGATE_H
#define RADIOBUTTONDELEGATE_H
#include <QItemDelegate>
class RadioButtonDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit RadioButtonDelegate(QObject *parent = 0);
signals:
public slots:
void commitMyData();
};
#endif // RADIOBUTTONDELEGATE_H
radiobuttondelegate.cpp (or here):
#include "radiobuttondelegate.h"
#include <QDebug>
RadioButtonDelegate::RadioButtonDelegate(QObject *parent) :
QItemDelegate(parent)
{
}
void RadioButtonDelegate::commitMyData() {
QWidget *obj = qobject_cast<QWidget*>(sender());
emit commitData(obj);
emit closeEditor(obj);
qDebug() << "commitMyData";
}
Everytime i click my QPushButton which I have added with the UI Designer, the button stays clicked and the application crashes. When I remove the slot which the 'clicked()' signal of the button is connected to, I can click the button and the application behaves normal.
This is the header of the class that uses the UI:
#ifndef DARLEHENSRECHNER_H
#define DARLEHENSRECHNER_H
#include <QMainWindow>
#include "Darlehensgeber.h"
namespace Ui {
class Darlehensrechner;
}
class Darlehensrechner : public QMainWindow
{
Q_OBJECT
public:
explicit Darlehensrechner(QWidget *parent = 0);
~Darlehensrechner();
private slots:
void on_berechnenButton_clicked();
private:
Ui::Darlehensrechner *ui;
Darlehensgeber dg;
};
#endif // DARLEHENSRECHNER_H
And this is the cpp:
#include "darlehensrechner.h"
#include "ui_darlehensrechner.h"
Darlehensrechner::Darlehensrechner(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Darlehensrechner),
dg()
{
ui->setupUi(this);
}
Darlehensrechner::~Darlehensrechner()
{
delete ui;
}
void Darlehensrechner::on_berechnenButton_clicked()
{
dg.takeLoan(ui->kreditEdit->text().toFloat(),
ui->ratenEdit->text().toFloat(),
ui->zinsEdit->text().toFloat());
ui->dauerLabel_2->setText(QString::number(dg.getAmountOfInstallments()));
ui->betragLabel_2->setText(QString::number(dg.getAmount()));
}
I was able to simulate the Right-Click event by subclassing the QTableWidget:
header file:
#ifndef QRIGHCLICKTABLE_H
#define QRIGHCLICKTABLE_H
#include <QTableWidget>
#include <QMouseEvent>
class QRightClickTable : public QTableWidget
{
Q_OBJECT
public:
explicit QRightClickTable(QWidget *parent = 0);
private slots:
void mousePressEvent(QMouseEvent *e);
signals:
void rightClicked();
public slots:
};
#endif // QRIGHCLICKTABLE_H
cpp file
QRightClickTable::QRightClickTable(QWidget *parent) :
QPushButton(parent)
{
}
void QRightClickTable::mousePressEvent(QMouseEvent *e)
{
if(e->button()==Qt::RightButton)
emit rightClicked();
}
QRightClickTable *button = new QRightClickTable(this);
ui->gridLayout->addWidget(button);
connect(button, SIGNAL(rightClicked()), this, SLOT(onRightClicked()));
void MainWindow::onRightClicked()
{
qDebug() << "User right clicked me";
}
Now, right-click works correctly, but there are other problems with QTableWidget: all other mouse events, such as the left click to select a cell, no longer work.
Can you help me? I know I need to call the base class implementation in my override of mousePressEvent, you could show me how with a little piece of code?
Change your event handler like this :
void QRightClickTable::mousePressEvent(QMouseEvent *e) {
if(e->button()==Qt::RightButton) {
emit rightClicked();
} else {
QTableWidget::mousePressEvent(e);
}
}