I have a checkable pushbutton set to exec/close a dialog widget that I have created.
My idea is when the pushbutton is checked, it will close the dialog widget. If it's not checked, it should open the dialog widget. But I am unable to get it to work. It keeps on opening instances of the dialog widget. I wanted to open one instance of the dialog widget only. Could anyone please help?
MainDlg::MainDlg()
{
connect(dialogButton, SIGNAL(clicked()), this, SLOT(setDialog()));
}
void MainDlg::setDialog()
{
SetDialogDlg setDlg;
if(dialogButton->isChecked())
{
setDlg.close();
}
else
{
setDlg.exec();
}
}
There are a few things that are wrong in your code. First thing is, your SetDialogDlg object will only exist inside your MainDlg::setDialog() function. Once this function finishes your SetDialogDlg object will be destroyed.
Then you are creating a new instance of SetDialogDlg every time MainDlg::setDialog() function is called. And you are trying to close a dialog that hasn't been shown yet.
Then there is a problem with setDlg.exec(). This is a blocking function. So you shouldn't even be able to push your dialogButton once the dialog has been shown.
To solve these problems you should have a member variable in your MainDlg class.
//maindlg.h
...
public:
SetDialogDlg *myDialog;
...
//maindlg.cpp
MainDlg::MainDlg()
{
...
myDialog = new SetDialogDlg(this);
...
}
Then inside your MainDlg::setDialog() function, call QWidget::show() instead of QDialog::exec().
void MainDlg::setDialog()
{
if(dialogButton->isChecked())
{
myDialog->close();
}
else
{
myDialog->show();
}
}
Related
I just want to disable form's close button while doing a task(by QThread), So I connected the thread's signal "started()" and "finished()" to my two slots, for controlling my form's close button.
//...
m_pTestThread = new TestThread();
connect(m_pTestThread, SIGNAL(started()), this, SLOT(onThreadStart()));
connect(m_pTestThread, SIGNAL(finished()), this, SLOT(onThreadFinish()));
m_pTestThread->start();
//...
void QTest::onThreadStart()
{
this->setWindowFlags(this->windowFlags() & (~Qt::WindowCloseButtonHint));
}
void QTest::onThreadFinish()
{
this->setWindowFlags(this->windowFlags() | Qt::WindowCloseButtonHint);
}
After the thread started, my form was hidden... that is strange.
So I call show() after setWindowFlags() function to avoid this problem,
but still don't know why this happened...
Is this the expected behaviour? Should I call show() after setWindowFlags()?
Check the documentation for setWindowFlags here:
Note: This function calls setParent() when changing the flags for a
window, causing the widget to be hidden. You must call show() to make
the widget visible again..
I need to block specific buttons on an MMI.
I implemented a button blocking function in a subclass of QPushButton.
For this, I used the clicked() signal and blocked the button with blockSignals(true).
This means that with each button clicked on my MMI, 2 SLOTS are always called.
But when calling the blocking of a specific button, I get the first SLOT (clicked()) of my subclass, in which I block the button, then I then arrive in the original SLOT linked to this button, which is still called despite the blocking (the first time only).
How can I in my QPushButton subclass know the subsequent SLOTs linked to this button and avoid them (delete them)?
void QbtnStandardButton::slotButtonClicked(void)
{
if (modeProtection)
{
// Special mode to protect/unprotect the button
if (isProtected())
{
// Reset the protection
this->blockSignals(false);
}
else
{
// Set the protection: button will be unclickable
this->blockSignals(true);
}
modeProtection = false;
}
if (isProtected())
{
QMessageBox *pMsgBox = new QMessageBox(QMessageBox::Information,
"Protection",
"This button is protected!",
QMessageBox::Ok);
pMsgBox->exec();
pMsgBox->deleteLater();
// Here: remove subsequent SLOT of this button ?
}
}
I think it's very difficult if not impossible to find SLOTS linked to a button.
I worked around the problem by using an eventFilter() instead of a SIGNAL() in my base class.
In this case, I can filter the "clicked()" event before it is reissued.
for(auto s :listofPossibleValues){
// item =s;
action = myMenu.addAction("Set Value to "+s);
connect(action,SIGNAL(triggered(bool)),this,SLOT(menuClicked()));
}
void MainWindow::menuClicked(){
value = new QStandardItem(item);
model->setItem(mainindex->row(),mainindex->column(),value);
}
I add actions and connect signals to the slot to my menu using the code above. Previously I was using the item to be the text. But it will only work for last item.
Does anyone at least know how to get the action that I clicked on?
How can I make it work for each individual item rather than just the last one?
Use the triggered signal of QMenu:
connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(menuClicked(QAction*)));
Then, in menuClicked():
void MainWindow::menuClicked(QAction *action) {
// do something with action
}
In my Qt application, I want to use a checkbox to do A when it's toggled to unchecked, and do B when toggle to checked. The checkbox is hooked to foo(int).
connect(myCB, SIGNAL(stateChanged(int)), this, SLOT(foo(int)));
There's a problem when the sanity check fails (eg. some variable got invalid values), I want to just show error message and remain everything unchanged. So I toggle the checkbox again to revert it back to where it was. But it seems this action would trigger the callback function foo(int) again, which mess up everything. I don't want it to trigger the callback in this situation. How should I do? Or is there a better way? See the pseudo code below.
void foo(int checkState)
{
if (checkState == Qt::Unchecked) {
if (!passSanityCheck()) {
// show error message
checkBoxHandle->toggle();
return;
}
// do A when it's unchecked
}
else {
if (!passSanityCheck()) {
// show error message
checkBoxHandle->toggle();
return;
}
// do B when it's checked
}
return;
}
Connect QCheckBox::clicked(bool checked) signal to your slot:
QCheckBox *cb = new QCheckBox(this);
connect(cb, SIGNAL(clicked(bool)), this, SLOT(toggled(bool)));
This signal is not emitted if you call setDown(), setChecked() or toggle().
I have a Qt main window where I call another window, actually a kind of submenu wich contains parameters for the first one; here is a part of this main window :
void Ui_MainWindow::createSignals()
{
connect(actionDisk_galaxy, SIGNAL(triggered()), this, SLOT(ICMenu()));
}
void Ui_MainWindow::ICMenu()
{
qmenu = new QMainWindow;
DiskMenu = new Ui_DiskGalMenu;
DiskMenu->setupUi(qmenu,this);
setInitialDiskMenuPosition(qmenu, this);
qmenu->show();
}
As you can see, I call another QMainwindow ("qmenu"); here's the code of this new window (whose type is "Ui_DiskGalMenu"):
void Ui_DiskGalMenu::createMenuSignals()
{
connect(pushButton_4, SIGNAL(clicked()), this, SLOT(closeMenu()));
}
void Ui_DiskGalMenu::closeMenu()
{
close(true);
}
After setting parameters in this sub-menu, I would like to close it with a pushButton (here "pushButton_4").
My problem is that when I click on "pushButton_4", this window doesn't close.
I have also tried to reimplement closeEvent but without success.
This function call looks like a mistake:
close(true);
QWidget::close() doesn't take any parameters. So what you're doing here, is call the close(int) function of the C library (for closing file descriptors.) bool is implicitly converted to int, so you end up with this call:
::close(1);
Which is (probably) closing stderr.
You can see what's happening if you change the above to:
this->close(true);
You should get a compilation error since no such function exists. So the correct call would have been:
this->close();
However, QWidget::close() is already a slot, so you don't need the Ui_DiskGalMenu::closeMenu() function at all. All you need is connect to the close() slot to begin with:
connect(actionDisk_galaxy, SIGNAL(triggered()), this, SLOT(close()));
If you need to do more stuff when the window closes, you can override closeEvent() which will be called before the window gets closed.