I'm new to C++ and never used macros before but I beleive they may allow me to solve the following problem although I would welcome alternative solutions.
I have written the following macro:
#define COMMAND(NUMBER){ button_ ## NUMBER ## ->hide(); }
and I want to call it like this
for (int i = 1; i < 10; i++)
{
COMMAND(i)
}
in the hope that when the program executes it would do the equivalent of:
button_1->hide();
button_2->hide();
button_3->hide();
button_4->hide();
.
.
button_10->hide();
The idea is that I want to make a FLTK GUI display/hide widgets dynamically depending on a configuration file being read in when the form is loaded.
Unfortunately it appears that the macro above doesn't work and instead what it does is
button_i->hide();
which causes a compile error because button_i doesn't exist!
So my questions are:
A) Is it possible to do this in C++?
B) Is a macro able to accomplish this?
C) If not what can?
D) If macros can do this then how do I amend the above code to actually get it to work!
Thanks
I'm pretty sure there is a way to make a macro trick work, but there are better options.
You can, for example, store your buttons in an array.
Assuming your buttons have a type called struct button, declare your buttons like this:
struct button *buttons[42];
You need to initialize all of them as you would have for your individual button_X variables.
button[i] = <whatever you do to create button number i>;
Then you can simply do:
for (int i=0; i<42; i++) {
button[i]->hide();
}
Or toggle any individual button with just its number. You'll probably find that better than any macro trick in the long run.
(Warning: arrays are 0-based, so your first button is button[0])
If you have control over the button_2 etc. variables, I would recommend using an array instead. That way you could use a look like:
for (int i = 1; i < 10; i++)
{
button[i]->hide();
}
Of course, this is trivial to place in a macro.
In general, you can't accomplish what you want with a plain loop in C. However, if you really want to go that route, look at the boost preprocessor package.
Do not try to manage the buttons yourself, FLTK does not like that. You will have an awesome array of buttons that you cannot see. I am not sure how to do it the way you want but I would do it this way:
Fl_Button * o = (Fl_Button *)myWindow->child(i);
o->hide();
and let the buttons be children of the FLTK window.
Related
I have a function who's job is to generate a list of checkboxes based upon the contents of an enum.
void Controller::createCheckBoxes()
{
const QMetaObject &mo = LicenseManager::staticMetaObject;
int index = mo.indexOfEnumerator("Packages");
QMetaEnum metaPackeges = mo.enumerator(index);
for (int i=0; i != metaPackeges.keyCount(); ++i)
{
QString name = (metaPackeges.key(i));
if(!packageCheckBoxes.contains(name))
{
QCheckBox* box = new QCheckBox;
ui->layoutCheckBoxes->addRow(box);
box->setText(name); box->setCheckable(true);
packageCheckBoxes.insert(name, box);
}
}
}
Where "Packages" is the enum containing the packages, and "packageCheckBoxes" is the QMap that is holding the checkboxes for other functions to operate on them, and "layoutCheckBoxes" is a Qt form layout that the checkboxes visually reside in.
Now, the checkboxes appear on screen looking correct, exactly how I intend them too, and inside the layout. However, clicking on them, or asking the code to do anything to them, instantly results in a crash and I can't figure out why. There's no explanation given by "Application Output" other than "The program has finished unexpectedly." which amazingly I figured out on my own without this notice /s
I had checkboxes in "layoutCheckBoxes" before, but they were manually generated from Design, and those worked perfectly. The reason I'm going through this hassle is to allow packages to be easily added through the enum, with various functions performing the operations necessary to generate the required checkboxes and hook them up to their appropriate functions.
The function that calls "createCheckboxes" is in the same source file, as well as the other functions that operate on the check boxes.
I don't have control over the enum, it is what it is, and it's what I need to work with.
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.
I've got a pretty old MFC application that's been touched by many people over the years (most of them probably not even CS guys) and it follows, what I like to call the "anarchy design pattern."
Anyway, one of the dialogs has a series of 56 vertical sliders and check boxes. However, there are additional sliders and checkboxes on the dialog as shown below.
Now, the problem is that the additional sliders and checkboxes take on IDs that are in sequence with the slider/checkbox series of the dialog. My task is to add more sliders and checkboxes to the series (in the blank space in the Slider Control group box) Unfortunately, since IDC_SLIDER57 through IDC_SLIDER61 are already in the dialog (same goes for the checkboxes), existing code, such as the snippet below will break:
pVSlider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER1+i);
Is there a better way to modify the resource file without doing it manually? I've seen a third party tool called ResOrg that looks like it'll help do what I want, but the software is a bit pricey, especially since I'll only use it once. I guess I can give the demo a try, but the limitations might restrict me.
FYI, I'm using Visual C++ 6.0 (yes...I know, don't laugh, it's being forced upon me).
Instead of writing:
pVSlider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER1+i);
you could write:
pVSlider = (CSliderCtrl *)GetDlgItem(GetSliderID(i));
where GetSlider is a function that returns the id of slider number i.
GetSlider function
int GetSliderID(int nslider)
{
static int sliderids[] = {IDC_SLIDER1, IDC_SLIDER2, IDC_SLIDER3, .... IDC_SLIDERn};
ASSERT(nslider < _countof(sliderids));
return sliderids[nslider];
}
With this method the IDC_SLIDERn symbols dont need to have sequential values.
I am using Qt to draw out some data visualisations. I have lines which indicate certain important points along a timeline, but I would like to be able to remove these lines from view so that the information underneath is more clearly visible.
I understand how to remove them from sight, but the problem is how to find which QGraphicsItems in the scene's view are Lines and which are not.
I have tried using
try {
qgraphicsitem_cast<QGraphicsLineItem>(scene->items()[i]);
} catch (...) {
}
But this doesn't even compile. I tried checking the output of qgraphicsitem_cast() to see if was 0, but the compiler didn't like that, either.
This is my most current code:
void Plotter::showHideLines() {
int i;
QGraphicsLineItem l;
for (i = 0; i < scene->items().count(); i++) {
try {
qgraphicsitem_cast<QGraphicsLineItem>(scene->items()[i]);
scene->items()[i]->setVisible(!scene->items()[i]->isVisible());
} catch (...) {
}
}
}
Ignore l, I didn't bother to delete it after trying something else.
I am pretty new to Qt, I have just been learning it over the last few days. Can anybody help?
I wouldn't advise iterating through every scene item, just to hide a certain type as things will get slow when the number of items gets large.
Instead, whenever a line is created, add it to a list. When they need to be hidden, iterate through list and hide them. It takes slightly more memory, but is much faster, safer, and requires less coding.
i just can find any example in the internet how to loop and get each item in the QListWidget
int count = listWidget->count();
for(int index = 0;
index < count;
index++)
{
QListWidgetItem * item = listWidget->item(index);
// A wild item has appeared
}
The foreach thing is totally different, I think.
If you want more info on that, look at this
http://doc.qt.digia.com/4.2/containers.html#the-foreach-keyword
scroll down to where it talks about the foreach keyword.
Special thanks to Tomalak Geret'kal for adding the proper characters which my keyboard is unable to produce :)
Due to so many upvotes on this, i'll explain the foreach macro here as well.
foreach is a Qt specific C++ addition, implemented using the preprocessor. If you want to disable the thing, just add CONFIG += no_keywords to your XX.pro file.
Qt makes a copy of the list being iterated, but don't worry about performance. Qt containers use implicit sharing, where the actual contents are not copied. Think of it as two reference variables using the same actual variable. This makes it possible to modify the list you are iterating over, without messing up the loop. Note that modifying the list forces Qt to make a copy of the actual contents of the list the first time it's modified.
foreach can be used to loop over all Qt basic containers, QList QVector QMap QMultiMap and so on. QListWidget is not one of these, so it doesn't work on it, sadly. To make matters worse, QListWidget doesn't provide a list of all items, only the ones selected. There is a method called items, which would seem to be nice, but is protected.
To loop over selected items, I think this would work
foreach(QListWidgetItem * item, listWidget->selectedItems())
{
// A wild item has appeared
}
The first Google result for "QWidgetList" told me how to do it.
You can use a QWidgetListIt iterator.
QWidgetList wl = get_some_widget_list();
for (QWidget* w = wl.first(); w != 0; w = wl.next()) {
// use w
}
// or
foreach (QWidget* w, wl) {
// use w
}
I'm not quite sure where this foreach comes from. If it's not provided by Qt, it may be a macro expanding to BOOST_FOREACH, for which you'll need to include boost/foreach.hpp.