When i enter the keypressevent while pressing on a combobox, keypressevent is not triggered. Is there a way to still get events, when another widget is active?
def keyPressEvent(self, event):
if event.key() == 49: #49 = number 1 on keyboard
self.takeScreenshot()
Eventfilter:
def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.KeyPress:
if event.key() == Qt.Key_Delete:
print datetime.datetime.now().time()
return QtGui.QWidget.eventFilter(self, obj, event)
even using eventFilter, when i am clicking on a combobox, the event is not propagated to this function.
It's a C++ example but I think you will find the same for Python:
Sometimes an object needs to look at, and possibly intercept, the events that are delivered to another object. For example, dialogs commonly want to filter key presses for some widgets; for example, to modify Return-key handling.
bool FilterObject::eventFilter( QObject* object, QEvent* event )
{
if ( ( object == target ) && ( event->type() == QEvent::KeyPress ) )
{
QKeyEvent* keyEvent = static_cast< QKeyEvent* >( event );
if (keyEvent->key() == 49) // Better to use Qt::Key_*
{
return true;
}
else
{
return false;
}
}
return false;
}
So I suggest you to use the eventFilter( ... ).
Related
Ok I did it. It works fine. Thanks for help. Here is my code. Now I only need to call my command button in a differend form to disable it and create a info there. Anyone could look about it ? In my code I got reference errors.
[ExtensionOf(formdatasourcestr(ProdTableListPage, ProdTable))]
final class ProdParmReportFinishedActiveWG_Extension
{
public int active()
{
int ret;
next Active();
{
ProdTable tableBuffer = this.cursor();
ProdTable prodtable;
if(tableBuffer.ProdId == tableBuffer.CollectRefProdId
&& tableBuffer.ProdStatus != ProdStatus::ReportedFinished)
{
select firstonly RecId,ProdId from ProdTable where
ProdTable.CollectRefProdId == tableBuffer.ProdId
&& ProdTable.Prodstatus != ProdStatus::ReportedFinished
&& tableBuffer.RecId != prodtable.RecId;
{
Global::info(strFmt("%1 , %2",
prodtable.prodid, prodtable.recid));
// FormButtonControl mybutton = this.FormRun().design().controlname(formControlStr(ProdParmReportFinished, Ok)) as FormButtonControl;
// mybutton.enabled(false);
}
}
else
{
Global::info(strFmt("%1 , %2, %3, %4",
tableBuffer.prodid, tableBuffer.CollectRefProdId, tableBuffer.InventRefType, tableBuffer.ProdStatus));
}
}
return ret;
}
}
"I want to use this code everytime user changes his actual row but instead it runs just once and apply to all my rows."
Use the selectionChanged() method instead of active().
In fact most use cases where you think you should use active(), you're probably looking for selectionChanged() (or the OnSelectionChanged event for handlers) instead.
I started working with QT and want to program a little game named Pong ( 2 player and a ball). The left player should be moved with the keys 'W' and 'S', the right player with the arrow keys up and down. I have a class Game to handle my animation. There I have an eventfilter to handle the keyPress
bool Game::eventFilter(QObject *target, QEvent *e)
{
Q_UNUSED(target);
bool handled = false;
if(e->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = (QKeyEvent *)e;
if(keyEvent->key() == Qt::Key_W)
{
leftPlayerDir = ((leftPlayerDir == 0) ? 5 : leftPlayerDir);
handled = true;
}
else if(keyEvent->key() == Qt::Key_S)
{
leftPlayerDir = ((leftPlayerDir == 0) ? -5 : leftPlayerDir);
handled = true;
}
else if(keyEvent->key() == Qt::Key_Up)
{
rightPlayerDir = ((rightPlayerDir == 0) ? 5 : rightPlayerDir);
handled = true;
}
else if(keyEvent->key() == Qt::Key_Down)
{
rightPlayerDir = ((rightPlayerDir == 0) ? -5 : rightPlayerDir);
handled = true;
}
}
return handled;
}
and in my class Pong, where I set up the Mainwindow and handle the buttons, I have a line to install the eventfilter
ui->animation->installEventFilter(game);
If I start my program the animation is working, but the players are not moving on keyPress and I don't know why. Some ideas?
I'm developing a virtual musical keyboard that allows you to press keys on your keyboard and have it play notes. So in my MainWindow class I have reimplemented keyPressEvent. I would like to ignore events generated by modifiers (Control, Alt, Shift, etc.), as well as events generated by other non-character keys such as Tab, Backspace, and Enter. Something like this would be ideal:
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if (!event->key().isCharacter()))
{
event->ignore();
return;
}
// handle the event
}
Is there a way to do something like that (short of testing every possible non-character key individually)? If not, is there at least a way to easily ignore the event if it is a modifier?
Looks like you want QKeyEvent::text().
The accepted answer is unfortunately incomplete. If you press Ctrl+C, then QKeyEvent::text() will return "\x03" (^C "End of Text").
That is not an empty string.
I decided to look inside the Qt source code, since they need to handle this problem for QLineEdit as well:
In QLineEdit::keyPressEvent:
d->control->processKeyEvent(event);
src/widgets/widgets/qlineedit.cpp:1742
In QWidgetLineControl::processKeyEvent:
if (unknown
&& !isReadOnly()
&& isAcceptableInput(event)) {
insert(event->text());
src/widgets/widgets/qwidgetlinecontrol.cpp:1912
In QInputControl::isAcceptableInput:
bool QInputControl::isAcceptableInput(const QKeyEvent *event) const
{
const QString text = event->text();
if (text.isEmpty())
return false;
const QChar c = text.at(0);
// Formatting characters such as ZWNJ, ZWJ, RLM, etc. This needs to go before the
// next test, since CTRL+SHIFT is sometimes used to input it on Windows.
if (c.category() == QChar::Other_Format)
return true;
// QTBUG-35734: ignore Ctrl/Ctrl+Shift; accept only AltGr (Alt+Ctrl) on German keyboards
if (event->modifiers() == Qt::ControlModifier
|| event->modifiers() == (Qt::ShiftModifier | Qt::ControlModifier)) {
return false;
}
if (c.isPrint())
return true;
if (c.category() == QChar::Other_PrivateUse)
return true;
if (c.isHighSurrogate() && text.size() > 1 && text.at(1).isLowSurrogate())
return true;
if (m_type == TextEdit && c == u'\t')
return true;
return false;
}
src/gui/text/qinputcontrol.cpp:21
This is exactly what you need but you may want to change the check for \t and ignore that as well.
I manually create QTouchEvents and send them to a QGraphicsView's viewport(). While the QGraphicsScene does get the events, my QGraphicsItems (or ...Objects) don't. setAcceptTouchEvents is set to true:
myObject::myObject(QGraphicsItem * parent)
: QGraphicsItem(parent)
{
setAcceptTouchEvents(true);
}
...
bool myObject::sceneEvent( QEvent * event )
{
switch (event->type()) {
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
//this is never reached?!
return true;
}
return QGraphicsItem::sceneEvent(even);
}
//in a different class:
QTouchEvent * event = new QTouchEvent(t,QTouchEvent::TouchScreen,Qt::NoModifier,states,tpList);
if(m_view->viewport())
{
qApp->postEvent(m_view->viewport(), event);
}
Also, I get "QGestureManager::deliverEvent: could not find the target for gesture" warnings, though I don't even try to grab QGestures anywhere in my program.
I'm writing an application were i use my own shortcut. It looks like this:
myShortcut= new QShortcut(Qt::SHIFT + Qt::Key_B,this);
connect(myShortcut, SIGNAL(activated()), this, SLOT(setCameraBack()));
I defined it in the constructor of main widget and it works fine until i click one of the spinbox buttons which are also located on the main widget. After that my shortcut stop working and it doesn't work until i click push button or check box. When i do that everything is fine again. I'd like to add that after i click spinbox it seems to be "active" (because the cursor is still "blinking" on it) until i click one of the other buttons. Do you have any idea what is wrong? Is it some kind process or event problem? Thanks for all answers
~Marwroc
A shortcut is "listened for" by Qt's
event loop when the shortcut's parent
widget is receiving events.
When the QSpinBox has keyboard focus, then the QShortcut object's parent is no longer receiving events. Therefore, the shortcut does not work until keyboard focus is removed form the QSpinBox. You can change this behavior by passing Qt::WidgetWithChildrenShortcut or Qt::ApplicationShortcut to the QShortcut::setContext method of your QShortcut.
Before a shortcut is activated, the focus widget is given a ShortcutOverride event. If the event is accepted, the key event is passed along to the widget and the shortcut is not activated.
Source: https://wiki.qt.io/ShortcutOverride
Looking at Qt source
QAbstractSpinBox::event(QEvent *event)
{
Q_D(QAbstractSpinBox);
switch (event->type()) {
...
case QEvent::ShortcutOverride:
if (d->edit->event(event))
return true;
break;
...
}
return QWidget::event(event);
}
QAbstractSpinBox is allowing the internal edit to accept the event. QLineEdit defers to QLineControl. From qt/src/gui/widgets/qlinecontrol.cpp
case QEvent::ShortcutOverride:{
if (isReadOnly())
return false;
QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
if (ke == QKeySequence::Copy
|| ke == QKeySequence::Paste
|| ke == QKeySequence::Cut
|| ke == QKeySequence::Redo
|| ke == QKeySequence::Undo
|| ke == QKeySequence::MoveToNextWord
|| ke == QKeySequence::MoveToPreviousWord
|| ke == QKeySequence::MoveToStartOfDocument
|| ke == QKeySequence::MoveToEndOfDocument
|| ke == QKeySequence::SelectNextWord
|| ke == QKeySequence::SelectPreviousWord
|| ke == QKeySequence::SelectStartOfLine
|| ke == QKeySequence::SelectEndOfLine
|| ke == QKeySequence::SelectStartOfBlock
|| ke == QKeySequence::SelectEndOfBlock
|| ke == QKeySequence::SelectStartOfDocument
|| ke == QKeySequence::SelectAll
|| ke == QKeySequence::SelectEndOfDocument) {
ke->accept();
} else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
|| ke->modifiers() == Qt::KeypadModifier) {
if (ke->key() < Qt::Key_Escape) {
ke->accept();
} else {
switch (ke->key()) {
case Qt::Key_Delete:
case Qt::Key_Home:
case Qt::Key_End:
case Qt::Key_Backspace:
case Qt::Key_Left:
case Qt::Key_Right:
ke->accept();
default:
break;
}
}
}
}
This code accepts most keys if the control key is not also pressed.
So the easiest solution is to change the shortcut to include the control modifier.
Alternatively, you can subclass the spin box and override the event function
bool MySpinBox::event(QEvent *event)
{
if( event->type() == QEvent::ShortcutOverride && !isReadOnly() )
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
// Ignore 'B' shortcuts
if( keyEvent->key() == Qt::Key_B )
{
Q_ASSERT( !event->isAccepted() );
return true;
}
return QSpinBox::event(event);
}
Have you tried MySpinBox -> setFocusPolicy (Qt::NoFocus) ?