Я пытаюсь создать окно SDL, которое сохраняет соотношение сторон при изменении размера события. Если пользователь расширяет окно, высота увеличивается и наоборот. Я улавливаю событие SDL_WINDOWEVENT_RESIZED, вычисляет новую ширину или высоту, которая поддерживает соотношение сторон, а затем вызывает SDL_SetWindowSize() с вычисленными значениями.SDL2: Как сохранить соотношение сторон при изменении размера окна
Проблема заключается в том, что вызов функции SDL_SetWindowSize() внутри цикла опроса событий ничего не делает на экране. SDL обновляет переменные размера окна (вызов SDL_GetWindowSize() в моем основном цикле возвращает обновленные размеры окна). Однако фактическое окно не обновляется.
Единственный способ, которым я могу заставить это работать, - постоянно вызывать SDL_SetWindowSize() в основном цикле, но я думаю, что это неправильный способ делать что-то. Следующий код иллюстрирует мою проблему. Есть ли лучший и более чистый способ заставить это работать?
Я использую SDL 2.0.3 и 64-разрядный Ubuntu Linux с рабочим столом GNOME.
#include <SDL2/SDL.h>
static const float ASPECT_RATIO = 16.f/9.f;
SDL_Window* window;
SDL_Renderer* renderer;
uint32_t windowID;
SDL_Rect screen;
bool done = false;
bool resizeDone = false;
void handle_events()
{
SDL_Event e;
while (SDL_PollEvent(&e)) {
switch (e.type) {
case SDL_WINDOWEVENT:
if(e.window.windowID == windowID) {
switch(e.window.event) {
case SDL_WINDOWEVENT_RESIZED: {
int width = e.window.data1;
int height = e.window.data2;
float aspectRatio = (float)width/(float)height;
if(aspectRatio != ASPECT_RATIO) {
if(aspectRatio > ASPECT_RATIO) {
height = (1.f/ASPECT_RATIO) * width;
}
else {
width = ASPECT_RATIO * height;
}
printf("Setting window size to %d, %d, aspect ratio: %f\n",
width, height, (float)width/(float)height);
}
screen.w = width;
screen.h = height;
SDL_SetWindowSize(window, width, height); // <-- does not work
resizeDone = true;
break;
}
}
}
break;
case SDL_QUIT:
done = true;
break;
default:
break;
}
}
}
void run() {
while(!done) {
//SDL_SetWindowSize(window, screen.w, screen.h); // <-- works
handle_events();
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
if(resizeDone) {
int w, h;
SDL_GetWindowSize(window, &w, &h);
printf("SDL_GetWindowSize: %d, %d\n", w, h);
resizeDone = false;
}
}
}
int main(int, char**) {
SDL_Init(SDL_INIT_VIDEO);
uint32_t window_flags = SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
window = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
windowID = SDL_GetWindowID(window);
renderer = SDL_CreateRenderer(window, -1, 0);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
run();
SDL_Quit();
return 0;
}
Работает для меня, но может быть зависимо от оконного менеджера (или даже композитинга). Во всяком случае, ваш 'if (resizeDone)' выглядит как лучшее место для фактического изменения размера; обработка событий должна просто поднять флаг, который необходимо изменить. – keltar
@keltar: с какой системой вы это проверили? В любом случае, спасибо за предложение, я пробую это с другими оконными менеджерами. 'If (resizeDone)' действительно лучшее место для изменения размера, но при моей текущей настройке окно не изменяется, чтобы скорректировать соотношение сторон, если вызов сделан оттуда. – Scam