How to make a simple table simply?

I have a bit of tabular data that I want to display in aligned rows and columns, i.e. as a table. I see there is an iced_table crate, but it seems overly-complicated for what I want, with features I don’t need. My table has only four rows and three columns. I could endure the complexity of iced_table if it did what I want, but it can’t even optimize its column widths to the content the way an HTML table does automatically.

Is there a simple way to display some text in aligned rows and columns, such that the rows and columns are big enough to contain the content but no bigger than necessary, with the sizes set automatically? I’m looking for the iced equivalent of HTML’s

<table>
  <tr>
    <td>Alice</td>
    <td>21</td>
  </tr>
  <tr>
    <td>Bob</td>
    <td>66</td>
  </tr>
</table>

Thanks!

I have a project that I kind of have a similar problem with, where I have 3 columns and n number of rows (~1500 in my case). And the bad news is that iced does not:

  1. Have a native table widget
  2. Optimize for out-of-view content. So the 1500x3 text widgets lags quite a bit

Now the iced_table crate you mentioned is not bad, it sort of is clunky to get going, I get that, so there is a way to get the content you requested, it looks quite similar:

use iced::widget::{button, column, container, horizontal_space, row, scrollable, text};
use iced::{Application, Command, Element, Length};


    fn view(&self) -> Element<'static, Message> {
        container(scrollable(
            row![
                horizontal_space(),
                column!(
                    text("item1"),
                    text("item2"),
                    text("item3"),
                    text("item4"),
                    text("item5"),
                ),
                column!(
                    text("set1"),
                    text("set2"),
                    text("set3"),
                    text("set4"),
                    text("set5"),
                ),
                horizontal_space()
            ]
            .spacing(20),
        ))
        .width(Length::Fixed(450.0))
        .into()
    }

I’m not too familiar with the behaviour of the html you posted, but I’m pretty sure what I posted does the job.

image
image
You can mess with the width and if you want the horizontal spacing if you want it to look a certain way, but this will do the thing you need. (Also once you add enough items, or set .width() on the container, a scrollbar will appear on the right, so you can navigate the content.

What happens if you have a longer item that takes even more space? Will the text wrap to a new line? Or will it overwrite the next column or will the rightmost column get pushed off the right edge of the screen or something else?

And FYI, I cut and pasted the HTML code in my OP into this editor and it displays properly:

Alice 21
Bob 66

And if I add more text to one of the cells it resizes and wraps properly:

Alice 21
Bob Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

I'm not asking for much. Can Iced, apparently the leading GUI library for Rust, do what web browsers have been able to do since three decades ago?

I got a working version:
image

It isn’t super clean, and is sort of a bit of boilerplate. But it is pretty much like the segment you sent:

    fn view(&self) -> Element<'static, Message> {
        container(scrollable(
            row![
                horizontal_space(),
                column![
                    row![text("item1"), text("value1")].spacing(10),
                    row![text("item2"),
 text("your super long text. i dont want to clutter this so its not included")]
                    .spacing(10)
                    .align_items(Alignment::Center),
                    row![text("item3"), text("value3")].spacing(10),
                    row![text("item4"), text("value4")].spacing(10),
                ],
                horizontal_space()
            ]
            .spacing(20),
        ))
        .width(Length::Fixed(450.0))
        .into()
    }

So the .align_items() call is so the text that has the super long text next to it is in the center instead of the top of that little area.

If you swap the contents only of the first and second columns with each other, but leave everything else the same what does it look like? Specifically, what does the following produce?

fn view(&self) -> Element<'static, Message> {
        container(scrollable(
            row![
                horizontal_space(),
                column![
                    row![text("value1"), text("item1")].spacing(10),
                    row![text("your super long text. i dont want to clutter this so its not included"),
 text("item2")]
                    .spacing(10)
                    .align_items(Alignment::Center),
                    row![text("value3"), text("item3")].spacing(10),
                    row![text("value4"), text("item4")].spacing(10),
                ],
                horizontal_space()
            ]
            .spacing(20),
        ))
        .width(Length::Fixed(450.0))
        .into()
    }```

If you swap the two you get the following:
image
Note that the text on the right is cut off, it should says “items2”. I was also messing around with the text and spacing a bit so it might look different than previous screenshots.

You can fix the cut off by adding a dummy text with some whitespace to fix it

image

row![text("super long text"), text("items2"), text("  ")]
.spacing(30)
.align_items(Alignment::Center),

im pretty certain text is getting some type of makeover (there was some discussion in the discord iirc), so hopefully these little quirks are changed.

It seems here that the right column is not a column. If this were a tabular display then “value1” (or “item1” in the code I posted) should be above “items2”. But I see “value1” above “txtxt…” which is the left, not the right, column.

Well it isn’t really a table. What I’m doing is just mimicking how a table looks. And in the previous screenshot, the items were aligned to the start. If you change the alignment to Alignment::End, it will move them over.

Again, its sort of finicky, and iced isn’t perfect. You do have the iced_table crate , and you have the ability to create your own widgets where you can customize the behaviours (not the best thing to hear i know).

image

Actually I don’t have the iced_table crate, since that cannot automatically set the cell sizes based on content.

Yes, I could write my own widget, or even my own gui library, but if I can avoid reinventing the wheel, I would prefer to do other things with my time.

I admit I’m quite surprised that creating such a simple text alignment in a Rust GUI is so unsupported, since it’s commonly seen for example in web browsers and MS-Word. And I’m even more surprised that I seem to be the first person to ask about it. egui can’t do it, Iced can’t do it. Now I’m looking into Slint, maybe there’s a way.

Anyway, thanks for you suggestions. At least I can move on with confidence to another library, knowing that I’m not overlooking some way to do it in Iced.

Have you looked at Grid in Iced additional widgets. iced_aw/src/widgets/grid at main · iced-rs/iced_aw · GitHub

This looks like it might be the way, thank you. So far I don’t see how to make the text wrap into multiple lines; it displays one long line that runs off the right edge.

I see there is a widget called wrap in the same crate, but don’t think that’s for turning single line text into multiline. Maybe there is another iced widget for this?