Capy — Framework GUI Nativo Multiplataforma em Zig
O Capy é o framework de interface gráfica de usuário (GUI) mais promissor do ecossistema Zig. Projetado para criar aplicações desktop nativas multiplataforma, o Capy utiliza os widgets nativos de cada sistema operacional — GTK no Linux, Win32 no Windows e Cocoa no macOS — proporcionando aplicações que se integram naturalmente ao ambiente do usuário.
O Que É o Capy
O Capy é um framework GUI declarativo escrito em Zig que abstrai as diferenças entre toolkits nativos. Em vez de renderizar sua própria interface (como o Flutter ou o Electron), o Capy usa os controles nativos do sistema operacional, resultando em aplicações que:
- Parecem naturais em cada plataforma
- Consomem menos memória que soluções baseadas em browser
- Iniciam instantaneamente sem overhead de runtime
- Respeitam temas e configurações de acessibilidade do sistema
Arquitetura
O Capy utiliza uma arquitetura em camadas:
- API Declarativa: Interface de alto nível em Zig para definir layouts e widgets
- Backend Abstrato: Camada de abstração sobre toolkits nativos
- Backends Nativos: Implementações específicas para cada plataforma
Backends Suportados
- Linux: GTK3/GTK4 via bindings C
- Windows: Win32 API nativa
- macOS: Cocoa via Objective-C runtime
- WebAssembly: Canvas HTML5 para aplicações web
- Framebuffer: Renderização direta para sistemas embarcados
Começando com o Capy
Instalação
Adicione o Capy como dependência no seu build.zig.zon:
.{
.name = "minha-app-gui",
.version = "0.1.0",
.dependencies = .{
.capy = .{
.url = "https://github.com/capy-ui/capy/archive/refs/tags/v0.5.0.tar.gz",
.hash = "1220...",
},
},
}
Configure o build.zig:
const std = @import("std");
const capy = @import("capy");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "minha-app",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const capy_dep = b.dependency("capy", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("capy", capy_dep.module("capy"));
b.installArtifact(exe);
}
Hello World
const capy = @import("capy");
pub fn main() !void {
var app = try capy.App.init();
defer app.deinit();
var window = try capy.Window.init(.{
.title = "Olá, Capy!",
.width = 400,
.height = 300,
});
try window.setContent(
capy.Column(.{}, .{
capy.Label(.{ .text = "Bem-vindo ao Capy!" }),
capy.Button(.{
.label = "Clique aqui",
.on_click = struct {
fn callback() void {
std.debug.print("Botão clicado!\n", .{});
}
}.callback,
}),
}),
);
try window.show();
try app.run();
}
Widgets Disponíveis
Widgets Básicos
O Capy oferece um conjunto abrangente de widgets nativos:
// Label - texto estático
capy.Label(.{ .text = "Texto informativo" })
// Button - botão clicável
capy.Button(.{ .label = "Confirmar", .on_click = meu_callback })
// TextInput - campo de entrada de texto
capy.TextInput(.{
.placeholder = "Digite seu nome...",
.on_change = on_text_change,
})
// Checkbox
capy.Checkbox(.{ .label = "Aceitar termos", .checked = false })
// Slider
capy.Slider(.{ .min = 0, .max = 100, .value = 50 })
// Image
capy.Image(.{ .source = "assets/logo.png" })
// Canvas para desenho livre
capy.Canvas(.{
.on_draw = minha_funcao_desenho,
.width = 800,
.height = 600,
})
Containers e Layouts
// Coluna vertical
capy.Column(.{ .spacing = 10 }, .{
capy.Label(.{ .text = "Item 1" }),
capy.Label(.{ .text = "Item 2" }),
capy.Label(.{ .text = "Item 3" }),
})
// Linha horizontal
capy.Row(.{ .spacing = 10 }, .{
capy.Button(.{ .label = "Esquerda" }),
capy.Button(.{ .label = "Direita" }),
})
// Stack para sobreposição
capy.Stack(.{}, .{
capy.Image(.{ .source = "fundo.png" }),
capy.Label(.{ .text = "Texto sobre imagem" }),
})
// ScrollView para conteúdo rolável
capy.ScrollView(.{
.direction = .vertical,
}, capy.Column(.{}, items))
Sistema de Eventos
O Capy usa callbacks para tratar eventos, aproveitando as capacidades de closures do Zig:
const State = struct {
contador: i32 = 0,
label: *capy.Label = undefined,
};
var state = State{};
// Botão com closure que captura estado
capy.Button(.{
.label = "Incrementar",
.on_click = struct {
fn callback() void {
state.contador += 1;
state.label.setText(
std.fmt.bufPrint(&buf, "Contagem: {}", .{state.contador}) catch "Erro",
);
}
}.callback,
})
Eventos Comuns
on_click: Clique do mouseon_change: Alteração de valor (inputs, sliders)on_key_press: Tecla pressionadaon_mouse_move: Movimento do mouseon_focus/on_blur: Ganhar/perder focoon_resize: Redimensionamento de janelaon_draw: Renderização customizada (Canvas)
Canvas para Desenho Customizado
Quando os widgets padrão não são suficientes, use o Canvas para desenho livre:
capy.Canvas(.{
.on_draw = struct {
fn draw(ctx: *capy.DrawContext) void {
// Retângulo
ctx.setColor(.{ .r = 255, .g = 0, .b = 0, .a = 255 });
ctx.fillRect(10, 10, 100, 50);
// Círculo
ctx.setColor(.{ .r = 0, .g = 0, .b = 255, .a = 255 });
ctx.fillCircle(200, 100, 40);
// Texto
ctx.setColor(.{ .r = 0, .g = 0, .b = 0, .a = 255 });
ctx.drawText(10, 80, "Texto desenhado no canvas");
// Linha
ctx.setColor(.{ .r = 0, .g = 128, .b = 0, .a = 255 });
ctx.drawLine(0, 0, 300, 200);
}
}.draw,
})
Aplicação Completa: Calculadora
Um exemplo mais completo demonstrando o uso de múltiplos widgets e estado:
const capy = @import("capy");
const std = @import("std");
const Calculadora = struct {
display: []const u8 = "0",
acumulador: f64 = 0,
operacao: ?u8 = null,
fn pressionarDigito(self: *Calculadora, digito: u8) void {
// Lógica da calculadora
_ = self;
_ = digito;
}
fn calcular(self: *Calculadora) f64 {
// Executar operação
_ = self;
return 0;
}
};
pub fn main() !void {
var app = try capy.App.init();
defer app.deinit();
var window = try capy.Window.init(.{
.title = "Calculadora Zig",
.width = 300,
.height = 400,
});
try window.setContent(
capy.Column(.{ .spacing = 5 }, .{
// Display
capy.Label(.{
.text = "0",
.alignment = .right,
}),
// Linhas de botões
criarLinhaBotoes("7", "8", "9", "/"),
criarLinhaBotoes("4", "5", "6", "*"),
criarLinhaBotoes("1", "2", "3", "-"),
criarLinhaBotoes("0", ".", "=", "+"),
}),
);
try window.show();
try app.run();
}
Estilização
O Capy permite customização visual mantendo a aparência nativa:
capy.Label(.{
.text = "Texto estilizado",
.font_size = 24,
.font_weight = .bold,
.color = .{ .r = 51, .g = 51, .b = 51, .a = 255 },
.background = .{ .r = 240, .g = 240, .b = 240, .a = 255 },
.padding = .{ .top = 10, .right = 20, .bottom = 10, .left = 20 },
})
Comparação com Alternativas
| Característica | Capy | GTK (C) | Qt (C++) | Electron |
|---|---|---|---|---|
| Linguagem | Zig | C | C++ | JS/HTML |
| Widgets nativos | Sim | Parcial | Próprios | Não |
| Tamanho binário | ~5 MB | ~20 MB | ~50 MB | ~150 MB |
| Uso de memória | Baixo | Médio | Médio | Alto |
| Compilação cruzada | Nativa | Complexa | Complexa | N/A |
| Curva aprendizado | Média | Alta | Alta | Baixa |
Casos de Uso Ideais
O Capy é especialmente adequado para:
- Ferramentas de desenvolvimento e utilitários desktop
- Aplicações de linha de negócio que precisam parecer nativas
- Dashboards e painéis de monitoramento
- Editores de configuração e ferramentas administrativas
- Aplicações embarcadas com interface gráfica (via framebuffer)
Próximos Passos
Explore outras bibliotecas visuais do ecossistema como o Mach Engine para jogos e as bibliotecas gráficas para renderização avançada. Para aprender mais sobre Zig, confira nossos tutoriais e receitas práticas.