Javascript object that inherits QWidget - javascript

I am doing something in Javascript and Qt, and for my purpose, I need a javascript object that inherits QWidget. So far, I have tried the following:
function Test()
{
QWidget.call(this);
this.button = new QPushButton("test");
this.layout().insertWidget(1,this.button);
this.button.clicked.connect(this.slot);
}
Test.prototype.slot = function()
{
print("Test button clicked");
}
Test.prototype = new QWidget();
I instantiate object from the class "Test" and with the call of the show() method, I get the widget:
var testVariable = new Test();
testVariable.show();
However, I get the following interpreter error:
Error: In run/evaluate: TypeError:
Function.prototype.connect: target is
not a function
If I change the line this.button.clicked.connect(this.slot); to call a static method defined like this:
this.button.clicked.connect(Test.slot);
...
...
Test.slot = function () { /* code */ }
the program runs fine, but static method is a no-no. I don't want anyone to call slot() except the instantiated object.
What is wrong with this picture? Has anyone had experience with Javascript objects inheriting Qt objects?
Thanks in advance

Ok I think I might figured this out. So the magic here is:
Test.prototype = new QWidget();
needs to be before the constructor, also the constructor has to take "parent" argument too. And last but not least, in connect() there are two arguments: first is which class contains the slot (in my case it is this) and the name of the slot with this pointer.
So, having this in mind, the above code will look like this:
Test.prototype = new QWidget();
function Test(parent)
{
QWidget.call(this, parent);
this.button = new QPushButton("test");
this.layout().insertWidget(1, this.button);
this.button.clicked.connect(this, this.slot);
}
Test.prototype.slot = function()
{
print("Test button clicked");
}
This is to whom it may concern.

Related

Why can’t I access a property on “this” in a class via its prototype?

I wrote this class and have set up an array property for it. Then, I want to add an item to this array.
However, when I try to do it, I get the error “Uncaught TypeError: Cannot read property push of undefined”.
Isn’t this possible?
class test {
constructor() {
this.myArray = [];
}
myMethod() {
this.myArray.push("ok");
}
};
console.log(test.prototype.myMethod());
That’s not how classes are used. You need to instantiate test first, by using new test(). The constructor was never called in your case, so this.myArray was never defined.
This is the only way this can work:
let testInstance = new test();
testInstance.myMethod();
This way, the constructor is called and there will be no error.
Of course, next you’ll need some way of retrieving your array, in order to see the effect.
try to create the instance first. See the code I've commented it in details
test.prototype = {
constructor: test,
myMethod: function() {
this.myArray.push("ok");
}
};
var test = function(){
this.myArray = [];
}
test.prototype = { // add our custom constructor and custom methods
constructor: test,
myMethod: function() {
this.myArray.push("ok");
}
};
var myVar = new test(); // create new instance of test
myVar.myMethod(); // run custom method to push val
console.log( myVar.myArray );
You need to initiate your class test first.
var t = new test();
For your information:
console.log(test.prototype.myMethod());
will give you "undefined". Try e.g. :
var t = new test();
t.myMethod();
console.log(t.myArray);
to get output similar to this:
Array [ "ok" ]

Calling 'normal' member functions from JS prototypes

I'm trying to create a JS class, where each object will contain a member, verify_function which will be supplied by a constructor at the time of creation. Then at some point in time, the prototype functions will call this verify_function.
This is what my code looks like:
var ClassName = function(verify_callback) {
this.verify_function = verify_callback;
}
ClassName.prototype.functionName = function() {
this.verify_function(); //problem lies here
}
I'm trying to create the object like this:
var objectName = new ClassName(function() {
console.log('This should be printed!');
})
On executing the code, it says:
TypeError: this.verify_function is not a function
Any help will be greatly appreciated.

How to change the constructor of an object?

I am diving deeper into Javascript, and learning how constructor methods work.
In the code below, I would expect that I would be able to overwrite the constructor of an object, so that newly created instances would use the new constructor. However, I can't seem to make new instances use a new constructor.
Any insight as to what is going on would be greatly appreciated!
function constructorQuestion() {
alert("this is the original constructor");
};
c = new constructorQuestion();
constructorQuestion.constructor = function() { alert("new constructor");}
howComeConstructorHasNotChanged = new constructorQuestion();
Here's the fiddle: http://jsfiddle.net/hammerbrostime/6nxSW/1/
The constructor is a property of the prototype of the function, not the function itself. Do:
constructorQuestion.prototype.constructor = function() {
alert("new constructor");
}
For more information see: https://stackoverflow.com/a/8096017/783743
BTW, if you expect the code howComeConstructorHasNotChanged = new constructorQuestion(); to alert "new constructor" that won't happen. This is because you're not calling the new constructor, you're calling the old one. What you want is:
howComeConstructorHasNotChanged = new constructorQuestion.prototype.constructor;
Changing the constructor property doesn't magically change the constructor.
What you really want is:
function constructorQuestion() {
alert("this is the original constructor");
};
c = new constructorQuestion();
function newConstructor() {
alert("new constructor");
}
newConstructor.prototype = constructorQuestion.prototype;
howComeConstructorHasNotChanged = new newConstructor();
This will work. See: http://jsfiddle.net/GMFLv/1/
I think it will be same to create new object with same prototype like this:
function newClass(){
alert('new class with same prototype');
}
newClass.prototype = constructorQuestion.prototype;

