Koji je najbolji cross platform gui lib?

QT je dobar, ali ruzan.
wxwidgets je tu negde - malo manje elaboriran
TKinter je tek arhaican i vrlo bazican

silesija java GUIja je nazalost Java

zaista x-platform je web ali to nije isto (mada ima ovih meta desktop web app varijanti)

posle nekoliko decenija trazenja kvalitetnog xplatfom gui-ja digao sam ruke. Nikad to nece postojati, pogotovo ako se u x-platform uracunaju i mobilni.

najvise mi je lego GTK ali nije x-platform (mada sam uspevao da nesto napravim za windows u starijoj varijanti, ali ga slabo razvijaju na tu stranu - tamte za kukuriku - windows alati nece na linux, linux alati nece na windows :) ) OSX posebna prica.

Nekako mi je stav - desktop aplikacije ce vremenom prestati da postoje ili cemo konvergirati u jednu vrstu operativnog sistema samim tim u gui ili ce ceo gui da prestane da postoji i preci cemo na ljudski naturalan interfejs - glasovno upravljanje.
 
QT je dobar, ali ruzan.
wxwidgets je tu negde - malo manje elaboriran
ne znas. qt omogucava totalnoi da overajdujes message handling i zanenis sa svojim.
wxidgets je klon mfca.
najvise mi je lego GTK ali nije x-platform (mada sam uspevao da nesto napravim za windows u starijoj varijanti, ali ga slabo razvijaju na tu stranu - tamte za kukuriku - windows alati nece na linux, linux alati nece na windows :) ) OSX posebna prica.
gtk je ok, ali ne radi, na Apple.
Jedino qt pristojno izgleda na Apple.
Mene prakticno interesuje Rust, njbolji lib za njega je iced, ali nije testirano na Apple.
Qt jeste i super radi.
 
oho, iced se rapidno razvija
evo app da prikaze analogni sat:
Kod:
use iced::executor;
use iced::mouse;
use iced::widget::canvas::{stroke, Cache, Geometry, LineCap, Path, Stroke};
use iced::widget::{canvas, container};
use iced::{
    Application, Color, Command, Element, Length, Point, Rectangle, Renderer,
    Settings, Subscription, Theme, Vector,
};

pub fn main() -> iced::Result {
    Clock::run(Settings {
        antialiasing: true,
        ..Settings::default()
    })
}

struct Clock {
    now: time::OffsetDateTime,
    clock: Cache,
}

#[derive(Debug, Clone, Copy)]
enum Message {
    Tick(time::OffsetDateTime),
}

impl Application for Clock {
    type Executor = executor::Default;
    type Message = Message;
    type Theme = Theme;
    type Flags = ();

    fn new(_flags: ()) -> (Self, Command<Message>) {
        (
            Clock {
                now: time::OffsetDateTime::now_local()
                    .unwrap_or_else(|_| time::OffsetDateTime::now_utc()),
                clock: Cache::default(),
            },
            Command::none(),
        )
    }

    fn title(&self) -> String {
        String::from("Clock - Iced")
    }

    fn update(&mut self, message: Message) -> Command<Message> {
        match message {
            Message::Tick(local_time) => {
                let now = local_time;

                if now != self.now {
                    self.now = now;
                    self.clock.clear();
                }
            }
        }

        Command::none()
    }

    fn view(&self) -> Element<Message> {
        let canvas = canvas(self as &Self)
            .width(Length::Fill)
            .height(Length::Fill);

        container(canvas)
            .width(Length::Fill)
            .height(Length::Fill)
            .padding(20)
            .into()
    }

    fn subscription(&self) -> Subscription<Message> {
        iced::time::every(std::time::Duration::from_millis(500)).map(|_| {
            Message::Tick(
                time::OffsetDateTime::now_local()
                    .unwrap_or_else(|_| time::OffsetDateTime::now_utc()),
            )
        })
    }
}

impl<Message> canvas::Program<Message> for Clock {
    type State = ();

    fn draw(
        &self,
        _state: &Self::State,
        renderer: &Renderer,
        _theme: &Theme,
        bounds: Rectangle,
        _cursor: mouse::Cursor,
    ) -> Vec<Geometry> {
        let clock = self.clock.draw(renderer, bounds.size(), |frame| {
            let center = frame.center();
            let radius = frame.width().min(frame.height()) / 2.0;

            let background = Path::circle(center, radius);
            frame.fill(&background, Color::from_rgb8(0x12, 0x93, 0xD8));

            let short_hand =
                Path::line(Point::ORIGIN, Point::new(0.0, -0.5 * radius));

            let long_hand =
                Path::line(Point::ORIGIN, Point::new(0.0, -0.8 * radius));

            let width = radius / 100.0;

            let thin_stroke = || -> Stroke {
                Stroke {
                    width,
                    style: stroke::Style::Solid(Color::WHITE),
                    line_cap: LineCap::Round,
                    ..Stroke::default()
                }
            };

            let wide_stroke = || -> Stroke {
                Stroke {
                    width: width * 3.0,
                    style: stroke::Style::Solid(Color::WHITE),
                    line_cap: LineCap::Round,
                    ..Stroke::default()
                }
            };

            frame.translate(Vector::new(center.x, center.y));

            frame.with_save(|frame| {
                frame.rotate(hand_rotation(self.now.hour(), 12));
                frame.stroke(&short_hand, wide_stroke());
            });

            frame.with_save(|frame| {
                frame.rotate(hand_rotation(self.now.minute(), 60));
                frame.stroke(&long_hand, wide_stroke());
            });

            frame.with_save(|frame| {
                frame.rotate(hand_rotation(self.now.second(), 60));
                frame.stroke(&long_hand, thin_stroke());
            });
        });

        vec![clock]
    }
}

fn hand_rotation(n: u8, total: u8) -> f32 {
    let turns = n as f32 / total as f32;

    2.0 * std::f32::consts::PI * turns
}
 

Back
Top