I am trying to show slowly one char from string ,like novel game.
To do it,at first I wrote the code as follows using CCLabelBMFont to extract one char from string.
string str = "I like an apple";
CCLabelBMFont *label = CCLabelBMFont::create(str.c_str(), "font.fnt");
CCSprite *spr = (CCSprite*)label1->getChildByTag(0);
spr->setPosition(ccp(100, 100));
this->addChild(spr);
I want to show spr that are extracted from CCLabelBMFont in GameScene(this)
But I am getting the error as follows
CCAssert( child->m_pParent == NULL, "child already added. It can't be added again");
Why did such the error appear ? and How should I do?
Look at the method you are using and the error you get. You use getChildByTag(...) to get your sprite. So what you get is a child node of your CCLabelBMFont, meaning it has a parent. Your error says that this sprite cannot be added again as a child, because it already has a parent.
I can't think of a straigthforward and sure way to achieve what you want, but here are some suggestions you may try :
Adding each letter as a seperate label - to be honest, this is really dumb as it unnecessarily multiplies your code and would use too much memory.
Making the children of your label invisible, and them make them visible one by one. When you create the label, iterate through its children and call setVisible(false) on them. Then schedule a call in which you will call setVisible(true) on subsequent children.
Possibly creating subclass of LabelBMFont and/or creating a custom action may be the most flexible way, but propably not the easiest.
Let me know if anything is not clear!
Related
QSpinBox* spinright[size] = {ui->norm_spinBox_2,
ui->norm_spinBox_3,
ui->norm_spinBox_4,
ui->norm_spinBox_5,
ui->norm_spinBox_6,
ui->norm_spinBox_7,
ui->norm_spinBox_8};
I'd like to be able to access this array in two spots in my program. However, if there is a better alternative for this solution I’m all ears. I tried to create a function that could be called for this program; however it started to get long and dragged out that it was becoming less worth it to go this route.
This is how I've set up the Hierarchy. My overall attempt is to make some buttons appear and disappear when a button is pressed. If it's possible to make the vertical layouts disappear then this would be a better way to go.
In the end I'll take whatever solution, that may be offered here.
Thank you for your help.
void GuiTest::setLabelsVisible(int index, bool visible){
QLabel* labels[norm_size] = {ui->norm_label_2,
ui->norm_label_3,
ui->norm_label_4,
ui->norm_label_5,
ui->norm_label_6,
ui->norm_label_7,
ui->norm_label_8};
labels[index]->setVisible(visible);
}
the best way to do this, I found, would to go this direction. Instead of setting this list of objects as global just have separate functions that will manipulate the structure in some way.
In my scene I have a vector with multiple custom sprites. When I tap on one of them, I want an action to be fired on another element on the scene, can be another sprite in the vector, or another node. I have been researching the best way to do this, but I'm not quite sure how to implement it. The options are:
Add a touch listener to the scene, and verify if it was tapped inside the bounds of the sprite with rect. containsPoint(point). And after that, I have to get the sprite that was tapped to do the action I want. For me, it doesn't seems very clean to do it this way. And if two sprites are overlaped, I have to verify if the sprite is behind or in the front in order to retrieve the desired sprite. I followed this example: Touch Event example
Add a touch listener in the subclass of the sprite (my custom sprite). And add onTouchBegan and onTouchEnded inside it. But this way, I don't know how to modify an attribute of another sprite, or another element in the scene (Is it possible to use Delegates like Objective-C does?). I followed this example: Subclass Sprite Example
My main problem is that I don't understand very well how to make a node interact with another node in the scene. I have seen a lot of tutorials, but in all of them, when you interact with a node, it only changes its attributes, not other nodes' attributes.
Thanks in advance.
I shall propose "EventCustom" way :)
You can add in your touchBegan / touchEnded methods (wherever you put them... you got the point...) additional code for passing an EventCusto to the _eventDispatcher and get it announced to the world ;)
EventCustom *e = new EventCustom("MyAwesomeEvent");
e->setUserData(ptrMyFantasticData); //This function takes a void pointer. cheers :)
_eventDispatcher->dispatchEvent(e);
You may subclass the EventCustom class but that is hardly necessary. You can always hang an object to it with setUserData().
Now the objects which need to react to the event can listen to it by
_myCustomListener = EventListenerCustom::create(
"MyAwesomeEvent",
CC_CALLBACK_1(
ListeningClass::onMyAwesomeEvent,
this
)
);
_eventDispatcher->addEventListenerWithXXXXXPriority(_myCustomListener, XXX);
//ScreenGraphPriority / FixedPriority depends on situation. Either should work.
It's always a good practice to remove your listeners when you go off, so somewhere, perhaps in onExit(), where you removed touch listeners remove this listener too, as
_eventDispatcher->removeEventListener(_myCustomListener);
Going a bit off the track, a clarification:
CC_CALLBACK_X are a bit tricky names. The X indicates the no. of args the target function will get. Here, event dispatcher will pass 1 arg i.e. ptr to object of EventCustom you handed it, so we use CC_CALLBACK_1. The next arg - here "this" - is the object on which the method will be invoked.
In short, we may say that this callback is going to result into a function call this->onMyAwesomeEvent(e);
For CC_CALLBACK_2 onwards, we can specify additional args, 3rd arg onwards.
Coming back to the issue at hand, ListeningClass::onMyAwesomeEvent will look something like
void ListeningClass::onMyAwesomeEvent(EventCustom *e)
{
MyFantasticData *d = (MyFantasticData *) e->getUserData();
CCLOG("[ListeningClass::onMyAwesomeEvent] %d", d->getMyPreciousInt());
}
Hope it helps :)
Set your elements tags or names with setTag and setName. Then if element x is touched, get them with getChildByTag or getChildByName and do what you need to do.
With the second option you list above.
To make a node interact with another node in the scene you can add touch callback function to your custom sprite object like that:
https://github.com/Longpc/RTS/tree/master/Classes/base/dialogBase
and in main scene you can define function to handle this callback. So you can do every thing to unit in you scene
The application that I'm building is supposed to create, destroy, and manipluate widgets that I've created
The problem is I'm not making a simple program with nice buttons where everything is symmetrical and needs to be evenly spaced and handled via a layout that will automatically move everything around and space it.
And yet, the only way I know of is to manually instance a layout and add the widgets to it, but then I can't set the coordinates of them
How can I simply instance my widget, and add it to the project generated frame?
This is how I'm instantiating my class, in which case I then set my own parameters:
Tile *tile = new Tile;
tile->setImg("://Images/placeholderTile.png");
tile->setCol(true);
tile->setGeometry(retX(line),retY(line),50,50);
To reiterate, I want to add my own widgets to a frame outside of the editor (only by code), and be able to manually move them around the frame by code.
I don't see an ".addWidget() as a method accessible from the QFrame, and yet they can be children within the designer, why can't I do this by code? Whenever I try to do it manually and add them to any layout, any attempt I make to manually set the widgets location doesn't do anything. I haven't overridden the setGeometry
I fixed my problem
After 2 hours of continual searching I finally came across my answer
I never thought that you could set the parent of a widget by code, as I thought you strictly had to add it in as a child of something else, not the reverse and declare that it should have a parent
So, by simply adding the line:
tile->setParent(ui->frame);
completely fixed my problem.
I will change this post back and submit the answer tomorrow when I'm allowed to by this site.
Thank you to those who actually came though. I'm just glad I managed to fix it before that.
All you need is to pass the parent to the widget's constructor:
Tile *tile = new Tile(ui->frame); // <-- here
tile->setImg("://Images/placeholderTile.png");
tile->setCol(true);
tile->setGeometry(retX(line),retY(line),50,50);
Since Tile is your own class, you should definitely have a Qt-style, parent-taking explicit constructor for it:
class Tile : public QWidget {
...
public:
explicit Tile(QWidget * parent = 0) : QWidget(parent) { ... }
};
Another approach is to write your own layout that would know about the relationships that are to be held between your objects. After you do it once, writing custom layouts isn't that hard.
I am in the process of developing a html editor in Qt for one of my university assignments, and i am having a problem regarding naming of some variables.
the problem is this:
when the user decides to load their "project" the program iterates through the folder and finds how many .html files are in there, it then creates tabs for them to be displayed in.
I have a custom QTextEdit which has a customer completer and syntax highlighting etc. the problem i am having at the moment is how to create them depending on the number needed.
i create a QStringList of file names:
QStringList m_files;
m_files = aDialog.m_loadDirectory->entryList(QStringList("*.html"),QDir::Files|QDir::NoSymLinks);
then i iterate through each one of the list:
for(int i=0; i<m_files.count();i++)
{
}
and for each one i need to create a new custom QtextEdit
TextEdit *name = new TextEdit;
then add to the tab
tabs->addTab(name,"someTitle");
but as each TextEdit needs to be different for each tab (i think this is correct) i need a different Variable name for each one.
i thought about creating a list/array of TextEdit objects but as i dont know how many i need to use, i could end up easily with too many (wasted memory) or not enough..
any ideas on how i can get around this?
one thought..
would it be possible to create a TextEdit object before the loop
then make a copy of that object in the loop and add the copied object to the tab? (still variable naming problem...)
thanks
but as each TextEdit needs to be different for each tab (I think this is correct)
Yes, you need a different TextEdit in each tab.
I need a different Variable name for each one.
No, you don't need a different variable name for each one. You need different objects, but variable names don't have much to do with that.
A simple:
for (...) {
TextEdit *te = new TextEdit(...);
// set up that text edit in whatever way you need
tabs->addWidget(te, "foo");
}
does exactly what you want. The variable name te is completely irrelevant (it won't even appear in the executable outside of debugging symbols). Each time through the loop, you'll be working on a separate TextEdit instance.
If you need to refer to that TextEdit by name at runtime, you can keep all your widgets in a collection, a QMap for instance.
QMap<QString, QWidget*> all_editors;
...
for (...) {
TextEdit *te = ...;
all_editors[filename] = te;
...
}
You have discarded quickly the only viable solution : put your text edits in a collection. The textedit have to be created with new, so the collection itself will not waste space.
You can use a QPair<QTabWidget*, QTextEdit*> for simplest cases. For more complicated cases create a custom widget, and just make a list of those.
Copying a QObject is a really bad idea. I think the copy constructor is private so you will not even be able to do that
I would like to ask if anyone knows how to display 2 QToolBars in two lines, one on top of the other? I found the class QStyleOptionToolBar, but I don't know how to use it...
It is easy to drag one toolbar with the mouse to be placed below the other, so I think there must be a way how this can be done from the source code as well...
Any hint would be appreciated!
Claus
Try calling QMainWindow::addToolBarBreak(Qt::ToolBarArea) in between adding the two tool bars.
I think that when you add the 2 toolbar's if you place them in the same area, they'll stack automatically:
QMainWindow *mainWin = get_main(); // however you get it
mainWin->addToolBar(Qt::TopToolBarArea, new QToolBar);
mainWin->addToolBar(Qt::TopToolBarArea, new QToolBar);
This should produce 2 toolbars, both at the top.
If you want toolbars to be in two lines you should do it in following manner:
firstToolbar = new QToolBar(this);
secondToolbar = new QToolBar(this);
addToolBar(Qt::TopToolBarArea, firstToolbar);
addToolBarBreak();
addToolBar(Qt::TopToolBarArea, secondToolbar);
addToolBarBreak accepts Qt::ToolBarArea so you can specify for which area you would like to add the break. By default it is Qt::TopToolBarArea.