I make a color picker based on Qt 5.4.1. It works as this: when user clicked one QToolButton, it shows the QColorDialog. I use the QToolButton's 'released()' signal. Now the problem is, when I close the QColorDialog, the released() signal fired again. But when I change it to QPushButton, the problem gone.
My toolbutton has no menu with it. I wonder if QToolButton is designed as this, or it's just a bug? Because other reason, I can't use QPushButton. So, is there some workround to make toolbutton work?
Update:
I tried put only the code below in the released slot:
static int n = 0;
qDebug() << Q_FUNC_INFO << ++n;
return;
the counter is increased 2 every click. So it should has nothing with the QColorDialog.
I finally find the reason. I've never noticed Qt has the ability to connect signals and slots automatically. That is, QMetaObject::connectSlotsByName(). I accidently give my slot a name like
void on_<object name>_<signal name>(<signal parameters>);
style, this is just the style what "QMetaObject::connectSlotsByName()" needed. So, Qt automatically connect the released() signal to my slot. And I manually connect them too. In Qt, connect a signal twice, it will fire twice, even the sender and receiver is the same!!!!
Related
I have a child QDialog, when a button is pressed from it a socket is opened from QtConcurrent, and if there's an error an alert dialog is shown.
But if the user closes the child QDialog to return to the main window the signal cannot be received by the child QDialog slot.
I tried to broadcast the signal to parentWidget, but the program crashes, because this->parentWidget() doesn't exist anymore.
I use this code to emit the signal and connect it to the slot
connect(this, SIGNAL(errorTcpSignal(QString)), this, SLOT(displayTcpError(QString)));
connect(&t, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),[=](QAbstractSocket::SocketError err){
emit errorTcpSignal("Error while changing game settings \n" + QVariant::fromValue(err).toString());
});
Is there a way to solve this issue?
Thank you very much.
SOLVED:
emit the signal from the child widget, but set the connection from the father widget.
I am opening a QDialog which contains a QLineEdit. I want the QLineEdit to have keyboard focus initially, with the blinking cursor as a visual cue. Simple, right?
Calling line_edit->setFocus() has no effect.
Calling line_edit->grabKeyboard() gives it input focus BUT
the blinking caret doesn't move to line_edit
if I click into a different QLineEdit, the blinking caret goes there but keypresses are still delivered to line_edit
If I do neither, I have to click into line_edit to get the caret and input focus. Looking at the source code for QLineEdit::mousePressEvent it seems that the critical function is QWidgetLineControl::moveCursor, but that's not accessible via the public API and peeking further into the source doesn't show anything promising.
So how do I move the damn keyboard input cursor?
How do I set the keyboard input cursor to QLineEdit widget?
From one of replies to this thread: Set QLineEdit focus in Qt.
QTimer::singleShot(0, line_edit, SLOT(setFocus()));
Before I found that elegant way to set focus I developed my own:
void forceFocus(QWidget* widget)
{
// unless set active, no stable set focus here
widget->activateWindow();
// the event object is released then in event loop (?)
QFocusEvent* eventFocus = new QFocusEvent(QEvent::FocusIn);
// posting event for forcing the focus with low priority
qApp->postEvent(widget, (QEvent *)eventFocus, Qt::LowEventPriority);
}
The accepted answer did not work for me. The qApp->focusWidget() is correctly updated, but the caret does not appear. I tried a great deal many variations on things like grabKeyboard(), setReadOnly(), setCursorPosition(), activateWindow(), cursorBackward(), cursorForward(), cursorFlashTime() and so on, but to no avail. They revealed that the cursor was in the right place, just not being drawn.
Not sure how my scenario differs to the OP. Like in Activate cursor in QTextEdit I'm calling setFocus() after responding to another button press but otherwise pretty standard.
Finally, using the clues in the OP, this sledgehammer approach got me there:
QPoint pos(line_edit->width()-5, 5);
QMouseEvent e(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, 0);
qApp->sendEvent(line_edit, &e);
QMouseEvent f(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, 0);
qApp->sendEvent(line_edit, &f);
In my Qt program, I have modal QDialogs that are meant to halt everything and not continue execution of code until after it is dismissed. And it works for the function it's in--I put a breakpoint on the next line of code after qDialog::exec() and it doesn't break until after I dismiss the dialog.
However, there is a QTimer connected to a slot on its timeout, and it will continue to go even when the modal dialog is up and execute the code in its slot.
I suppose I could stop the timer before showing the modal dialog. However, there may be cases when the dialog is in a totally different class than the timer. Is there a way to truly halt execution of the program until the QDialog is dismissed?
Example:
QTimer* pTestTimer = new QTimer( this );
connect( pTestTimer , SIGNAL( timeout() ), this, SLOT( timerSlot() ) );
//Slot code elsewhere
void cMyClass::deleteMeTimerSlot()
{
qDebug() << "See me during modal?";
}
//starting a modal dialog
pTestTimer->start( 1000 );
QDialog* pModalDlg = new QDialog( this, Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint );
pModalDlg->setModal(true);
pMOdalDlg->exec();
Output still shows "See me during modal?" while in exec();
I suppose I could stop the timer before showing the modal dialog.
However, there may be cases when the dialog is in a totally different
class than the timer.
Yes, you can do operate with all the timers accessible within the parent context (it seems like you look for generic solution).
// Halt all the timers within parent context.
// If all the timers have parent maybe the top app widget pointer
// should be used for parentObj
QList<QTimer*> listOfTimers = parentObj->findChildren<QTimer*>(
QString(), Qt::FindChildrenRecursively);
for(QTimer* pTimer : listOfTimers)
pTimer->stop();
Is there a way to truly halt execution of the program until the QDialog is dismissed?
Unless you mean stop all the threads: No, QDialog is part of the program and does not imply halting any execution but modal dialog runs in own event loop and only prevents user from operating the other program UI. I suppose you can probably restart all stopped timers after exiting the modal dialog.
pModalDlg->exec();
// restart all the timers within parent context
for(QTimer* pTimer : listOfTimers)
pTimer->start();
You can also peek at Qt source code (at QDialog and event loop it uses) and create your own sophisticated dialog class with very specific event loop for it.
I've made my first qt window. Now I'd like to make my first dialog, using qt. I have just finished creating the dialog, which is basically made of a QDialogButtonBox, and now I'd like to connect it to the window. I have two beginner's questions:
How can I retrieve how the dialog was closed (ok pressed or cancel pressed) from the window.cpp, which creates a new dialog, and then calls dialog->show() ?
Where and how to destroy the dialog pointer ?
If you use dialog->show() then I assume it's non-modal dialog.
If you have created QDialogButtonBox and connected its signals with accept() and reject() slots of your dialog as documentation shows, then your dialog will emit finished(int) and additionally accepted() or rejected() signals by which you can determine how it was closed.
If you need more customized behavior, then you can reimplement closeEvent(QCloseEvent *event) or create your own singnals.
If you need to delete your dialog you can use setAttribute(Qt::WA_DeleteOnClose, true);, which will delete instance on close.
you can use one flag, and signal and slot.
when put OK flag=1 , and when put cancel then flag=-1; and then use signal.
in in the window.h write code how to handle that flags with 1 simple slot.
for destroying the pointer you can use signal and slot in your Dialog and tell when user push
Ok, or Cancel , or exit (up- right (red cross)) go to slot in call the Destructer of dialog
and also you that you better set parent of dialog to window.
First Question:
When you want to show the dialog,just construct it,using myDialog *d = new myDialog(this)(the this pointer will make sure that you havn't to delete the pointer you created 'cause Qt will handle this if you specified the dialog's parent). And use d->exec() if you need a modal dialog, or d->show() to make it non-modal;
Second Question:
Once your specified the dialog's parent object, all u need is just use it and leave alone the memory managent,Qt will do this for you. Also you can use d->setAttribute(Qt::WA_DeleteOnClose,true) to make it destroy itself when it is closed.
Remember to link the QDialogButtonBox to your dialog's actions.
New to QT just playing around with it to see if its something I will enjoy using and if so would like to go on and learn the program in depth.
Struggling a bit with the button concept. I have created a button and a textedit area. I want to add a string of text into the textedit window when the button is pressed.
I can't seem to find anything on google or the QT wiki to achieve this. Can someone point me in the direction so I can at least get started and have a play with this great tool.
In Qt signals and slots are being used to communicate between the objects. This should provide you with the necessary information to get you started.
A signal is emitted when a particular event occurs. Qt's widgets have many predefined signals, but we can always subclass widgets to add our own signals to them. A slot is a function that is called in response to a particular signal. Qt's widgets have many pre-defined slots, but it is common practice to subclass widgets and add your own slots so that you can handle the signals that you are interested in.
So, in your particular case you need to connect the QPushButton clicked() signal with your custom slot that does what is needed (add the text to the textarea):
QPushButton * btn = new QPushButton("Button", this);
connect(btn, SIGNAL(clicked()), this, SLOT(onBtnClicked()));
And we need to declare our slot in the header:
private slots:
void onBtnClicked();
And define it:
void MySpecialWidget::onClick()
{
// Do what is to be done
}
If you have done everything correctly it should work... Otherwise have a look at the console to see if there are any messages looking like:
Object::connect: No such slot MySpecialWidget::onClick() in ...
or
Object::connect: No such signal ....
They should give you a hint about what is going on.
Finally I recommend to have a look at the broad set of Qt examples.