当用户单击它时如何移动无框架 pygame 窗口? [英] How to move a no frame pygame windows when user click on it?

查看:19
本文介绍了当用户单击它时如何移动无框架 pygame 窗口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我会创建一个 pygame 窗口,它没有框架,但是当用户点击它并移动鼠标时会移动.所以我尝试了这个脚本,但是当我点击窗口时,打印的是0"而不是1"

i would create a pygame window that haven't frame but that move move when the user click on it and move the mouse. So I try this script but when I click on the windows, '0' printed but not '1'

但是我的脚本有问题

# coding : utf-8
import pygame
from pygame.locals import *
from random import randint
from os import environ
from math import sqrt
pygame.init()

max_fps = 250

clock = pygame.time.Clock()
window_size_x, window_size_x = 720, 360

infos = pygame.display.Info()
environ['SDL_VIDEO_WINDOW_POS'] = str(int(infos.current_w / 2)) + ',' + str(int(infos.current_h / 2)) # center the window
screen = pygame.display.set_mode((window_size_x, window_size_x), pygame.NOFRAME)

def move_window(): # move the windows when custom bar is hold
        window_x, window_y = eval(environ['SDL_VIDEO_WINDOW_POS'])
        mouse_x, mouse_y = pygame.mouse.get_pos()
        dist_x , dist_y = mouse_x - window_x, mouse_y - window_y # calcul the dictance between mouse and window origin

        for event in pygame.event.get():        
            if event.type != MOUSEBUTTONUP: # while bar is hold
                print('1')
                mouse_x, mouse_y = pygame.mouse.get_pos()
                environ['SDL_VIDEO_WINDOW_POS'] = str(mouse_x - dist_x) + ',' + str(mouse_x - dist_x)
                screen = pygame.display.set_mode((window_size_x, window_size_x), pygame.NOFRAME) # rebuild window

def main():
    run = True
    while run :
        screen.fill((255, 255, 255))

        pygame.display.update()
        clock.tick(60) # build frame with 60 frame per second limitation

        for event in pygame.event.get():
            if event.type == MOUSEBUTTONDOWN:
                print('0')
                move_window()

if __name__ == '__main__':
    main()

推荐答案

编写一个函数,根据之前的鼠标位置移动窗口(start_x, start_y) 和鼠标位置 (new_x, new_y)

Write a function, which moves the window from dependent on a previous mouse position (start_x, start_y) and a mouse position (new_x, new_y)

def move_window(start_x, start_y, new_x, new_y):
        global window_size_x, window_size_y

        window_x, window_y = eval(environ['SDL_VIDEO_WINDOW_POS'])
        dist_x, dist_y = new_x - start_x, new_y - start_y
        environ['SDL_VIDEO_WINDOW_POS'] = str(window_x + dist_x) + ',' + str(window_y + dist_y)
 
        # Windows HACK
        window_size_x += 1 if window_size_x % 2 == 0 else -1 

        screen = pygame.display.set_mode((window_size_x, window_size_y), pygame.NOFRAME)

在这个函数中有很重要的一行:

In this function is a very important line:

window_size_x += 1 if window_size_x % 2 == 0 else -1

此行交替更改窗口宽度 +1 和 -1.在 Windows 系统上似乎有一个错误,如果窗口的大小没有改变,它会忽略新的位置参数.
这个黑客"是一种解决方法,只要位置发生变化,窗口的大小就会稍微改变.

this line changes the width of the window from alternately by +1 and -1. On Windows systems there seems to be a bug, which ignores the new position parameter, if the size of the window didn't change.
This "hack" is a workaround, which slightly change the size of the window whenever the position is changed.

没有闪烁的另一种方法可能如下所示.但请注意,此版本要慢得多:

A different approach, with no flickering, may look as follows. Note, though, that this version is significantly slower:

