I have a simple code; here I've two buttons, I press the first one and it shows a MsgBox. Then I press the "Okay", and it should call a connected action written in a second button, but it doesn't. Instead I get an error:
Object::connect: No such signal QMessageBox::buttonClicked(QMessageBox::Ok)
Object::connect: (receiver name: 'OpenFile_Bttn')
The code:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_OpenFile_Bttn_clicked(){
QFileDialog::getOpenFileName(this,tr("Open file"), "", tr(""));//Open a dialog "OpenFile"
}
void MainWindow::on_pushButton_clicked(){
QMessageBox msgBox;
msgBox.setText("Push button to choose a file");
//Connect clicking button in MsgBox to an action in OpenFile_Bttn button
QWidget::connect(&msgBox,SIGNAL(buttonClicked(QMessageBox::Ok)),
ui->OpenFile_Bttn, SLOT(on_OpenFile_Bttn_clicked()));
msgBox.exec();//Show MsgBox
}
Also I found an interesting thing, that the error message appears when a MsgBox popup, but not when I click the button "Ok" inside the MsgBox.
No need for signals here, exec returns the button clicked.
void MainWindow::on_OpenFile_Bttn_clicked(){
QFileDialog::getOpenFileName(this,tr("Open file"), "", tr(""));//Open a dialog "OpenFile"
}
void MainWindow::on_pushButton_clicked(){
QMessageBox msgBox;
msgBox.setText("Push button to choose a file");
//Connect clicking button in MsgBox to an action in OpenFile_Bttn button
if(msgBox.exec() == QMessageBox::Ok)
{
on_OpenFile_Bttn_clicked();
}
}
If you want to use custom buttons you can still call msgBox.buttonClicked() after exec to find out which button was clicked.
If you do this instead you get a compiler error, that way you can see something is wrong at compile instead of runtime error
QObject::connect(msgBox, &QMessageBox::buttonClicked, ui->OpenFile_Bttn, &QPushButton::clicked);
out of interest the above code is untested and probably wont compile but basicallt just do sender, signal, reciever, slot but use their class object to select signal and slots like shown above and then you will get an easier to spot compile error that tells you what could be wrong
Related
I have a simple flow
Click on QPushButton
QMenu with a couple of actions appears
Navigate through the QMenu using key clicks or mouse move.
(Triggering actions from code isn't a way, it should be a clean GUI test).
QTest::keyClick(m_menu, Qt::Key::Key_Down); - doesn't seem to work for me.
Simple example:
#include "mainwindow.h"
#include <QTest>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
m_button = new QPushButton("My Button", this);
m_button->setFixedSize(100,50);
m_menu = new QMenu("&Menu");
m_menu->addAction("&test1");
m_menu->addAction("&test2");
m_menu->addAction("&test3");
m_menu->addAction("&test4");
m_menu->addAction("&test5");
m_menu->addAction("&test6");
connect(m_button, SIGNAL (released()), this, SLOT (handleButton()));
}
void MainWindow::handleButton()
{
m_menu->exec(m_button->mapToGlobal(QPoint(20,20)));
QTest::qWait(2000);
for(int i = 0 ;i<=5;i++){
QTest::keyClick(m_menu, Qt::Key::Key_Down);
QTest::qWait(1000);
QTest::mouseMove(m_menu, QPoint(0,20));
QTest::qWait(1000);
}
}
MainWindow::~MainWindow()
{
}
Thanks to vahancho I found work around.
QMenu.exec() is executing synchronously. So, to have an opportunity to provide some input when menu is opened we should use next template:
QTimer::singleShot(0, [menu]()
{
//code that should be executed
});
menu->exec();
I want to create a combobox inside a message box and return the selected value to be used later.
I can do the same on the window itself but not sure how to do that inside a combobox.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->comboBox->addItem("Red");
ui->comboBox->addItem("Blue");
ui->comboBox->addItem("Green");
ui->comboBox->addItem("Yellow");
ui->comboBox->addItem("Pink");
ui->comboBox->addItem("Purple");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QMessageBox::about(this,"Choose color of rectangle", ui->comboBox->currentText() );
}
If I understand you correct you would like to show a combobox in a separate dialog window for the user to select some option.
One of the ways to do that, would be to subclass QDialog. If a combo field and a button to accept is sufficient the class could look as below:
class CustomDialog : public QDialog
{
public:
CustomDialog(const QStringList& items)
{
setLayout(new QHBoxLayout());
box = new QComboBox;
box->addItems(items);
layout()->addWidget(box);
QPushButton* ok = new QPushButton("ok");
layout()->addWidget(ok);
connect(ok, &QPushButton::clicked, this, [this]()
{
accept();
});
}
QComboBox* comboBox() { return box; }
private:
QComboBox* box;
};
To use the class object you can call exec to display it modally. Then you can verify whether the user accepted the choice by pressing the ok button and take proper action.
QStringList itemList({"item1", "item2", "item3"});
CustomDialog dialog(itemList);
if (dialog.exec() == QDialog::Accepted)
{
// take proper action here
qDebug() << dialog.comboBox()->currentText();
}
Similar approach is implemented in the QMessageBox class where a number of options can be specified to alter the displayed contents (for example button configuration or check box existance).
EDIT:
To use the sample code in your own project you should put the latter section I posted into your on_pushButton_clicked() slot. Substitute the itemList with your color names list. Then put the CustomDialog class to a separate file which you include in main and you should be good to go.
I have been trying to hide a stand alone dialog application when the user hits the typical close button (The one with the X in the corner usually next to the minimize button) I cam across this post:
Qt: How do I handle the event of the user pressing the 'X' (close) button?
which I thought would have my solution, but I get strange behavior when I implement it.
void MyDialog::reject()
{
this->hide()
}
When I hit the X Button the whole application closes (the process disappears) which is not what I want. Since my gui spawns with a command line, I setup a test system where I can tell my dialog to hide via a text command where I call the same 'this->hide()' instruction, and everything works fine. The dialog hides and then shows back up when I tell it to show.
Any ideas why the reject method is closing my app completely even when I don't explicitly tell it to?
Override the virtual function "virtual void closeEvent(QCloseEvent * e)" in your dialog class. The code comment will explain in detail.
Dialog::Dialog(QWidget *parent) :QDialog(parent), ui(new Ui::Dialog){
ui->setupUi(this);
}
Dialog::~Dialog(){
delete ui;
}
//SLOT
void Dialog::fnShow(){
//Show the dialog
this->show();
}
void Dialog::closeEvent(QCloseEvent *e){
QMessageBox::StandardButton resBtn = QMessageBox::question( this, "APP_NAME",
tr("Are you sure?\n"),
QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
QMessageBox::Yes);
if (resBtn != QMessageBox::Yes){
//Hiding the dialog when the close button clicked
this->hide();
//event ignored
e->ignore();
//Testing. To show the dialog again after 2 seconds
QTimer *qtimer = new QTimer(this);
qtimer->singleShot(2000,this,SLOT(fnShow()));
qtimer->deleteLater();
}
//below code is for understanding
//as by default it is e->accept();
else{
//close forever
e->accept();
}
}
My buttonGroup is already load with 45 buttons i want do anything after a button is clicked this is my code:
#include "escogerpuesto.h"
#include "ui_escogerpuesto.h"
#include <iostream>
EscogerPuesto::EscogerPuesto(QWidget *parent) :
QWidget(parent),
ui(new Ui::EscogerPuesto)
{
ui->setupUi(this);
ui->buttonGroup->connect(ui->buttonGroup, SIGNAL(clicked()), this, SLOT(asientoClickeado));
}
EscogerPuesto::~EscogerPuesto()
{
delete ui;
}
void EscogerPuesto::asientoClickeado()
{
std::cout<<"click en asiento";
}
Button group contains signal with parameter QAbstractButton* or int, so you should connect this signal with slot which has an appropriate parameter.
ui->buttonGroup->connect(ui->buttonGroup, SIGNAL(buttonClicked(QAbstractButton*)),
this, SLOT(your_slot(QAbstractButton* ));
Or you can connect each button with some slot.
You can read more here: http://harmattan-dev.nokia.com/docs/library/html/qt4/signalsandslots.html
and here http://harmattan-dev.nokia.com/docs/library/html/qt4/qbuttongroup.html
I am trying to create a drop down button using QToolBar.
I tried to do that using the following strategy:
http://qt-project.org/forums/viewthread/5377
The problem is that the button doesn't respond immediately when I click on it. It takes several clicks to make the menu appear.
I guess I am putting the code in the wrong place, but where else should I put it?
Here is my code:
Proto::Proto(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Proto)
{
ui->setupUi(this);
QMenu *menu = new QMenu("Menu");
QWidgetAction *action = new QWidgetAction(this);
QPushButton *button2 = new QPushButton("Click me", menu);
action->setDefaultWidget(button2);
menu->addAction(action);
ui->btnVolume->setMenu(menu);
}
Please, anyone can help me?
Thanks in advance,
Seems like you forget to connect your button to a slot (or at least, it's not shown in the piece of code you posted). I just added the connect() statement like that
QPushButton *button2 = new QPushButton("Click me", menu);
connect(button2, SIGNAL(clicked()), SLOT(dosmth()));
action->setDefaultWidget(button2);
and then implemented this simple dosmth() Q_SLOT
void MainWindow::dosmth() {
qDebug() << "Hi";
}
and at each button click, i get this on the console:
Hi
Hi
Hi