Issues while writing a clock with egui

I'm trying to write a clock with egui as my first time to make a gui program , and it seems that I've got some problems .

Code may seems to be like this

impl eframe::App for Clock {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        self.udpate_time();
        //Time updated here
        // pub fn udpate_time(&mut self) {
        //     self.current_time = Local::now();
        // }

        CentralPanel::default().show(ctx, |ui| {
            ui.horizontal(|ui| {
                ui.centered_and_justified(|ui| {
                    ui.heading("Clock");
                });
            });
            ui.heading("Current Time :");
            ui.horizontal(|ui| {
                ui.centered_and_justified(|ui| {
                    ui.label(
                        RichText::new(format!(
                            "{}:{}:{}",
                            self.current_time.hour(),
                            self.current_time.minute(),
                            self.current_time.second()
                        ))
                        .size(30.0),
                    );
                });
            });
        });
    }
}

the time is provided by chrono and is updated at the beginning of the update method

My issue is that the showing time won't be always changed in time , sometimes it kept the time for seconds ,and then changed.

Clock issue

It seems that it is only active when I move my mouse on it

Call request_repaint(). The Fractal Clock Demo has this at the start of update()

    pub fn ui(&mut self, ui: &mut Ui, seconds_since_midnight: Option<f64>) {
        if !self.paused {
            self.time = seconds_since_midnight.unwrap_or_else(|| ui.input(|i| i.time));
            ui.ctx().request_repaint();
        }
2 Likes

Also check out therustlings formated print page. You can maybe pad your numbers with spaces or zeros so it looks more standard "clock"

    // You can right-justify text with a specified width. This will
    // output "    1". (Four white spaces and a "1", for a total width of 5.)
    println!("{number:>5}", number=1);

    // You can pad numbers with extra zeroes,
    println!("{number:0>5}", number=1); // 00001
1 Like

Thanks so much for all your help ! It did help me a lot !
But I hope it only repaints when the time has gone by, instead of every time
So I write the code below , it doesn't seem to work

fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        self.udpate_time();
        // pub fn udpate_time(&mut self) {
        //     self.current_time = Local::now();
        // }

        println!(
            "Current : {} Last : {}",
            self.current_time.second(),
            self.last_second.second()
        );
        if self.last_second.second() != self.current_time.second() {
            //if the time has gone by for a second , the showing numbers should change
            //request to repaint
            println!("Repaint as {}", self.current_time.second());
            ctx.request_repaint();
            self.last_second = self.current_time;
        }

        CentralPanel::default().show(ctx, |ui| {
            ui.horizontal(|ui| {
                ui.centered_and_justified(|ui| {
                    ui.heading("Clock");
                });
            });
            ui.heading("Current Time :");
            ui.horizontal(|ui| {
                ui.centered_and_justified(|ui| {
                    ui.label(
                        RichText::new(format!(
                            "{hour:0>2}:{month:0>2}:{second:0>2}",
                            hour = self.current_time.hour(),
                            month = self.current_time.minute(),
                            second = self.current_time.second()
                        ))
                        .size(30.0),
                    );
                });
            });
        });
    }

If I simply ask it to repaint every time , then it will work

fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        ctx.request_repaint();
        self.udpate_time();

        CentralPanel::default().show(ctx, |ui| {
            ui.horizontal(|ui| {
                ui.centered_and_justified(|ui| {
                    ui.heading("Clock");
                });
            });
            ui.heading("Current Time :");
            ui.horizontal(|ui| {
                ui.centered_and_justified(|ui| {
                    ui.label(
                        RichText::new(format!(
                            "{hour:0>2}:{month:0>2}:{second:0>2}",
                            hour = self.current_time.hour(),
                            month = self.current_time.minute(),
                            second = self.current_time.second()
                        ))
                        .size(30.0),
                    );
                });
            });
        });
    }

Updating and repainting are the same thing in egui. There's simply no way to run update and not repaint.

By default, you can either update every time an input event is received, or update continuously.

However, since this is specifically a clock, you can probably just use Context::request_repaint_after to schedule the repaint.

If you want to use a more complex scheme, you'll need to write your own backend that implements the appropriate logic to detect whether an update is needed, run the update, and cache the resulting rendered output.

1 Like

Do I understand it in a correct way ?

Now I think that the framework will only call the update method at first and paint only the first frame if the window is not active, and request_repaint or request_repaint_after means that the next frame will be painted at once or after the time I given and the update method will be called before painting

On a repaint, inside your update(), if you call request_repaint() then equi will schedule an immediate repaint. If you call request_repaint_after(duration) egui will schedule a repaint after duration. If you don't call either of those, then egui will do a repaint when it needs to.

1 Like

I learnt that , thanks !

The topic will be closed