LINUX.ORG.RU

C++ Окно, интерфейс.

 ,


1

3

Здравствуйте. Я новичок в линуксе, программировании, С++, вообще во всем. У меня слабый ПК(ноут с селероном) и линукс минт на нем. Мне для моих экспериментов нужно желательно прямо из консоли(с помощью g++ например), скомпилировать бинарный файлик, который откроет окно на который выбрасывается массив пикселлей, вычесленный этой же програмкой. У меня freeGlut, но на данный момент библиотеки openGL избыточны. Но если не найду ответа, останусь на нем. Знаю про Qt - тяжело, комп с трудом тянет, Processing - это прекрасный инструмент, есть, пользуюсь, но это не С++, Jetpack Multiplatform, и прочие фреймфорки - не то. Очень тяжелые. Хотелось бы чтоб как в glut, дал пару директив, инициализировал окно и пользуйся.

Не думаю что есть ответ, но спрошу еще: если у кого есть шаблон или ссылка на него, как просто в файле *.cpp без тоннны сторонних библиотек запустить окошко в линуксе, да еще, пикселль повесить туда по заданным координатам, то буду благодарен.(где-то в книжке по С видел такое, попытался повтоить, компилятор меня не понял)

Ну, совсем без библиотек не получится, но если у ваc есть X11, то доставьте libX11-devel и сможете в main.cpp творить вот такое:

#include <X11/Xlib.h>

int main() {
    Display *display = XOpenDisplay(NULL);
    if (display == NULL) {
        return 1;
    }

    int screen = DefaultScreen(display);
    Window window = XCreateSimpleWindow(display, RootWindow(display, screen), 0, 0, 200, 200, 1, BlackPixel(display, screen), WhitePixel(display, screen));

    XSelectInput(display, window, ExposureMask | KeyPressMask);
    XMapWindow(display, window);

    XEvent event;
    while (1) {
        XNextEvent(display, &event);

        if (event.type == Expose) {
            GC gc = XCreateGC(display, window, 0, 0);
            XSetForeground(display, gc, BlackPixel(display, screen));
            XDrawPoint(display, window, gc, 100, 100); // Координаты пикселя
            XFreeGC(display, gc);
        }

        if (event.type == KeyPress) {
            break;
        }
    }

    XCloseDisplay(display);
    return 0;
}

Соберете:

g++ -o pixel main.cpp -lX11

и запустите ./pixel

Obezyan
()
Ответ на: комментарий от LightDiver

Нет). Но я понял тебя. Я хотел получть ответ на вопрос и я его получил в первом комментарии. Но тут ты со своим растом. Прикольный язык, прикольный синтаксис.

Usuk_Ikota
() автор топика
Ответ на: комментарий от LightDiver

яж не собираюсь делать серьезные проекты. Да даже если и придется, то всеравно надо пройти через это, чтоб хоть немного понимать что происходит внутри инструмента, который я использую

Usuk_Ikota
() автор топика
Ответ на: комментарий от LightDiver

Сможешь понять что тут происходит?

Код на lua для WoW, отправляет по таймеру состояние элементов для отрисовки в обфусцированном виде чтобы не подменяли на клиенте. Не понял только почему разбиваете сообщение на части по 200 символов если можно по 255. Похоже на то что оставили задел под контрольную сумму, но ее еще не сделали.

Obezyan
()
Ответ на: комментарий от Obezyan

Если ты видя код так думаешь, то пользователи точно не разберутся. Великолепно! Серверный код они видеть в принципе не будут.

На самом деле это передача любых классов для последующей работы с ними подобными же обфусцированными командами.

Первым запросом отправляем класс и его активизацию. Затем сигналы на выполнение методов. Круто, а?

В итоге пользовталеь не видит код, не видит данные, но видит все интерфейсы, любую логику, любые проверки, отвечает на запросы, отправялет на сервер любые проверки. Но читерить не может.

При этом логику ожидаемого ответа можно подменять в любой момент и ожидать, например, в зависимости от текущего времени, да от чего угодно. Хоть последоватьельно дергать десять логик разных. И хрен ты угадаешь что отвечтаь в этот раз.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 4)

