When i try to access offsetX from a SyntheticMouseEvent triggered, Flow throw this error:
[flow] Cannot get event.nativeEvent.offsetX because property offsetX is missing in Event 1. (References: 1)
_handleClick = (event: SyntheticMouseEvent<HTMLDivElement>): void => console.log(event.nativeEvent.offsetX);
The only 'workaround' i have for now is to type the event as a MouseEvent:
_handleClick = (event: MouseEvent): SyntheticMouseEvent<HTMLDivElement>
But and if i'm not mistaken, Event triggered in a React component are always SyntheticEvent, so my workaround is a hack. Do you know a better way to type this ?
Flow-try (but this will not be really helpfull as SyntheticMouseEvent is not defined)
Instead of writing event.nativeEvent.offsetX, I would write (event.nativeEvent: MouseEvent).offsetX (I cast the native event to MouseEvent before accessing to offsetX).
Note : MouseEvent comes from dom.js (that you don't need to import or require), see https://github.com/facebook/flow/blob/master/lib/dom.js#L284
offsetX is not part of SyntheticMouseEvent. See more context here
https://github.com/facebook/react/pull/7011
Related
I found an interesting article on how to impement QObject with dynamic properties (see C++ class DynamicObject). The code from the article works fine, the properties of DynamicObject are get and set successfully from both C++ and QML, but the only thing I cannot figure out is how to fire dynamic signals.
I tried to fire "nameChanged()" signal with the following code:
bool DynamicObject::emitDynamicSignal(char *signal, void **arguments)
{
QByteArray theSignal = QMetaObject::normalizedSignature(signal);
int signalId = metaObject()->indexOfSignal(theSignal);
if (signalId >= 0)
{
QMetaObject::activate(this, metaObject(), signalId, arguments);
return true;
}
return false;
}
myDynamicObject->emitDynamicSignal("nameChanged()", nullptr);
the index of the signal is found and signalId is assigned to 5, but the signal is not fired. But if I do, for example,
myDynamicObject->setProperty("name", "Botanik");
the property is changed and the signal is fired successfully.
What is wrong in my code? What should I pass as 'arguments' parameter of QMetaObject::activate ?
EDIT1:
The full source code is temporarily available here.
A signal is also a method. You can invoke it from the meta object.
So, replace your line QMetaObject::activate(...) by:
metaObject()->method(signalId).invoke(this);
And let Qt handles the call to activate().
There is also an issue in DynamicObject::qt_metacall(): you are handling only QMetaObject::ReadProperty and QMetaObject::WriteProperty calls.
You have to add QMetaObject::InvokeMetaMethod if you want to emit your signal.
I want to intercept Tab key press in my main window to prevent Qt from switching focus. Here's what I've tried so far:
bool CMainWindow::event(QEvent * e)
{
if (e && e->type() == QEvent::KeyPress)
{
QKeyEvent * keyEvent = dynamic_cast<QKeyEvent*>(e);
if (keyEvent && keyEvent->key() == Qt::Key_Tab)
return true;
}
return QMainWindow::event(e);
}
This doesn't work, event isn't called when I press Tab. How to achieve what I want?
The most elegant way I found to avoid focus change is to reimplement in your class derived from QWidget the method bool focusNextPrevChild(bool next) and simply return FALSE. In case you want to allow it, return TRUE.
Like other keys you get now also the key Qt::Key_Tab in keyPressEvent(QKeyEvent* event)
Reimplementing virtual bool QApplication::notify(QObject * receiver, QEvent * e) and pasting the code from my question there works.
You can achieve by using setFocusPolicy( Qt::NoFocus) property of QWidget. You can set Focus policy on widget which doesn't require tab focus. I think the reason why event handler is not calling, because Tab is managed by Qt framework internally. Please see QWidget::setTabOrder API, which is static.
You'll need to install an event filter on your main window in order to receive the events. You can use installEventFilter method for this.
Another option is to override the keyPressEvent method to handle the key presses.
I need to know the value from which a combo box is changing, when it changes. I've been all through the documentation for the events, and none of them let you know what the value is before user interaction changes it. (currentStateChanging is a total red herring!) Handling the open event and saving the value isn't a solution, because there are other ways to change the value.
I'm using the Flex 3.5 SDK.
Something like this?
var currentVal : Object;
private function onChange(newVal) : void {
// currentVal stores your previous value - do something with it
currentVal = newVal;
}
<mx:ComboBox change="onChange(event.target.selectedItem)"/>
I just used the "changing" event on a Spark ComboBox to solve this very problem but it's not available on the mx version
Also - see this
I've come to the conclusion that there isn't an answer :( The best workaround is to override all possible ways there are to set the value of a combo box, plus handle any events that involve the user changing the value, back up that value and then you have a trail of previous values. Then, put a lot of comments saying
this is a 3.5-necessary kluge! If doing this on another SDK you might have to change it!
=======
I've come up w/a solution, but it's not perfectly reliable (since it makes assumptions about how it will work in other SDKs) and its elegance is wanting:
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml" valueCommit="OnChangeAnyway()" change="OnChange()">
<mx:Metadata>
[Event(name='traceable_change', type="assets.LineComboChangeEvent")]
</mx:Metadata>
<mx:Script><![CDATA[
public static const CHANGE:String = 'traceable_change';
private var m_oOld:Object;
private var m_oNew:Object;
private var m_bCallLaterPending:Boolean = false; //This is necessary, because I found OnChangeAnyway() could be called any number of times before OnChange() is
private function OnChange():void {
var oNewEvent:LineComboChangeEvent = new LineComboChangeEvent(CHANGE, m_oOld); //there's nothing special in this class
dispatchEvent(oNewEvent);
}
private function OnChangeAnyway():void {
if (!m_bCallLaterPending) {
m_bCallLaterPending = true;
callLater(function ():void { m_bCallLaterPending = false;}, []); //presumably, whatever is passed to callLater() will be executed after everything else currently queued
m_oOld = m_oNew;
m_oNew = value;
}
}
]]></mx:Script>
m_oNew is obviously redundant because that value will be available to whatever handles traceable_change, but it does explain why I have to barrel-shift these objects.
There are a couple of reasons why I don't consider this reliable:
It assumes that the valueCommit handler will be called ahead of the change one. On my system, it always seems to, but I don't see that promise anywhere.
It assumes that whatever callLater() calls will be called after change is. See concerns for 1.
Doesn't .getKeyCode( ) return the key's int value? Because I have set my JTextField to listen to a keylistener, and in the keytyped method, I check what key has been pressed. Here's a snippet of my code:
JTextField jtf = new JTextField( );
jtf.addKeyListener( this );
.
.
.
public void keyTyped( KeyEvent e )
{
if( e.getKeyCode( ) == KeyEvent.VK_ENTER ) System.out.println( "pressed enter" );
}
but everytime I type enter in the JTextField, nothing happens, ie nothing prints.
maybe you should check first if you event handler is actually get called when you pressed anything... or if your event handler is able to receive KeyEvents objects, i believe the problem lies there... for it to work, the component must have focus... Java Tutorial
I think you are comparing the wrong values. e.getKeyCode() returns the key, then i guess KeyEvent.VK_ENTER is something really different.
I just figured out a better way. you should put all your key methods inside an inner class just under your main class, Put your GUI construction code in a constructor method again out side of your main method. now. have you're inner method implement the KeyListener interface, and instantiate the three abstract methods associated with said interface, you're only using the keyTyped(KeyEvent e) method. inside that method, instantiate an int variable called keyHit and assign it to e.getKeyChar(); then put an if statement that states if(keyHit == '\n') the \n will corresopnd to the ENTER key,
I tried to post a template of the code Iused to get it to work, but It was a little long to go through and indent so if you're really need it i'll send it to you via some e-mail address or something
VK_ENTER corresponds to the int value of the enter key, seeing as how it is a constant. You should be using input and action maps from the swing class to listen for the key values when the JTextField is in focus as opposed to applying a key listener to the text field and listening for one key. Because an event is created (although may or may not be handled) every time a key is pressed, you should prevent the method from running when keys that aren't the enter key are pressed. Therefore preventing runtime errors and unnecessary method calls.
You have to implement KeyListener Inteface and override the keyTyped method in your class definition to use
jtf.addKeyListener(this).
Replace the above line with
jtf.addKeyListener(new KeyAdapter(){
#Override
public void keyTyped(KeyEvent e) {
if( e.getKeyCode( ) == KeyEvent.VK_ENTER )
System.out.println( "pressed enter" );
}
});
I am trying to add some Sprite objects as the contents of an array, and I would like to be able to "clear" them from the stage. I would assume that if there are loaders involved, I need to do
_imgArray[i].close();
_imgArray[i].unload();
And if I am using a sprite, I can do:
removeChild(_imgArray[i]);
None of the above work. WHY???
For an example and/or description of how I am setting this up, see Joel's post here
...but note that he hasn't included a reference for deleting them from view.
Currently I try:
for(i = 0; i < _localXML.length(); i++)
{
var tmp:BMLink = new BMLink(_localXML[i], _bw, _bh, i);
_imgArray[i] = tmp;
_imgArray[i].x = (_bw + _mainpad) * i;
_base.addChild(_imgArray[i]);
}
But this doesn't work.
I would love it if someone could explain to me why this wouldn't be proper syntax.
The class instances that are populating the array are all extending sprite, but they have their own individual loaders inside w/ progress events etc.
jml
OK; I finally figured it out through a bunch of trial and error.
It seems that I was attempting to remove the child of my main class sprite (this) rather than the sub-sprite that I had added the children to.
Sorry for the noise, but for the record, if you find that you can't do
this.removeChild(_imgArray[i]);
it's not because you don't have the correct syntax, but because you might not have an
_imgArray[i]
at that particular point of your display list hierarchy... so...
_base.removeChild(_imgArray[i]);
...worked in this case.
jml
You can make an Interface IDestroy for example with a destroy method who will manage all cleaning/removing stuff :
public interface IDestroy{
function destroy():void;
}
public class MySprite extends Sprite implements IDestroy {
..
public function destroy():void{
// remove events
..
// remove loader
..
//remove from parent
if (parent!==null){
parent.removeChild(this);
}
// etc.. more cleaning
}
}
then when you have an object who is an instance of IDestroy you can call the destroy method
if (myObject is IDestroy){
IDestroy(myObject).destroy();
}
or another way
var id:IDestroy=myObject as IDestroy;
if (id!==null)
id.destroy();
Edit:
I don't understand why any of the method i gave you in the comment will not work but _base.removeChild(_imgArray[i]) will :
addChild and removeChild accept only a DisplayObject as a parameter, so if you can do _base.addChild(_imgArray[i]) it means that _imgArray[i] inherits from DisplayObject and _imgArray[i] has a parent.
So var myDisplayObject:DisplayObject=_imgArray[i] as DisplayObject; will not return null and you will be able todo myDisplayObject.parent.removeChild(myDisplayObject); which is a general approach to your problem without relying on your _base DisplayObjectContainer (MovieClip/Sprite/...)