I have a scroll area with a layout that has 8 of the same custom widgets that have been added to it. This custom widget has a getter function that will return a value. My question is how to get back that original custom widget so I can call the getter function to retrieve the data it stores?
I have added the custom widget to the layout this way:
for (int var = 0; var < 9; ++var) {
calcRow *CalcWidget = new calcRow(this, &js, KeyList, SizeList);
connect(CalcWidget, &calcRow::testSignal, this, &MainWindow::getRowData);
ui->scrollArea_layout->layout()->addWidget(CalcWidget);
}
Where I am stuck:
void MainWindow::getRowData()
{
for (int i = 0;i < ui->scrollArea_layout->layout()->count() ;++i ) {
QWidget *row = ui->scrollArea_layout->layout()->itemAt(i)->widget();
if(row != NULL)
{
std::cout << row->"SOMETHING TO GET CALCROW WIDGET" <<std::endl;
}
}
}
Usually it's not the best structure for your code, any layout change might break your implementation. For example this solution will not work if you will have multiple calcRow widgets.
To make it better, you can pass required parameters which you want use inside getRowData as a parameters of testSignal signal.
Or just simplify it even more with lambda:
for (int var = 0; var < 9; ++var) {
calcRow* CalcWidget = new calcRow(this, &js, KeyList, SizeList);
connect(CalcWidget, &calcRow::testSignal, [CalcWidget]()
{
std::cout << CalcWidget->"SOMETHING TO GET CALCROW WIDGET" << std::endl;
});
ui->scrollArea_layout->layout()->addWidget(CalcWidget);
}
For anyone else that will find this in the future, the comments helped a bunch and I ended up using static_cast. My final code looks like this:
void MainWindow::getRowData()
{
for (int i = 0;i < ui->scrollArea_layout->layout()->count() ;++i ) {
QWidget *row = ui->scrollArea_layout->layout()->itemAt(i)->widget();
calcRow *rowConverted = static_cast<calcRow*>(row);
if(row != NULL)
{
std::cout << rowConverted ->getData() <<std::endl;
}
}
}
This is my 2d array:
int pay_scale[15][10] =
{ { 18526, 19146, 19762, 20375, 20991, 21351, 21960, 22575, 22599, 23171},
{ 20829, 21325, 22015, 22599, 22853, 23525, 24197, 24869, 25541, 26213 },
{ 22727, 23485, 24243, 25001, 25759, 26517, 27275, 28033, 28791, 29549},
{ 25514, 26364, 27214, 28064, 28914, 29764, 30614, 31464, 32314, 33164},
{ 28545, 29497, 30449, 31401, 32353, 33305, 34257, 35209, 36161, 37113},
{ 31819, 32880, 33941, 35002, 36063, 37124, 38185, 39246, 40307, 41368},
{ 35359, 36538, 37717, 38896, 40075, 41254, 42433, 43612, 44791, 45970},
{ 39159, 40464, 41769, 43074, 44379, 45684, 46989, 48294, 49599, 50904},
{ 43251, 44693, 46135, 47577, 49019, 50461, 51903, 53345, 54787, 56229},
{ 47630, 49218, 50806, 52394, 53982, 55570, 57158, 58746, 60334, 61922},
{ 52329, 54073, 55817, 57561, 59305, 61049, 62793, 64537, 66281, 68025},
{ 62722, 64813, 66904, 68995, 71086, 73177, 75268, 77359, 79450, 81541},
{ 74584, 77070, 79556, 82042, 84528, 87014, 89500, 91986, 94472, 96958},
{ 88136, 91074, 94012, 96950, 99888, 102826, 105764, 108702,11640,114578},
{ 103672, 107128, 110584, 114040, 117496, 120952, 124408,127864, 1, 2}};
My goal is to std::cout in the same order it is displayed above so it prints each value in the first array pay_scale[0][n++]
then moves onto pay_scale[1][[n++]
then moves onto pay_scale[2][n++] etc. until it reaches pay_scale[14]
As of right now I just have:
for (int i = 0; i < 10; i++) {
std::cout << "[" << pay_scale[n][i] << "]" << "\t";
}
And n = 0
I am having trouble indexing it without it jumping to the next array before it finishes the first one.
I must say I am new to cpp as I am sure you can see, any guidance is appreciated.
Thank you!
Here's the way the cool kids do it. :-)
for (const auto &row : pay_scale) {
for (auto col : row) {
std::cout << col << " ";
}
std::cout << "\n";
}
Why not use something more like this which loops through all the array:
for(int i = 0; i<15; i++)
{
for(int n = 0; n<10; n++) cout<< "["<< pay_scale[i][n]<<"]\t";
cout<<endl;
}
Hope this helps.
Constructor:
ScrollArea::ScrollArea(...)
{
...
end = myItems.count();
for(int i=0; i<end; i++)
{
scrollItems.append(new ScrollItem(myItems.at(i), 0, width, i, this));
}
scrollArea->setWidget(this); //must be last for auto-scrolling to work
}
Member function:
void ScrollArea::updateSelection(int selection)
{
foreach(ScrollItem* item, scrollItems)
{
if(item->updateSelection(selection, 0))
{
scrollArea->ensureWidgetVisible(item);
}
}
}
After running ScrollArea::updateSelection, it looks like this:
I want it to look like this:
Google returns a mis-titled question (as far as I can tell: Place widget in center of QScrollArea) and a bunch of junk.
Still don't know why QScrollArea::ensureWidgetVisible doesn't work, even with explicit margins, but I found something that does:
void ScrollArea::updateSelection(int selection)
{
int item = -1;
int i = scrollItems.count();
while(i)
{
i--;
if(scrollItems.at(i)->updateSelection(selection, 0))
{
item = i;
}
}
if(item < 0)
{
return;
}
i = scrollItems.first()->height();
item *= i;
item += i / 2;
//item is now the position that should be centered
scrollArea->verticalScrollBar()->setValue(
item - (scrollArea->height() / 2)
);
}
So I'm basically brute-forcing what I want instead of having the library do it. (and fail)
Well I have that code that saves an array map on a txt file:
std::ofstream output("mapa.txt");
for(int y=0;y<worldHeight;y++) {
for(int x=0;x<worldWidth;x++) {
output<<scene[x][y];
if(x<(worldWidth-1)){output<<",";}
}
if(y<(worldHeight-1)){output<<std::endl;}
}
I want to integrate it to a while loop:
std::ofstream output("mapa.txt");
while (true) {
if (yPos == topOfTheWorld) {
scene[xPos][yPos] = 2;
} else if (yPos >= topOfTheWorld) {
scene[xPos][yPos] = 1;
} else if(yPos < topOfTheWorld) {
scene[xPos][yPos] = 0;
} else {
scene[xPos][yPos] = 0;
}
output<<scene[xPos][yPos] << ",";
//if(xPos<(worldWidth-1)){output<<",";}
//if(yPos<(worldHeight-1)){output<<std::endl;}
yPos++;
if(yPos>worldHeight) {
output<<std::endl;
slope = random(5)-2;
if(topOfTheWorld<(worldHeight/6)) {
slope = 1;
} else if(topOfTheWorld>(worldHeight-10)) {
slope = -1;
}
topOfTheWorld += slope;
yPos = 0;
xPos++;
}
if (xPos>=worldWidth) {
break;
}
}
But for some reason the 'while' loop becomes infinite... :/
What can I do?
The code looks good.
However I'm not sure if scene is correctly allocated.
You have yPos>worldHeight and below xPos>=worldWidth which suggests that you're not sure how to compare these. I suspect you got at least one of them wrong. This can easily write outside the scene variable and overwrite yPos or xPos.
Try changing to ypos>=worldHeight and see if that works.
If not check how much space you allocate for scene and if it looks OK try making it a bit bigger.
I have to program something that filters email by checking if the source of the email is found in a blacklist or if any word in the email's content is found in a list of blocked words.
Here's the function that filters the email.
void filterEmail(vector<email>& amis, vector<email>& corbeille,
vector<email>& rejete, vector<email>& emails,
vector<string> b, vector<string> w,
vector<string> spam)
{
bool isListed(email, vector<string>);
bool isSpam(email, vector<string>);
for(vector<email>::size_type i = 0; i < emails.size();)
{
if(isListed(emails[i], b))
{
corbeille.push_back(emails[i]);
emails.erase(emails.begin() + i);
}
else i++;
}
for(vector<email>::size_type i = 0; i < emails.size();)
{
if(isListed(emails[i], w))
{
amis.push_back(emails[i]);
emails.erase(emails.begin() + i);
}
else i++;
}
for(vector<email>::size_type i = 0; i < emails.size();)
{
if(isSpam(emails[i], spam))
{
cout << emails[i].source << " " << emails[i].content[0];
rejete.push_back(emails[i]);
emails.erase(emails.begin() + i);
}
else i++;
}
return;
}
I have a really weird problem with the part where it checks for spam words in the content (3rd for loop)
after a few test cout's I realised after the first time isSpam returns true, the content of the email changes to the line where it first returns true, and all the next emails return true.
bool isSpam(const email e, const vector<string> motsinterdis)
{
for(vector<string>::size_type i = 0; i < e.content.size(); ++i)
{
for(vector<string>::size_type j = 0; j < motsinterdis.size(); ++j)
{
if(string::npos != e.content[i].find(motsinterdis[j]))
{
cout << e.source << endl;
cout << motsinterdis[j] << " found in " << e.content[i] << endl;
return true;
}
}
}
return false;
}
I have an Struct Email, which contains a vector content. Sorry for the french variables in there :P
Hope I've been clear enough,
Thanks a lot.