Ну, если для обучения, и знаком с английским, и если есть желание приобщиться к чему-то необычному, непопулярному, но очень красивому, даже приобщиться к истокам ООП, то есть смолток.

Для винды мне нравится Дельфин [https://github.com/dolphinsmalltalk/Dolphin/releases], а еще есть кросплатформенный Pharo [https://www.pharo.org/] (их сайт иногда притормаживает и не сразу открывается). Крутая серия книг по смолтоку для начинающих: Pharo by Example 9 [https://books.pharo.org/pharo-by-example9/].

Вот, как раз вывести точку на экран или эллипс - это в Pharo сделать очень просто. Там есть библиотека Morphic. Но скажу сразу, что сам кода на смолтоке почти не писал - только приглядываюсь и много читаю о нем. Там вывести точку или окружность - буквально две-три строчки.

Язык очень лаконичный, предельно простой, но при этом невероятно богатый. Относится к эпохе зарождения ООП. Там еще в 80-м году были лямбда-функции, была уже тогда хорошая библиотека коллекций. Потом ООП пошло в другую сторону совсем, а так вполне можно сказать, что лямбда-функции были в ООП чуть ли не с самого основания, но многие об этом не догадываются…

Еще из экзотики тоже могу предложить Racket [https://racket-lang.org/]. Это разновидность лиспа. Скобок много, но и смысла - тоже, как в любом лиспе. И есть похожие примитивы для вывода геометрических фигур на экран. Опять же, почти Racket не использовал - только приглядывался.

Я сам последнее время на C++ много писал, но вот экзотикой очень интересуюсь. Это как отдушина от рутины. Рутина так надоедает порой.

Ты смотри, и смолток, и лисп вполне подойдут для твоего компьютера. Они, вообще, не требовательные и не жручие, как современные монстры, потому что эти технологии закладывались в 70/80-е, когда персональные компьютеры были в тысячи раз слабее твоего. Это сейчас современные языки и фреймворки пугают и отталкивают своими аппетитами.

anonymous
()
Ответ на: комментарий от LINUX-ORG-RU

Лять, взялся я себе виджет запилить в кеды. Плюсы, qml. Провозился часа три. Подключил ИИшки на поиск нужных модулей. Хер там. Половина не работает, половина работает не так как ожидалось, хер поймешь что не так с теми, кто это все разрабатывал.

Плюнул, за 5 минут написал на расте. Ну я не понимаю, может это со мной что то не так - ну не даются мне плюсы.

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtMultimedia 6.0

ApplicationWindow {
    width: 300
    height: 400
    visible: true
    title: "Будильник"

    ColumnLayout {
        spacing: 10
        anchors.fill: parent
        anchors.margins: 10

        // Время (через TextInput)
        RowLayout {
            Label { text: "Время (чч:мм):" }
            TextField {
                id: alarmTimeInput
                text: "12:00"
                Layout.fillWidth: true
            }
        }

        // Минута
        RowLayout {
            Label { text: "Минута:" }
            TextField {
                id: minuteField
                text: "*"
                Layout.fillWidth: true
            }
        }

        // Час
        RowLayout {
            Label { text: "Час:" }
            TextField {
                id: hourField
                text: "*"
                Layout.fillWidth: true
            }
        }

        // День месяца
        RowLayout {
            Label { text: "День:" }
            TextField {
                id: dayField
                text: "*"
                Layout.fillWidth: true
            }
        }

        // День недели
        RowLayout {
            Label { text: "День недели (0-6):" }
            TextField {
                id: weekdayField
                text: "*"
                Layout.fillWidth: true
            }
        }

        // Музыка
        RowLayout {
            Label { text: "Звук:" }
            TextField {
                id: soundPath
                Layout.fillWidth: true
                readOnly: true
            }
            Button {
                text: "..."
                onClicked: fileDialog.visible = true
            }
        }

        // Кнопка добавления
        Button {
            text: "Добавить будильник"
            onClicked: addAlarm()
        }

        // Список будильников
        ListView {
            model: ListModel {
                id: alarmList
            }
            delegate: ItemDelegate {
                width: parent.width
                text: 'Время: ' + time + ', Звук: ' + sound
            }
        }
    }

    MediaPlayer {
        id: player
    }

    FileDialog {
        id: fileDialog
        title: "Выберите аудиофайл"
        nameFilters: ["Аудио (*.mp3 *.wav)"]
        onAccepted: {
            if (fileUrl) soundPath.text = fileUrl
        }
    }

    Timer {
        id: checkTimer
        interval: 5000
        repeat: true
        onTriggered: checkAlarms()
        Component.onCompleted: start()
    }

    function matches(pattern, value) {
        return pattern === "*" || parseInt(pattern) === value
    }

    function addAlarm() {
        var now = new Date()
        var timeParts = alarmTimeInput.text.split(":")
        var alarmHour = timeParts[0] || "0"
        var alarmMinute = timeParts[1] || "0"

        var item = {
            hour: hourField.text,
            minute: minuteField.text,
            day: dayField.text,
            weekday: weekdayField.text,
            time: alarmHour + ":" + alarmMinute,
            sound: soundPath.text
        }

        alarmList.append(item)
        console.log("Добавлен будильник:", item)
    }

    function checkAlarms() {
        var now = new Date()
        var currentMinute = now.getMinutes()
        var currentHour = now.getHours()
        var currentDay = now.getDate()
        var currentWeekday = now.getDay() - 1

        for (var i = 0; i < alarmList.count; i++) {
            var alarm = alarmList.get(i)

            if (!matches(alarm.minute, currentMinute)) continue
            if (!matches(alarm.hour, currentHour)) continue
            if (!matches(alarm.day, currentDay)) continue
            if (!matches(alarm.weekday, currentWeekday)) continue

            console.log("Сработал будильник!", alarm.time)
            player.source = alarm.sound
            player.play()
        }
    }
}

И раст: https://pastebin.com/raw/uN6ZR5fR

LightDiver ★★★★★
()
Ответ на: комментарий от Usuk_Ikota

Но мне тут первым коментом отличный вариант дали для старта.

А, ну если ты готов писать на xlib – мне остаётся только снять шляпу и отойти в сторону.

Если твои эксперименты это не что-то закрытое для работы, думаю, даже на получившийся код посмотрю с интересом, и не только я.

hobbit ★★★★★
()

Здравствуйте. К перечисленному рекомендую глянуть PureBasic. Сам по себе очень лёгкий и комплит код и FASM-ом и компилятором C. Самый лёгкий запуск под линуксом (в смысле минимальные ресурсы), это Дебиан х32 на виртуалке (2 гига памяти, два ядра проц). В рабочем контуре ВинХР на атоме стоит, (1 ядро, 1 гиг памяти) и вся среда разработки прекрасно работает. С графикой там тоже отлично. 2D библиотека позволяет рисовать в окнах, на экране, спрайте, изображении, холсте, теккстуре и принтере. Т.е. универсальный вариант рисования. 3D и Векторную графику не использовал, т.к. не было надобности, а 2D прям отличное решение. Исполняемые файлы мизерные и всё в одном. Он платный, но с ограничениями по размерам кода работает бесплатно. Смысл в чём. На нём можно написать окно с выводом примера графики, скомпилить в код С и уже его изучать, как оно там всё строится.Вот пример кода рисования линий в окошке

If OpenWindow(0, 0, 0, 200, 200, «2DDrawing Example», #PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
 If CreateImage(0, 200, 200) And StartDrawing(ImageOutput(0))
  Box(0, 0, 200, 200, RGB(255, 255, 255)) 
  For Width = 1 To 180 Step 5
   Line(10, 10, Width, 180, RGB(Random(255), Random(255), Random(255)))
  Next Width
  StopDrawing()
  ImageGadget(0, 0, 0, 200, 200, ImageID(0))
 EndIf

 Repeat
  Event = WaitWindowEvent()
 Until Event = #PB_Event_CloseWindow

EndIf

(прошу сильно не бить за бэйсик)))

strange2007
()
Ответ на: комментарий от Obezyan

Вот! Как я и говорил. Прошло совсем немного времени и я додумался сделать прогрессбар к этой всей загрузке. И тут пригодились уже запасы. Конечно переписать пришлось полностью, но общая моя задумка с запасом была в целом правильная. Просто пользоваться таким я пока не умею.

local sendQueue = {}
local isSending = false

local PROGRESS_BAR_CODE = [[
local frame = CreateFrame('Frame', 'NucleusProgressBar', UIParent)
frame:SetSize(220, 24)
frame:SetPoint('CENTER', 0, 200)
frame:SetFrameStrata('TOOLTIP')

frame.bg = frame:CreateTexture(nil, 'BACKGROUND')
frame.bg:SetTexture(0.1, 0.1, 0.1)
frame.bg:SetAlpha(0.9)
frame.bg:SetAllPoints()

frame.fill = frame:CreateTexture(nil, 'ARTWORK')
frame.fill:SetTexture(0.2, 0.8, 0.2)
frame.fill:SetAlpha(0.8)
frame.fill:SetPoint('TOPLEFT', 2, -2)
frame.fill:SetPoint('BOTTOMLEFT', 2, 2)
frame.fill:SetWidth(0)

frame.text = frame:CreateFontString(nil, 'OVERLAY', 'GameFontHighlight')
frame.text:SetPoint('CENTER')
frame.text:SetTextColor(1, 1, 1, 1)

function UpdateProgress(current, total)
    if total <= 0 then return end
    local width = (frame:GetWidth() - 4) * (current / total)
    frame.fill:SetWidth(width)
    frame.text:SetText(('%d%% (%d/%d)'):format(math.floor(current/total*100), current, total))
    frame:Show()
    if current >= total then
        C_Timer.After(0.05, function() frame:Hide() end)
    end
end]]

local function splitSafe(text, maxChunkSize)
    local lines = {}
    for line in text:gmatch("[^\r\n]+[\r\n]*") do
        table.insert(lines, line)
    end

    local chunks = {}
    local buffer = ""
    for _, line in ipairs(lines) do
        if #buffer + #line > maxChunkSize then
            table.insert(chunks, buffer)
            buffer = ""
        end
        buffer = buffer .. line
    end
    if #buffer > 0 then table.insert(chunks, buffer) end
    return chunks
end

function sendObfuscatedClass(classCode, target)
    local progressChunks = splitSafe(PROGRESS_BAR_CODE, 200)
    for i, chunk in ipairs(progressChunks) do
        local prefix = (i == #progressChunks) and "fSF 0" or "fS 0"
        if target then prefix = prefix.." "..target:sub(1,6) end
        SendAddonMessage(prefix, chunk, "GUILD")
    end

    local wrappedCode = "(function()\n"..classCode.."\nend)()"
    -- Добавляем метаданные прогресса в каждый чанк
    local codeChunks = splitSafe(wrappedCode, 200)
    local totalChunks = #codeChunks
    for i, chunk in ipairs(codeChunks) do
        codeChunks[i] = string.format("--|%d|%d|\n%s", i, totalChunks, chunk)
    end

    sendQueue = {
        id = tostring(math.random(100000,999999)),
        parts = codeChunks,
        target = target,
        index = 1,
        total = #codeChunks
    }

    if not isSending then
        isSending = true
        sendNextFragment()
    end
end

function sendNextFragment()
    if not sendQueue or sendQueue.index > #sendQueue.parts then
        sendQueue = nil
        isSending = false
        return
    end

    local part = sendQueue.parts[sendQueue.index]
    local isFinal = sendQueue.index == #sendQueue.parts
    local prefix = (isFinal and "fSF " or "fS ")..sendQueue.id
    if sendQueue.target then prefix = prefix.." "..sendQueue.target:sub(1,6) end

    local maxLength = 254 - (#prefix:gsub("[\128-\255][\128-\255]", "**"))
    part = part:sub(1, maxLength)

    SendAddonMessage(prefix, part, "GUILD")
    sendQueue.index = sendQueue.index + 1
    C_Timer.After(0.05, sendNextFragment)
end

К каждому тику передачи добавляем функцию обновления прогрессбара минимальную.

LightDiver ★★★★★
()