I have implemented a widget which has a grid (QTableView object) and two scollbars, one horizontal and one vertical. I have implemented a function that fetches the data to be shown in the grid from a database. I want when the user pressed the arrow from the scroll bar in order to make a single step the application instntly fetch the data. On the contrary when the user scrolls with the whell or move the slider the app don’t fetch the data instantly. More specifically i want the data to be fetched when the user stops the slider for some time or releases the slider. For this reason i have used sliderReleased() signal. Moreover, i have write, as a user from this forum suggested, this code for the vertical scrolling actions.
void handleVTableScrollAction(int action)
{
switch(action)
{
case QAbstractSlider::SliderSingleStepAdd:
case QAbstractSlider::SliderSingleStepSub:
drawGrid();
requestSlot();
break;
case QAbstractSlider::SliderMove:
drawGrid();
m_Timer.start(500);
}
the timer is connected to a slot the fetches the data
connect (&m_Timer, SIGNAL(timeout()), this, SLOT (requestSlot()));
So my problem is when i wnt to make a single step (by pressing the arrow key) the app don’t responds instantly. When i press the arrow for the firtst time nothing seems to be done, but when i am pressing second time the grid follows the movement. All the other movements(wheel and slider move) work fine.
So i tried to use the valueChange() signal just like this:
connect(ui->verticalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(sliderSigleStep()));
connect(ui->verticalScrollBar, SIGNAL(sliderMoved(int)), this, SLOT(sliderMoveSlot()));
In this way the single step works fine, but the sliderMoveSlost is never called as the valueChanged singal is always emmited first.
Is there an explantion for my first issue?
Can i call a function with the condition that two signals emmited? For example call the sliderMoveSlot only if sliderMove(int) and valueChanged(int) singals emmited and call sliderSingleStep() if only valueChanged(int) is emmited.
Related
Consider this situation:
For a button on a widget: if there is a chance that the button's clicked() slot is delivered (processed) after the widget (that contains the button) gets hided by explicitly calling hide()?
For instance, suppose that there is a timer, and in its timeout() slot, widget.hide() gets called. Coincidentally, The user clicks the button just at the same time time is up.
The question is: Is there a chance that the button's clicked() slot get called after timer's timeout() slot (which hides the widget that contains the button)?
No, the main thread in synchronous respect the GUI actions, so you cannot change the visibility of an object living in the main thread (like your QPushButton) exactly at the same time an user is clicking on it. Also, unless you 're on a multithread app with different events loops, your QTimer will be processed in the main thread too, so it is synchronous respect the UI. In few words: you may get a millisecond concurrence (clicking immediately before hiding it), but not actual parallelism.
If you care about this, maybe you can set a small delay before actually processing the click, just to check if the button was clicked but immediately hidden. In this case you can ignore the user input but it would be confusing. Another option would be to delay hiding the button if it was clicked, so the user doesn't get the wrong visual feedback.
I want to create a behavior in which when I finished editing a text, the focus either moves to the next child or clear the focus on the current field when I pressed "Enter". I would then get one signal to trigger a part of the code.
When I do editingFinished() and reimplement keyReleaseEvent() for "Enter" with focusNextChild() or clearFocus(), I get two signals for the text edit, one when the "Enter" is pressed, and one when the focus is change via focusNextChild() or clearFocus(). The extra signal is undesirable.
If I do returnPressed() and reimplement keyReleaseEvent() for "Enter" with focusNextChild() or clearFocus(), it would only create one signal, but I also want the signal to be created when the user exits the lineEdit via tab() or mouse click on any other line items, which would not be the case if I use returnPressed()
Ideally, I could use a signal when a lineEdit loses focus, its connected to a slot that runs the code and I can reimplement the keyReleaseEvent() for "Enter" to set the focus, but it doesn't seem like such a signal exists in Qt.
Does anyone have recommendations on how to implement this or a better way to approach it?
You can connect/disconnect signals when you want. For example, when you focus in the QLineEdit you can connect both listed signals to slot which will disconnect those two connections and move focus to the next child. Thus, you will have only one signal processed.
Another solution - you can call QLineEdit.blockSignals(true) in the beginning of the slot and call QLineEdit.blockSignals(false) in the end of the slot. In this case whatever you do in the slot you will not trigger any signal in QLineEdit and no duplicates will arise.
I have a QTableView that's connected to a QAbstractTableModel subclass. I'm editing the data owned by the model in response to user input in a different control (not the QTableView), and then I'm calling a method on the model that emits the dataChanged event:
void CharacterModel::characterChanged(int idx)
{
emit dataChanged(index(idx, 0), index(idx, (int)kNumColumns));
}
This works, as long as the QTableView is focused. As soon as it's not, it no longer shows the updated data. If I focus it again, it updates immediately. For example, I modified my code that's calling the above method to call setFocus() on the table view right afterwards, and everything is fine - except that my editing control loses focus every time I do anything. Not OK. I have several editing controls, including spin boxes; if I click on the spin box arrow, the FIRST update is displayed (because the table view is still focused), but then the spin box gets focused and all subsequent changes don't get displayed.
Anybody have any idea what's going on? This seems to be extremely well-defined behavior, but I can't find any reference to it anywhere.
Thanks,
Aaron
I think I've solved this. Turns out the solution is to call tableView->viewport()->repaint() after the dataChanged event fires. Calling tableView->repaint() doesn't do it.
Problem
Windows has a system setting that will cause the mouse pointer to jump (move) to a new focus element automatically, e.g. the default button of a dialog that pops up. While the advantage is an increase in speed and a reduction of mouse movements, it has a disadvantage:
If this happens just when before the user clicks on another element, the user is unable to abort his/her action in time and will immediately accept the dialogs default button because the focus is moved by the system. Usually this may entail cumbersome work to retrace the steps up to this point (think a file chooser dialog that forgot the very long path you input previously) but it could also mean triggering an irreversible process (e.g. file deletion).
Aim
Essentially I would like to disable the dialog's inputs for a small amount of time, just enough to prevent an inadvertant mouse click or keyboard button press.
Question
It comes down to a C++ question, namely how to access the base classes' objects (GUI widgets) from the inheriting class, i.e.
disable the button widgets of a QMessageBox
start a single shot QTimer and connect it to a slot that
enables the previously disabled widgets
(As alternative, I probably could reimplement input event handlers that suppress all input for a specific amount of time, but although I intend to keep that time very short (e.g. 100 ms), the user is not informed of the disabled input using that method.)
A simple class derived from QDialogBox can be found at http://www.qtforum.org/article/24342/messagebox-auto-close-mouse-event-close.html.
Do you need to use one of the "native"-ish message boxes provided by the QMessageBox static functions?
Otherwise, that's pretty simple to achieve, by building a QMessageBox and adding standard buttons to it:
QMessageBox *messageBox = new QMessageBox;
QPushButton *okButton = messageBox->addButton(QMessageBox::Ok);
okButton->setEnabled(false);
// use a QTimer to add logic to reenable the button
// use QCursor to move the mouse cursor on the button
// add a nice countdown in the button's label, like Firefox does
// add other nice UX touches as wanted
Last points are left as an exercise to the reader :)
To en/disable the buttons in QMessagebox one would need access to them.
qmessagebox.cpp uses buttonBox = new QDialogButtonBox; and the addButton() method
d->buttonBox->addButton(button, (QDialogButtonBox::ButtonRole)role);
d->customButtonList.append(button);
But I don't understand Qt internals and am unable to find these in qmessagebox.h and thus fail to find out if there is a chance to access the buttons..
Okay, using Qt, I'd like to know how to detect the current state of the mouse at any point in time - without a MouseEvent.
Using QCursor::pos(), you can get its position, but is there a way to determine the current state of the buttons?
Basically, I'm looking to verify the state of the mouse when a timer goes off, so it won't be related to any particular MouseEvent, and so there's no MouseEvent to query. I need to know how to query for the mouse's state - in particular the state of the buttons - without having a MouseEvent.
Oh, and I'm using Qt 3, so if such a function has been added in Qt 4 but isn't in Qt 3, it doesn't help me much (though it would still be nice to know about).
Qt::MouseButtons QApplication::mouseButtons () [static]:
Returns the current state of the buttons on the mouse. The current
state is updated syncronously as the event queue is emptied of events
that will spontaneously change the mouse state (QEvent::MousePress and
QEvent::MouseRelease events).
It should be noted this may not reflect the actual buttons held on
theinput device at the time of calling but rather the mouse buttons as
last reported in one of the above events. If no mouse buttons are
being held Qt::NoButton is returned.
Edit: hmm, I just noticed you asked about Qt3.3. This answer applies to Qt4 I'm afraid.
Is it a hard requirement that you don't use MouseEvent? Or can you use MouseEvents indirectly?
If you create a boolean variable for every button and update it with mouse pressed / released events then you could just look at the values of the relevant booleans when the timer goes off.
Update for Qt5 (5.3.2):
if (QGuiApplication::mouseButtons() == Qt::LeftButton) { ... }
I am using a QApplication, but there is no mouseButtons() function there. You will need to include <QGuiApplication>