def move_window(start_x, start_y, new_x, new_y):
        global window_size_x, window_size_y
        buffer_screen = pygame.Surface((window_size_x, window_size_y))
        buffer_screen.blit(pygame.display.get_surface(), pygame.display.get_surface().get_rect())

        window_x, window_y = eval(environ['SDL_VIDEO_WINDOW_POS'])
        dist_x, dist_y = new_x - start_x, new_y - start_y
        environ['SDL_VIDEO_WINDOW_POS'] = str(window_x + dist_x) + ',' + str(window_y + dist_y)

        window_size_x += 1 if window_size_x % 2 == 0 else -1 

        screen = pygame.display.set_mode((window_size_x, window_size_y), pygame.NOFRAME)
        screen.blit(buffer_screen, buffer_screen.get_rect())
        pygame.display.flip()

改变MOUSEMOTIONMOUSEBUTTONUP上的位置:

def main():
    run = True
    pressed = False
    start_pos = (0,0)
    while run :

        # [...]

        for event in pygame.event.get():

            if event.type == MOUSEBUTTONDOWN:
                pressed = True
                start_pos = pygame.mouse.get_pos()

            elif event.type == MOUSEMOTION:
                if pressed:
                    new_pos = pygame.mouse.get_pos()
                    move_window(*start_pos, *new_pos)
                    pygame.event.clear(pygame.MOUSEBUTTONUP)

            elif event.type == MOUSEBUTTONUP:
                pressed = False
                new_pos = pygame.mouse.get_pos()
                move_window(*start_pos, *new_pos)

完整示例程序:

# coding : utf-8
import pygame
from pygame.locals import *
from os import environ
pygame.init()

clock = pygame.time.Clock()
window_size_x, window_size_y = 720, 360

infos = pygame.display.Info()
environ['SDL_VIDEO_WINDOW_POS'] = str(int(infos.current_w/2)) + ',' + str(int(infos.current_h/2)) 
screen = pygame.display.set_mode((window_size_x, window_size_x), pygame.NOFRAME)

def move_window(start_x, start_y, new_x, new_y): 
        global window_size_x, window_size_y

        window_x, window_y = eval(environ['SDL_VIDEO_WINDOW_POS'])
        dist_x, dist_y = new_x - start_x, new_y - start_y
        environ['SDL_VIDEO_WINDOW_POS'] = str(window_x + dist_x) + ',' + str(window_y + dist_y)

        window_size_x += 1 if window_size_x % 2 == 0 else -1
        screen = pygame.display.set_mode((window_size_x, window_size_y), pygame.NOFRAME) 

def main():
    run = True
    pressed = False
    start_pos = (0,0)
    while run :
        screen.fill((255, 255, 255))
        pygame.display.update()
        clock.tick(60)

        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    run = False

            if event.type == MOUSEBUTTONDOWN:
                pressed = True
                start_pos = pygame.mouse.get_pos()

            elif event.type == MOUSEMOTION:
                if pressed:
                    new_pos = pygame.mouse.get_pos()
                    move_window(*start_pos, *new_pos)
                    pygame.event.clear(pygame.MOUSEBUTTONUP)

            elif event.type == MOUSEBUTTONUP:
                pressed = False
                new_pos = pygame.mouse.get_pos()
                move_window(*start_pos, *new_pos)

if __name__ == '__main__':
    main()


此解决方案不再适用于 Windows 系统和 Pygame 2.0.但是,可以使用 WINAPI 函数 MoveWindow:

import pygame
from ctypes import windll

pygame.init()
screen = pygame.display.set_mode((400, 400), pygame.NOFRAME)
clock = pygame.time.Clock()

def moveWin(new_x, new_y):
    hwnd = pygame.display.get_wm_info()['window']
    w, h = pygame.display.get_surface().get_size()
    windll.user32.MoveWindow(hwnd, new_x, new_y, w, h, False)

window_pos = [100, 100]
moveWin(*window_pos)

run = True
while run :
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                run = False
        elif event.type == pygame.MOUSEMOTION:
            if  pygame.mouse.get_pressed()[0]:
                window_pos[0] += event.rel[0]
                window_pos[1] += event.rel[1]
                moveWin(*window_pos)
    
    screen.fill((255, 255, 255))
    pygame.display.update()
    clock.tick(60)

这篇关于当用户单击它时如何移动无框架 pygame 窗口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