pub struct PushButton { /* private fields */ }Expand description
A pressable button with an optional click callback.
PushButton uses a builder pattern: call PushButton::new to
obtain a Builder, chain .on_clicked(f), .parent(w), then call
.build() or .show().
§Signals
| Method | Qt signal | When |
|---|---|---|
Builder::on_clicked | QPushButton::clicked | Button is pressed and released |
§Memory safety
Signal closures are stored on the heap and passed to C++ as u64
tokens. On Drop:
- No Qt parent: closures are reclaimed, then the C++ object is deleted. Safe — no more signals can fire after deletion.
- Has Qt parent: closures are intentionally leaked to prevent use-after-free (the C++ widget outlives the Rust wrapper and could still fire signals). Keep the Rust wrapper alive for the widget’s full lifetime to avoid this leak.
§Example
use qtrs::PushButton;
let btn = PushButton::new("Click me")
.on_clicked(|| println!("clicked!"))
.build();Implementations§
Source§impl PushButton
impl PushButton
Sourcepub fn new(text: impl Into<String>) -> Builder
pub fn new(text: impl Into<String>) -> Builder
Start building a new QPushButton.
Returns a Builder. Chain configuration, then call .build().
Examples found in repository?
examples/basic/basic.rs (line 16)
3fn main() {
4 let app = Application::new();
5
6 // Build a top-level window
7 let mut window = Widget::new()
8 .title("Hello, qtrs!")
9 .size(400, 300)
10 .icon("assets/icon.png")
11 .build();
12
13 // Put widgets in a vertical layout
14 let mut layout = VBoxLayout::with_parent(&window);
15
16 let btn = PushButton::new("Click me")
17 .on_clicked(|| println!("clicked!"))
18 .build();
19 let label = Label::new("Welcome!").build();
20
21 // Layout takes ownership of widgets
22 layout.add_widget(Box::new(btn));
23 layout.add_widget(Box::new(label));
24
25 // Install layout, then show the window
26 window.set_vlayout(layout.layout_ptr());
27 window.show();
28
29 // Enter the Qt event loop
30 app.exec();
31}More examples
examples/demo/demo.rs (line 47)
10fn main() {
11 let app = Application::new();
12
13 // ============================================================
14 // Main window
15 // ============================================================
16 let window = Widget::new()
17 .title("qtrs Widget Gallery")
18 .icon("assets/icon.png")
19 .size(900, 700)
20 .build();
21
22 // ============================================================
23 // Main layout
24 // ============================================================
25 let mut main_layout = VBoxLayout::with_parent(&window);
26 main_layout.set_spacing(10);
27 main_layout.set_contents_margins(15, 15, 15, 15);
28
29 // ============================================================
30 // Title
31 // ============================================================
32 let title_label = Label::new("\nqtrs Widget Gallery")
33 .parent(&window)
34 .build();
35 main_layout.add_widget(Box::new(title_label));
36
37 // ============================================================
38 // Section 1: Buttons
39 // ============================================================
40 let group1 = GroupBox::new("Buttons")
41 .parent(&window)
42 .build();
43 let mut g1_layout = VBoxLayout::with_parent(&group1);
44 g1_layout.set_spacing(8);
45
46 // PushButton
47 let btn = PushButton::new("Click Me")
48 .on_clicked(|| println!("[LOG] Button clicked"))
49 .parent(&group1)
50 .build();
51 g1_layout.add_widget(Box::new(btn));
52
53 // CheckBox
54 let cb = CheckBox::new("Check me")
55 .checked(false)
56 .on_toggled(|checked| println!("[LOG] CheckBox: {}", checked))
57 .parent(&group1)
58 .build();
59 g1_layout.add_widget(Box::new(cb));
60
61 // RadioButton group
62 let rb1_label = Label::new("Radio Group (click to log):").parent(&group1).build();
63 g1_layout.add_widget(Box::new(rb1_label));
64
65 let rb1 = RadioButton::new("Option A")
66 .checked(true)
67 .on_toggled(|checked| {
68 if checked {
69 println!("[LOG] Radio selected: A");
70 }
71 })
72 .parent(&group1)
73 .build();
74 g1_layout.add_widget(Box::new(rb1));
75
76 let rb2 = RadioButton::new("Option B")
77 .checked(false)
78 .on_toggled(|checked| {
79 if checked {
80 println!("[LOG] Radio selected: B");
81 }
82 })
83 .parent(&group1)
84 .build();
85 g1_layout.add_widget(Box::new(rb2));
86
87 let rb3 = RadioButton::new("Option C")
88 .checked(false)
89 .on_toggled(|checked| {
90 if checked {
91 println!("[LOG] Radio selected: C");
92 }
93 })
94 .parent(&group1)
95 .build();
96 g1_layout.add_widget(Box::new(rb3));
97
98 main_layout.add_widget(Box::new(group1));
99
100 // ============================================================
101 // Section 2: Input widgets
102 // ============================================================
103 let group2 = GroupBox::new("Inputs")
104 .parent(&window)
105 .build();
106 let mut g2_layout = VBoxLayout::with_parent(&group2);
107 g2_layout.set_spacing(8);
108
109 // LineEdit
110 let edit = LineEdit::new("Type text here...")
111 .on_return_pressed(|| println!("[LOG] LineEdit return pressed"))
112 .parent(&group2)
113 .build();
114 g2_layout.add_widget(Box::new(edit));
115
116 // ComboBox
117 let mut combo = ComboBox::new()
118 .items(&["Item 1", "Item 2", "Item 3", "Item 4"])
119 .on_current_text_changed(|| println!("[LOG] ComboBox text changed"))
120 .parent(&group2)
121 .build();
122 combo.connect_current_index_changed(|idx| {
123 println!("[LOG] ComboBox index: {}", idx);
124 });
125 g2_layout.add_widget(Box::new(combo));
126
127 // TextEdit
128 let text_edit = TextEdit::new()
129 .placeholder("Write multi-line text here...")
130 .on_text_changed(|| println!("[LOG] TextEdit content changed"))
131 .parent(&group2)
132 .build();
133 g2_layout.add_widget(Box::new(text_edit));
134
135 main_layout.add_widget(Box::new(group2));
136
137 // ============================================================
138 // Section 3: Full Bidirectional Sync (Slider ↔ SpinBox → ProgressBar)
139 // ============================================================
140 let group3 = GroupBox::new("Values")
141 .parent(&window)
142 .build();
143 let mut g3_layout = VBoxLayout::with_parent(&group3);
144 g3_layout.set_spacing(8);
145
146 // Build all widgets first (before adding to layout)
147 let bar = ProgressBar::new()
148 .range(0, 100)
149 .value(50)
150 .format("%p%")
151 .parent(&group3)
152 .build();
153
154 let slider = Slider::horizontal()
155 .range(0, 100)
156 .parent(&group3)
157 .build();
158 slider.set_value(50);
159
160 let spin = SpinBox::new()
161 .range(0, 100)
162 .value(50)
163 .suffix(" units")
164 .parent(&group3)
165 .build();
166
167 // ============================================================
168 // ALL connections BEFORE adding to layout
169 // ============================================================
170
171 // Slider → SpinBox (bidirectional)
172 slider.connect(
173 VALUE_CHANGED,
174 &spin,
175 SET_VALUE,
176 ConnType::Queued,
177 );
178
179 // SpinBox → Slider (bidirectional)
180 spin.connect(
181 VALUE_CHANGED,
182 &slider,
183 SET_VALUE,
184 ConnType::Queued,
185 );
186
187 // Slider → ProgressBar
188 slider.connect(
189 VALUE_CHANGED,
190 &bar,
191 SET_VALUE,
192 ConnType::Auto,
193 );
194
195 // SpinBox → ProgressBar
196 spin.connect(
197 VALUE_CHANGED,
198 &bar,
199 SET_VALUE,
200 ConnType::Auto,
201 );
202
203 // ============================================================
204 // NOW add widgets to layout (after all connections)
205 // ============================================================
206 g3_layout.add_widget(Box::new(bar));
207 g3_layout.add_widget(Box::new(slider));
208 g3_layout.add_widget(Box::new(spin));
209
210 main_layout.add_widget(Box::new(group3));
211
212 // ============================================================
213 // Section 4: TabWidget
214 // ============================================================
215 let mut tabs = TabWidget::new()
216 .on_current_changed(|idx| println!("[LOG] Tab changed to: {}", idx))
217 .parent(&window)
218 .build();
219
220 // Tab 1: Simple text
221 let tab1 = Widget::new().parent(&tabs).build();
222 let mut tab1_layout = VBoxLayout::with_parent(&tab1);
223 let tab1_label = Label::new("This is Tab 1").parent(&tab1).build();
224 tab1_layout.add_widget(Box::new(tab1_label));
225 tabs.add_tab(Box::new(tab1), "Tab 1");
226
227 // Tab 2: CheckBoxes
228 let tab2 = Widget::new().parent(&tabs).build();
229 let mut tab2_layout = VBoxLayout::with_parent(&tab2);
230 let cb1 = CheckBox::new("Option X").parent(&tab2).build();
231 let cb2 = CheckBox::new("Option Y").parent(&tab2).build();
232 tab2_layout.add_widget(Box::new(cb1));
233 tab2_layout.add_widget(Box::new(cb2));
234 tabs.add_tab(Box::new(tab2), "Tab 2");
235
236 // Tab 3: Button
237 let tab3 = Widget::new().parent(&tabs).build();
238 let mut tab3_layout = VBoxLayout::with_parent(&tab3);
239 let btn_tab3 = PushButton::new("Tab 3 Button")
240 .on_clicked(|| println!("[LOG] Tab 3 button clicked"))
241 .parent(&tab3)
242 .build();
243 tab3_layout.add_widget(Box::new(btn_tab3));
244 tabs.add_tab(Box::new(tab3), "Tab 3");
245
246 main_layout.add_widget(Box::new(tabs));
247
248 // ============================================================
249 // Section 5: Menu + MenuBar
250 // ============================================================
251 let file_menu = Menu::new("File")
252 .action("New", || println!("[LOG] Menu: New"))
253 .action("Open", || {
254 println!("[LOG] Menu: Open");
255 if let Some(path) = FileDialog::open_file(
256 None, // No parent needed
257 "Select a file",
258 "",
259 "All Files (*.*);;Text Files (*.txt);;Images (*.png *.jpg *.bmp)"
260 ) {
261 println!("[LOG] File selected: {}", path);
262 } else {
263 println!("[LOG] File dialog cancelled");
264 }
265 })
266 .action("Save", || {
267 println!("[LOG] Menu: Save");
268 if let Some(path) = FileDialog::select_directory(
269 None, "Select a directory to save",
270 "",
271 ) {
272 println!("[LOG] Directory selected: {}", path);
273 } else {
274 println!("[LOG] File dialog cancelled");
275 }
276 })
277 .action("Exit", || {
278 println!("[LOG] Menu: Exit");
279 std::process::exit(0);
280 })
281 .parent(&window)
282 .build();
283
284 let edit_menu = Menu::new("Edit")
285 .action("Copy", || println!("[LOG] Menu: Copy"))
286 .action("Paste", || println!("[LOG] Menu: Paste"))
287 .action("Cut", || println!("[LOG] Menu: Cut"))
288 .parent(&window)
289 .build();
290
291 let help_menu = Menu::new("Help")
292 .action("About", || {
293 println!("[LOG] Menu: About");
294 dialog::information(
295 None, // No parent needed
296 "About",
297 "qtrs Widget Gallery\nVersion 0.2.5\n\nAll widgets test",
298 );
299 })
300 .parent(&window)
301 .build();
302
303 let _menubar = MenuBar::new()
304 .add_menu(file_menu)
305 .add_menu(edit_menu)
306 .add_menu(help_menu)
307 .parent(&window)
308 .build();
309
310 // ============================================================
311 // Bottom buttons: Dialogs
312 // ============================================================
313 let mut bottom_layout = HBoxLayout::new();
314 bottom_layout.set_spacing(10);
315
316 let info_btn = PushButton::new("Show Info")
317 .on_clicked(|| {
318 println!("[LOG] Info dialog shown");
319 dialog::information(None, "Info", "This is an information dialog");
320 })
321 .parent(&window)
322 .build();
323 bottom_layout.add_widget(Box::new(info_btn));
324
325 let warn_btn = PushButton::new("Show Warning")
326 .on_clicked(|| {
327 println!("[LOG] Warning dialog shown");
328 dialog::warning(None, "Warning", "This is a warning dialog");
329 })
330 .parent(&window)
331 .build();
332 bottom_layout.add_widget(Box::new(warn_btn));
333
334 let ask_btn = PushButton::new("Ask Question")
335 .on_clicked(|| {
336 println!("[LOG] Question dialog shown");
337 let answer = dialog::question(None, "Question", "Are you sure?");
338 println!("[LOG] Answer: {}", if answer { "Yes" } else { "No" });
339 })
340 .parent(&window)
341 .build();
342 bottom_layout.add_widget(Box::new(ask_btn));
343
344 let mut bottom_widget = Widget::new().parent(&window).build();
345 bottom_widget.set_hlayout(bottom_layout.layout_ptr());
346 main_layout.add_widget(Box::new(bottom_widget));
347
348 // ============================================================
349 // Status bar
350 // ============================================================
351 let status_label = Label::new("Status: Ready - All widgets loaded")
352 .parent(&window)
353 .build();
354 main_layout.add_widget(Box::new(status_label));
355
356 // ============================================================
357 // Show window and run
358 // ============================================================
359 window.show();
360 println!("[LOG] Application started - all widgets loaded");
361 println!("[LOG] Interact with widgets to see logs in terminal");
362
363 app.exec();
364}Sourcepub fn set_text(&mut self, text: impl Into<String>)
pub fn set_text(&mut self, text: impl Into<String>)
Update the button text at runtime.
This calls
QPushButton::setText.
Sourcepub fn show(&self)
pub fn show(&self)
Show this button.
Normally child widgets are shown automatically by their parent; use this only for standalone buttons.
Sourcepub fn connect_clicked<F: Fn() + 'static>(&mut self, f: F)
pub fn connect_clicked<F: Fn() + 'static>(&mut self, f: F)
Connect a click callback to an already-existing button.
This is the runtime equivalent of
Builder::on_clicked — useful when the button was loaded
from a .ui file rather than built in Rust.
Trait Implementations§
Source§impl AsWidget for PushButton
impl AsWidget for PushButton
Source§fn set_has_parent(&mut self)
fn set_has_parent(&mut self)
Mark this widget as having a Qt parent. Read more
Source§impl Drop for PushButton
impl Drop for PushButton
Auto Trait Implementations§
impl !Send for PushButton
impl !Sync for PushButton
impl Freeze for PushButton
impl RefUnwindSafe for PushButton
impl Unpin for PushButton
impl UnsafeUnpin for PushButton
impl UnwindSafe for PushButton
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> ConnectExt for Twhere
T: AsWidget,
impl<T> ConnectExt for Twhere
T: AsWidget,
Source§fn connect<S, T>(
&self,
_signal: S,
target: &dyn AsWidget,
_slot: T,
conn_type: ConnType,
) -> bool
fn connect<S, T>( &self, _signal: S, target: &dyn AsWidget, _slot: T, conn_type: ConnType, ) -> bool
Connect a signal to a slot with compile-time type checking. Read more
Source§fn disconnect<S, T>(&self, _signal: S, target: &dyn AsWidget, _slot: T) -> boolwhere
S: SignalMeta,
T: SlotMeta,
fn disconnect<S, T>(&self, _signal: S, target: &dyn AsWidget, _slot: T) -> boolwhere
S: SignalMeta,
T: SlotMeta,
Disconnect a signal-slot connection. Read more