Adding a property to a "Class" in JavaScript

There are no actual classes in javascript. But you have to work with what you get.
Lets take this example "Class":
var example = function (string) {
this._self = string;
}
With the above, you could do something like:
var ex = new example("Hello People."),
display = ex._self; // returns "Hello People."
I thought that by using something like example.prototype.newFun = function(){} would add a new property to that "Class". But it isn't working in my code.
Here is the full code i'm testing:
var example = function (string) {
this._self = string;//public, var like, storage
}
var showExample = new example("Hello People");
showExample.prototype.display = function (a) {//code stops here, with error "Uncaught TypeError: Cannot set property 'display' of undefined"
return a;
}
console.log(showExample._self);
console.log(showExample.display("Bye"));
What i'm trying to do is add the display function to the example function as a "public function". I might be doing something wrong.
It's not the object that has the prototype, it's the function that you use to create the object:
var example = function (string) {
this._self = string;
}
example.prototype.display = function (a) {
return a;
};
Because there's no prototype for showExample - it's only an instance of example. Try to do this: example.prototype.display = function (a) {} and it will work.
Here's a bit more on classes in JavaScript:
3 Ways to "define" classes
This lovely SO question
I like the way Classy handles this and also how classes are implemented in CoffeeScript.
You can modify to the constructor of showExample ..
ex.
showExample.constructor.prototype.display = function (a) {
return a;
}
You try to add a method to the prototype of the instance of example (showExample). The instance has no prototype. Try example.prototype.display = function() {/*...*/}; (in other words, add the method to the prototype of the constructor of showExample, that is example) and check again. After that, all instances of example 'know' the display method, or in your words, display is 'public' to all instances.
You can add the method to the instance using showExample.display = function() {/*...*/};. Using that, only showExample knows the the display method.
in your case showExample is an object of example...
use
example.prototype.display = function(a)...

JavaScript : Create new object of a custom class based on an existing one (adding methods to it)

I use the iOS UI Automation framework to make sure my iPhone app rocks.
Everybody who uses this framework would tell you that it's great, but that it's lacking a lot of structure.
So I have to deal with instances of UIAWindow, which represent different screens of my app. To be more object-oriented, I'd like to have a specific class for each screen, so I could add specific methods, like
myScreen1.tapDoneButton();
var total = myScreen2.getNumberOfElements();
For the moment, I'm able to achieve this by passing the instances of UIAWindow to functions that will add the appropriate methods, like this :
function makeMainScreen(actualScreen)
{
actualScreen.constructor.prototype.getAddButton = function() {
return this.buttons()["add button"];
};
actualScreen.constructor.prototype.tapAddButton = function() {
this.getAddButton().tap();
};
// Add any desired method...
return actualScreen;
}
It works fine, I use it like this :
var mainScreen = makeMainScreen(app.mainWindow());
mainScreen.tapAddButton();
But that doesn't seem object-oriented enough, I would like to create real objects, using the new and this keywords, so I'd have a declaration like this :
function MainScreen(actualScreen){
// This line doesn't work : because 'this' is immutable
this = actualScreen;
this.tapAddButton = function(){
this.getAddButton().tap();
}
//...
}
And I'd use it like this :
var mainScreen = new MainScreen(app.mainWindow());
mainScreen.tapAddButton();
I thought I could save the actualScreen as a property of the object (Like in Grace Shao's answer below), and call all the methods on it, but I'd like keep the original UIAWindow methods.
Does anybody know how to do this?
Or perhaps what I'm trying to achieve doesn't make sense, in which case I'd be happy to know.
If I understand correctly, you could try the following:
function MainScreen(actualScreen){
this.screen = actualScreen;
}
MainScreen.prototype.tapAddButton = function () {
this.screen.getAddButton().tap();
};
MainScreen.prototype.getScreen = function () {
return this.screen;
};
//...
var mainScreen = new MainScreen(app.mainWindow());
mainScreen.tapAddButton();
You are correct that you cannot assign anything to this. You could also define the methods inside the constructor MainScreen, but they would be considered privileged members.
function MainScreen(actualScreen){
this.screen = actualScreen;
this.tapAddButton = function () {
this.screen.getAddButton().tap();
};
}
If you dont want them to be privileged members, it is better to define them outside the constructor. Otherwise, the members will be initialized over and over again everytime when you instantiate a new object.
Updated:
You could also wrappers for the methods of screen inside the constructor as below.
var prop;
for (prop in actualScreen) {
if (typeof actualScreen[prop] !== 'Function') {
continue;
}
this[prop] = function () {
return actualScreen[prop].apply(actualScreen, arguments);
};
}

Categories

Resources