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.

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