Привет ребят. Я хочу написать что то вроде колоды карт с 3d эффектами на андроид, визуально ближе всего по задумке обычные лаунчеры под андроид(их гриды + перелистывания и пр.). Я перебирала кучу вариантов и... Это мягко говоря какая то жесть. Андроид студию нужно настраивать неделю на всякие зависимости и пр. утрировано с его котлин. Ее вообще не предлагайте, он мне все нервы убил
Мне важно визуально накидывать объекты а не прописывать координатами как в киви на питоне. И еще важно что бы код был... Я не знаю как его описать, попробую и надеюсь вы поймете.
пример C# кода рандомныйusing System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
// 1. Определение интерфейсов для паттерна "Наблюдатель"
// Интерфейс для наблюдателя (Observer)
public interface IObserver
{
// Метод, вызываемый при обновлении данных
void Update(object sender, DataChangedEventArgs args);
}
// Интерфейс для субъекта наблюдения (Subject)
public interface ISubject
{
void RegisterObserver(IObserver observer);
void RemoveObserver(IObserver observer);
void NotifyObservers(DataChangedEventArgs args);
}
// Класс аргументов события (передача данных)
public class DataChangedEventArgs : EventArgs
{
public DateTime Timestamp { get; }
public double Value { get; }
public string Description { get; }
public DataChangedEventArgs(double value, string description)
{
Value = value;
Description = description;
Timestamp = DateTime.Now;
}
}
// 2. Реализация Субъекта (Датчик данных)
public class DataSensor : ISubject
{
// Использование коллекции для хранения подписчиков
private readonly List<IObserver> _observers = new List<IObserver>();
private Random _random = new Random();
public void RegisterObserver(IObserver observer)
{
Console.WriteLine($"[СЕНСОР]: Наблюдатель {observer.GetType().Name} подписан.");
_observers.Add(observer);
}
public void RemoveObserver(IObserver observer)
{
_observers.Remove(observer);
Console.WriteLine($"[СЕНСОР]: Наблюдатель {observer.GetType().Name} отписан.");
}
public void NotifyObservers(DataChangedEventArgs args)
{
// Уведомляем всех подписчиков в цикле
foreach (var observer in _observers)
{
observer.Update(this, args);
}
}
// Асинхронный метод, имитирующий работу датчика
public async Task StartMonitoringAsync(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
// Имитация получения новых данных
double newValue = 20.0 + _random.NextDouble() * 10.0;
var args = new DataChangedEventArgs(newValue, "Новое значение температуры");
Console.WriteLine($"\n[СЕНСОР]: Генерация новых данных: {newValue:F2}°C");
NotifyObservers(args);
// Ожидание перед следующим измерением (асинхронно, не блокирует поток UI/Main)
await Task.Delay(2000, token);
}
}
}
// 3. Реализация конкретных Наблюдателей
public class ConsoleLogger : IObserver
{
public void Update(object sender, DataChangedEventArgs args)
{
Console.WriteLine($"[ЛОГГЕР]: Время: {args.Timestamp:HH:mm:ss} | Получено значение: {args.Value:F2}°C");
}
}
public class AlertSystem : IObserver
{
private const double AlertThreshold = 28.0;
public void Update(object sender, DataChangedEventArgs args)
{
if (args.Value > AlertThreshold)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"[!!! СИГНАЛ !!!]: ВНИМАНИЕ! Превышен порог {AlertThreshold}°C! Текущее значение: {args.Value:F2}°C");
Console.ResetColor();
}
}
}
// 4. Основная программа для запуска
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("--- Запуск Системы Мониторинга (Async Observer Pattern) ---");
var sensor = new DataSensor();
var logger = new ConsoleLogger();
var alertSystem = new AlertSystem();
// Подписка наблюдателей на события датчика
sensor.RegisterObserver(logger);
sensor.RegisterObserver(alertSystem);
// Используем CancellationTokenSource для возможности отмены асинхронной задачи
var cts = new CancellationTokenSource();
try
{
// Запуск мониторинга в асинхронном режиме
var monitoringTask = sensor.StartMonitoringAsync(cts.Token);
Console.WriteLine("\nСистема работает. Нажмите любую клавишу для отмены и выхода.");
Console.ReadKey(); // Блокируем Main поток, пока пользователь не нажмет клавишу
// Отмена задачи мониторинга
cts.Cancel();
await monitoringTask; // Ожидаем завершения асинхронной задачи
}
catch (TaskCanceledException)
{
Console.WriteLine("\nЗадача мониторинга была отменена.");
}
finally
{
// Отписка перед выходом
sensor.RemoveObserver(logger);
sensor.RemoveObserver(alertSystem);
Console.WriteLine("\n--- Работа системы завершена. ---");
}
}
}
qt рандомныйimport QtQuick
import QtQuick.Window
Window {
width: 400
height: 600
visible: true
title: "3D Карта в Qt QML"
property real rotY: 0
property real rotX: 0
property bool dragging: false
Timer {
interval: 16 // ~60fps
running: !dragging
repeat: true
onTriggered: rotY += 1 // Авто-ротация по Y
}
MouseArea {
anchors.fill: parent
onPressed: { dragging = true; mouse.accepted = true }
onReleased: dragging = false
onPositionChanged: (mouse) => {
if (dragging) {
rotY += mouse.x - pmouse.x // Горизонталь по Y
rotX -= mouse.y - pmouse.y // Вертикаль по X (инверт)
}
}
}
Rectangle {
width: 250
height: 350
anchors.centerIn: parent
color: "#007bff"
radius: 20
layer.enabled: true // Для smooth
Image {
anchors.fill: parent
source: "card.png" // Кинь PNG карты в папку, или убери для цвета
fillMode: Image.Stretch
}
Text {
anchors.centerIn: parent
text: "Твоя карта"
color: "white"
font.pixelSize: 28
}
transform: [
Rotation { origin.x: width/2; origin.y: height/2; axis { x: 0; y: 1; z: 0 }; angle: rotY },
Rotation { origin.x: width/2; origin.y: height/2; axis { x: 1; y: 0; z: 0 }; angle: rotX },
Rotation { origin.x: width/2; origin.y: height/2; axis { x: 0; y: 0; z: 1 }; angle: 45 } // Фикс перспектива
]
Rectangle { // Тень для 3D-вида
anchors.centerIn: parent
width: parent.width; height: parent.height
color: "black"
opacity: 0.3
radius: 20
z: -1
transform: Rotation { origin.x: width/2; origin.y: height/2; axis { x: 1; y: 0; z: 0 }; angle: 90 }
}
}
}
Да это qt а не ЯП. Я понимаю, но это просто пример что бы обьяснить. В С# идет куча всяких нагромождений... Я не знаю как это назвать. Параметров для функции что ли. Что бы написать что то простое из разряда "Привет qna.habr!" нужно создавать кучу всяких параметров функций, а так же в целом код какой то тяжелый для визуального восприятия.
В qt не нужно создавать кучу параметров что бы задать размеры обьекта и пр. ты просто пишешь ширина такая то и все. И + там как то все логично устроено что ли, я не знаю, но визуально он читается проще.
Повторюсь, я в курсе что qt это по сути оболочка для питона со своими приколами. Но здесь я просто показала что там код более лаконичный что ли. Я не знаю как это назвать.
И еще, я не матерый программист, а скорее дизайнер с навыками программирования. В основном писала на питоне, но тоже не сказать что я его прям хорошо знаю. Он мне знаком если что. Я это к тому, что я могу не понять если вы скажете что то замудреное
Для реализации моей задумки что подойдет ? посоветуйте. Я просто могу не знать других ЯП и пр. Есть всякие Nym, go и пр. может кто то что то пишет и подскажет. Пока приглядываюсь как раз к qt + питон