JUCE Tables

gui

#1

I’ve been studying the JUCE demo on and off for a few days and am having a lot of troubles trying to figure tables out. Would anyone be kind enough to provide a step-by-step tutorial on how to get one of these going? I’m not sure why this is so challenging for me, but I just keep struggling to figure it out.

If anyone is able to help, thank you very much.


#2

You need to subclass TableListBoxModel and at the very least implement the pure virtual getNumRows(), paintRowBackground() and paintCell() methods to set up your table. Then you can pass this model to your TableListBox object using the setModel() method and it will be displayed.


#3

Well, I had the getNumRows() overridden my table class, but I was missing paintRowBackground() and paintCell(). I’ve done that now (which I’ve just copied the code that was in the JUCE demo table in those pure virtual overridden functions for now to get me going) and declared an instance of this subclass in my MainComponent and used setModel(myTable) in the constructor of my MainComponent. I’ve also added addAndMakeVisible(). However, I’m still not getting a table in my MainComponent. Not sure what I’m missing. I know that I have no code to define where the table pops up on the GUI and I’m probably missing a ton of other things, but I’m just not sure what else I’m missing.


#4

I havent been working with [TableListBox] just yet, but those are quite similar to [ListBox]'es. Here is my template code for simple [ListBox] setup. I hope it will help you out.

class List : public Component, public ListBoxModel {
    	public:
    		List() {
    			box.setModel(this);
    			box.setColour(ListBox::backgroundColourId, Colour::greyLevel(0.2f));
    			box.setRowHeight(30);
    			addAndMakeVisible(box);
    		}
    	
    		void paintListBoxItem(int rowNumber, Graphics &g, int width, int height, 
    			bool rowIsSelected) override {
    			
    			if(!isPositiveAndBelow(rowNumber, items.size())) return;
    			g.fillAll(Colour::greyLevel(rowIsSelected ? 0.15f : 0.05f));
    			g.setFont(18);
    			g.setColour(Colours::whitesmoke);
    			g.drawFittedText(items.getReference(rowNumber), {6,0,width - 12,height}, Justification::centredLeft, 1, 1.f);
    		}
    	
    		int getNumRows() override {
    			return items.size();
    		}
    	
    		void addItem(const String &text) {
    			items.add(text);
    			box.updateContent();
    			box.selectRow(items.size() - 1);
    		}
    	
    		void resized() override {
    			box.setBounds(getLocalBounds());
    		}
    	
    	private:
    		ListBox box;
    		StringArray items;
    };

class MainComponent : public Component {
    	public:
    		MainComponent() {
    	            addAndMakeVisible(list);
    	
    		    list.addItem("one");
    		    /*(…)*/
    	            list.addItem("seven");
    	
    		    setSize(600, 400);
    		}
    	
    		void resized() override {
    			list.setBounds(0, 0, 110, getHeight());
    		}
    	
    	private:
    		List list;
    };

#5

Wow, thanks a ton for the template. I’ll dig into this tomorrow and see how it applies to the TableListBox.


#6

Found the issue. I ran your code and realized I wasn’t even touching the setBounds function, no wonder it wasn’t showing up! If you can’t tell, this is the first time I’ve gone outside of the Projucer to add a GUI component.


#7

Ha. If you would ask who never made that mistake, it would be pretty silent :wink:


#8

:slight_smile:

anyway, its good to think about resized() as a layout manager for your child components. So whenever you finish set up components, your next step is to lay them out, and thats your inner manager


#9

For sure. I knew that I was going to have to specify the bounds somewhere, but my mind was so wrapped up in trying to figure this whole thing out I totally forgot about resized(). Anyway, my GUIs are pretty lame, only been doing GUI dev for about 4 months now and am learning it all through JUCE. My table is getting there…


#10

I hate to be a burden, but any tips of placing items into the table? Still don’t quite get how this is achieved. I feel very silly for not being able to get this on my own.


#11

have you checked out the JUCE Demo app… it has an example.

Rail


#12

Where are you stuck? Remember TableListBox inherits ListBox, so if the docs seem to lack something, it’s worth to look one level up.

E.g. if you changed the model (adding data), you might have to call ListBox::updateContent().

And maybe you need to shoot a repaint() after it? I never really know, when it is necessary and when not (I was expecting model and view to implement a subject observer pattern, but you need to do that by hand, afaik…)


#13

I’ve read a few other posts about using the updateContent() function, but I’m not even that far. I’m actually stuck at figuring out what sort of structure I need to build in order to hold the information and don’t even know how to go about getting that information into the table. I saw that others used a String for the listbox, but I don’t know what I would use for a table. A 2D array?

JUCE is sweet, but the documentation isn’t easy on GUI beginners (though I’m not sure that JUCE is geared for GUI beginners).


#14

Yeah, unfortunately I studied it and was lost rather quickly. There are times I can extract good information from the JUCE demo and other times it completely loses me, as some of the examples go much further beyond the scope of what I need and end up confusing me.


#15

Exactly. That is can be done by using an Array of Arrays:

Array<Array<float> > myTableData;
myTable.resize (20);
for (auto column : myTable)
    column.resize (10);

Or you can put it into one array and implement the getter yourself:

Array<float> myTableData;
const int columns = 10:
const int rows = 20:
myTableData.resize (columns * rows);

void setValue (const int x, const int y, const float value)
{
    myTableData.set (x + y * columns, value);
}
float getValue (const int x, const int y)
{
    return myTableData [x + columns * y];
}

You see, there are a lot of options, and for the TableListBox it doesn’t really matter, how you implement it, because juce only defines the interface for a TableListBoxModel.

It tries to suit them all, but probably they cannot provide all levels of C++ knowledge. It would have been maybe a good clue to point out, that the implementation is up to the api user…


#16

Hey, just wanted to come back and thank you for the detailed help with this. I forgot to reply back and wanted to come back and do that. Thank you! :slight_smile: