Is there a way in Qt to handle situation when any widget of Window goes out of sight. I.e if a widget was in tab control and user have changed active tab, or if user just scrolls and widget goes offscreen, and also when it goes back on screen.
Is that possible to add some code to this two events?
Best if this can be done globally...
Is there a way in Qt to handle situation when any widget of Window goes out of sight. I.e if a widget was in tab control and user have changed active tab, or if user just scrolls and widget goes offscreen, and also when it goes back on screen.
The way the question asked makes one think that the widget show-hide-expose state changes need to be handled:
bool MyWidget::event(QEvent* pEvent)
{
if (pEvent->type() == QEvent::Show)
{
// event "shown"
}
else if (pEvent->type() == QEvent::Hide)
{
// event "hidden"
}
else if (pEvent->type() == QEvent::Expose)
{
// event "exposure changed"
// deal with QExposeEvent and evaluate the exposed region
// QExposeEvent* pExposeEvent = reinterpret_cast<QExposeEvent*>(pEvent);
}
return QWidget::event(pEvent);
}
Best if this can be done globally...
Event filter at the top level widget may solve that. Or you can override event() function for the top level widget but finding what exact widget was affected is another thing.
Refer to QExposeEvent description.
Related
I'm creating my first C++ wxWidgets application. I'm trying to create some kind of split button where the options are displayed in a grid. I have a custom button class which, when right-clicked on, opens a custom wxPopupTransientWindow that contains other buttons.
When I click on the buttons in the popup, I want to simulate a left click on the main button. I'm trying to achieve this through events, but I'm kinda confused.
void expandButton::mouseReleased(wxMouseEvent& evt)
{
if (pressed) {
pressed = false;
paintNow();
wxWindow* mBtn = this->GetGrandParent();
mBtn->SetLabel(this->GetLabel());
mBtn->Refresh();
wxCommandEvent event(wxEVT_BUTTON);
event.SetId(GetId());
event.SetEventObject(mBtn);
mBtn-> //make it process the event somehow?
wxPopupTransientWindow* popup = wxDynamicCast(this->GetParent(), wxPopupTransientWindow);
popup->Dismiss();
}
}
What is the best way to do this?
You should do mBtn->ProcessWindowEvent() which is a shorter synonym for mBtn->GetEventHandler()->ProcessEvent() already mentioned in the comments.
Note that, generally speaking, you're not supposed to create wxEVT_BUTTON events from your own code. In this particular case and with current (and all past) version(s) of wxWidgets it will work, but a cleaner, and guaranteed to also work with the future versions, solution would be define your own custom event and generate it instead.
I am using QSlider element in my app as a toogle switch. I took this project over from a colleage of mine who left. So far so good, except, that this switch has a black label around it. I can't really change the style and rework everything so, I am stuck with label and slider as switch.
I need to handle events from button clicked and button released. I do it like this-
bool CustomSlider::eventFilter(QObject *obj, QEvent *ev )
{
if (ev->type() == QEvent::MouseButtonRelease)
{
changeSliderValue();
}
if(ev->type() == QEvent::MouseButtonPress){
lastSaved = ui->horizontalSlider->value();
}
return QWidget::eventFilter(obj,ev);
And changeSliderValue()-
void CustomSlider::changeSliderValue()
{
int current = ui->horizontalSlider->value();
if(lastSaved==current){
if(current){
ui->horizontalSlider->setValue(0);
}else{
ui->horizontalSlider->setValue(1);
}
}
}
So, in short, if I click, it saves state of slider and when releasing it checks against saved state. I do it because QSlider has button pressed signal as well. I have put debug messages in my code and funny thing is debug messages fire. So my code works. If I call ui->horizontalSlider->value() I get the correct(changed) value But the slider is not moving. I have tried checking sequences, if it does not change value twice(it does not), I have tried calling repaint() and so far nothing works. Except if don't minimize(via minimize button) or click in different app(like web browser) and then I can see that slider moves to correct postion. I am completely confused. Has anyone encoutered something like this before?
I have a QMenu for which I've created a QColorModel action widget (It's effectively just a QStandardItemModel). My desired behavior is that when a user clicks one of the colors in the model, that the action should trigger, and the menu close. However, it doesn't seem to do that, even when I trigger the action manually.
I've tried manually hiding the menu, but it's a kludge because it won't hide parent menus which th menu may be attached to.
Here's the relevant section of code:
// color menu
m_colorMenu = new QMenu("color", this);
m_colorView = new QColorView(m_colorMenu);
m_colorViewAction = new QWidgetAction(m_colorMenu);
m_colorViewAction->setDefaultWidget(m_colorView);
m_colorView->setModel(new QStandardColorModel);
connect(m_colorView, &QColorView::clicked, [&](QModelIndex index)
{
QColor color = qvariant_cast<QColor>(index.data(Qt::DecorationRole));
if (m_pen.color() != color)
{
m_pen.setColor(color);
drawIcon();
drawColorIcon();
update();
}
//this->hide(); // kludge, didn't close all parent menus
m_colorViewAction->trigger(); // doesn't seem to cause menu closure
});
m_colorMenu->addAction(m_colorViewAction);
EDIT
I've also tried adding something to the effect of:
QMenu* menu = m_colorMenu;
do
{
menu->close();
menu = dynamic_cast<QMenu*>(menu->parent());
} while (menu);
but it also is fragile/kludgey because it assumes a) all widgets are properly parented, and b) that all the parents are actually supposed to be menus. In my case, they aren't.
If the containing menus aren't in the parentage tree, and the menu you want to close isn't the top level menu, there is no easy way to do this. That said, there is:
THE NUCLEAR OPTION
Adding this to the end of the lambda function
auto topLevelWidgets = qApp->topLevelWidgets();
for (auto widget : topLevelWidgets)
{
QMenu* menu = dynamic_cast<QMenu*>(widget);
if (menu)
{
menu->close();
}
}
will cause ALL top level menus to close once the action is triggered. This is a relatively OK way to accomplish what you want because:
one of the top level menus will contain the menu in question, and
never say never, but I can't think of a single case where you would have (or want) more than one menu open at a time, so most likely the only open menu tree you would close is the intended one.
I currently works on QT for my project. I implemented a MainWindow class which inherited from QMainWindow.
In MainWindow, I handled mouse wheel event like this:
void MainWindow::wheelEvent ( QWheelEvent * event )
{
if (event->modifiers().testFlag(Qt::ControlModifier)) {
if (event->delta() > 0) {
zoomInAct();
}
else if(event->delta()<0){
zoomOutAct();
}
}
}
The problem is: when I press CONTROL KEY and Wheel the mouse, the scroll bar alway scroll to top or bottom before reach my wheelEvent function. Would you please help to allow zoom-in/out when press control and wheel the mouse? (Not scroll the scroll bar)
Sorry for my bad english.
Looking at your current implementation here you have not specified event->accept() if you have added your own functionality and you don't want to propagate the event further to the parent. Try adding event->accept() in the if conditions where you have added your logic.
And try adding debug statement to test whether the event is reaching here or someone else is handling the event. By someone else I mean some other child widget. Some description of the UI and what widget is to be zoomed in would be helpful to further investigate the problem.
Make sure you read about the event system in Qt. Docs available here
Acctualy, there is a child widget that handle the wheel event first (default event handle is scroll the scrollbar).
Solution: override wheelevent in child widget to send it to parent widget (MainWindow) when the control key is pressed.
class WorkArea: public QWidget {
...
virtual void wheelEvent(QWheelEvent *event)
{
if(event->modifiers().testFlag(Qt::ControlModifier))
MainWindow::wheelEvent(event);
else
QWidget::wheelEvent(event);
}
...
}
I currently am attempting to display a tooltip on focusOutEvent of a widget. This tooltip basically validates the data inside the Widget (QLineEdit). Now the problem is I want to display the errors or issues using a tooltip . Here is what I am doing
void MyLineEdit::focusOutEvent(QFocusEvent *e)
{
QLineEdit::focusOutEvent(e);
QToolTip::showText( this->mapToGlobal( QPoint( 0, 0 ) ), "Something got it" );
emit(focussed(false));
}
Now the problem is the QTooltip is not displayed that is probably because the mouse is moving. My question is how can I make QTooltip be displayed and keep it there until I wish to turn it off ??
A tooltip will only show up if a QHelpEvent was intercepted. While you can send one from focusOutEvent using QCoreApplication::PostEvent and subclass QWidget::event like this
bool MyLineEdit::event (QEvent *event)
{
if (event->type() == QEvent::ToolTip) {
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
QToolTip::showText(helpEvent->globalPos(), "Something got it");
return false;
}
return QWidget::event(event);
}
, this has two undesirable consequences.
1) The event would still be triggered whenever a tooltip would be shown normally (that is, when your mouse pointer stays on the widget for a couple of seconds). You will have to implement some kind of recognition mechanism to distinguish your own help events from the rest.
2) The tooltip is only active while the respective widget is focused. So, displaying a tooltip when the focus is lost will show it only for a couple of seconds, until the next event loop is processed.
There might be a workaround for the latter, but at this point, it is probably better to leave the tooltips for their intended purpose and implement your own pseudo-tooltip which you would control directly.