为何此文本在右上角
代码太长,我没写注释,问chatgpt他说我代码太长不肯回我{:10_266:}import pygame
from selenium import webdriver
from requests import get
from subprocess import getstatusoutput as _gsout
from threading import Thread, Timer
from os import remove
from os.path import isfile
from pickle import load, dump
from time import sleep
from bs4 import BeautifulSoup
from lxml import html
pygame.init()
pygame.key.set_repeat(1000, 50)
class Button(pygame.sprite.Sprite):
def __init__(self, name, size, font: pygame.font.Font, bgc, fgc, pos, key='\0'):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface(size)
self.image.fill(bgc)
surf = font.render(name, False, fgc)
rect = surf.get_rect()
rect.center = self.image.get_rect().center
self.image.blit(surf, rect)
self.rect = self.image.get_rect()
self.rect.topleft = pos
self.key = key
self.font = font
self.bgc = bgc
self.fgc = fgc
def chosen(self, event: pygame.event.Event):
if event.type == pygame.MOUSEBUTTONUP:
if self.rect.collidepoint(event.pos):
return True
if event.type == pygame.KEYDOWN:
if event.key == ord(self.key) and event.mod & pygame.KMOD_ALT:
return True
return False
def draw(self):
screen.blit(self.image, self.rect)
class Text(pygame.sprite.Sprite):
def __init__(self, text, font, color, pos):
pygame.sprite.Sprite.__init__(self)
self.font = font
self._text = text
self.color = color
self.image = self.font.render(self.text, False, self.color)
self.rect = self.image.get_rect()
self.rect.topleft = pos
def draw(self):
screen.blit(self.image, self.rect)
@property
def text(self):
return self._text
@text.setter
def text(self, new):
self._text = new
self.image = self.font.render(self.text, False, self.color)
class Entry(pygame.sprite.Sprite):
def __init__(self, size, font, bgc, bdc, fgc, pos):
pygame.sprite.Sprite.__init__(self)
self.bgc = bgc
self.bdc = bdc
self.image = pygame.Surface(size)
self.image.fill(bgc)
for x in range(0, size):
self.image.set_at((x, 0), bdc)
self.image.set_at((x, size - 1), bdc)
for y in range(0, size):
self.image.set_at((0, y), bdc)
self.image.set_at((size - 1, y), bdc)
self.text = Text('', font, fgc, pos)
self.image.blit(self.text.image, (0, 0))
self.rect = self.image.get_rect()
self.rect.topleft = pos
self.selected = False
@property
def fgc(self):
return self.text.color
def draw(self):
screen.blit(self.image, self.rect)
def listen(self, event):
if event.type == pygame.MOUSEBUTTONDOWN:
self.selected = self.rect.collidepoint(event.pos)
elif event.type == pygame.KEYDOWN:
if self.selected:
if event.key == pygame.K_BACKSPACE:
self.text.text = self.text.text[:-1]
self._update_text()
elif (event.unicode in
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+[];,./{}|:"<>?'
+ "'" + '\\'
):
self.text.text += event.unicode
self._update_text()
def _update_text(self):
size = self.rect.size
self.image = pygame.Surface(size)
self.image.fill(self.bgc)
for x in range(0, size):
self.image.set_at((x, 0), self.bdc)
self.image.set_at((x, size - 1), self.bdc)
for y in range(0, size):
self.image.set_at((0, y), self.bdc)
self.image.set_at((size - 1, y), self.bdc)
self.text = Text(self.text.text, self.text.font, self.fgc, self.rect.topleft)
self.image.blit(self.text.image, (0, 0))
class PasswordEntry(Entry):
def _update_text(self):
size = self.rect.size
self.image = pygame.Surface(size)
self.image.fill(self.bgc)
for x in range(0, size):
self.image.set_at((x, 0), self.bdc)
self.image.set_at((x, size - 1), self.bdc)
for y in range(0, size):
self.image.set_at((0, y), self.bdc)
self.image.set_at((size - 1, y), self.bdc)
self.text = Text(len(self.text.text) * '*', self.text.font, self.fgc, self.rect.topleft)
self.image.blit(self.text.image, (0, 0))
class MyThread(Thread):
def __init__(self, func, args=(), kwargs=None, timeout=None):
Thread.__init__(self)
self.func = func
self.args = args
self.kwargs = {} if kwargs is None else kwargs
self.timeout = timeout
self.result = None
def run(self):
self.result = self.func(*self.args, **self.kwargs)
def timeout(seconds):
def decorated(func):
def done(*args, **kwargs):
err = None
result = None
def inner():
nonlocal err, result
try:
result = func(*args, **kwargs)
except BaseException as msg:
err = msg
thread = Thread(target=inner)
thread.start()
# 只等待seconds秒
thread.join(seconds)
# 如果线程还活着
if thread.is_alive():
raise TimeoutError
if err:
raise err
return result
return done
return decorated
# 实际上是生成了一个新的decorated函数,通过闭包的形式保存了秒数,然后done里再调用inner
@timeout(1)
def soutf(msg):
return _gsout(msg)
def check_internet():
try:
soutf('ping fishc.com.cn')
# 这东西,报错可是最快
print('你没联网')
exit()
except TimeoutError:
# 连上了的话那就好说
pass
def load_image(url):
filename = 'temp.png'
with open(filename, 'wb') as f:
f.write(get(url, headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
}).content)
image = pygame.image.load(filename)
remove(filename)
return image
def save():
with open('fishc.set', 'wb') as f:
dump(data, f)
def loginf(email, password):
driver.get('https://fishc.com.cn/member.php?mod=logging&action=login')
sleep(1)
driver.find_element(
'xpath',
'/html/body/div/div/div/div/div/div/div/form/div/div/table/tbody/tr/td/input'
).send_keys(email)
driver.find_element(
'xpath',
'/html/body/div/div/div/div/div/div/div/form/div/div/table/tbody/tr/td/input'
).send_keys(password)
driver.find_element(
'xpath',
'/html/body/div/div/div/div/div/div/div/form/div/div/table/tbody/tr/td/button'
).click()
sleep(1)
driver.find_element('id', 'succeedmessage_href').click()
return driver.page_source
def getdata(source):
tree = html.fromstring(source)
part = html.tostring(tree.xpath('//strong[@class="vwmy"]'), encoding='unicode')
usergroup = html.tostring(tree.xpath('//a[@id="g_upmine"]'), encoding='unicode')
soup = BeautifulSoup(part, features='lxml')
soup2 = BeautifulSoup(usergroup, features='lxml')
return soup.find('a').text, soup2.find('font').get('color'), soup2.find('font').text
def login_to1(email, password):
return getdata(loginf(email, password))
def login_to(email, password):
result = login_to1(email, password)
Timer(3, hide_msg).start()
return result
def hide_msg():
global state
state = 3
check_internet()
size = width, height = (640, 480)
screen = pygame.display.set_mode(size)
logo = load_image('https://fishc.com.cn/static/image/common/logo.png')
icon = load_image('https://fishc.com.cn/favicon.ico')
pygame.display.set_caption('FishC App')
pygame.display.set_icon(icon)
font15 = pygame.font.SysFont('microsoftyaheiui', 15)
font20 = pygame.font.SysFont('microsoftyaheiui', 20)
font20b = pygame.font.SysFont('microsoftyaheiui', 20)
font20b.set_bold(True)
chrome = Button('hrome', (100, 50), font20, (0, 255, 0), (0, 0, 0), (100, 200), 'c')
firefox = Button('irefox', (100, 50), font20, (0, 255, 0), (0, 0, 0), (300, 200), 'f')
c_chrome = Button('Change driver(Using Chrome)', (200, 50), font15, (255, 255, 255), (0, 0, 0), (width - 200, 0))
c_firefox = Button('Change driver(Using Firefox)', (200, 50), font15, (255, 255, 255), (0, 0, 0), (width - 200, 0))
change = c_chrome
login = Button('登录(L)', (100, 50), font20, (0, 0, 255), (255, 255, 255), (width - 123, height - 100), 'l')
save1 = Button('保存数据(S)', (150, 50), font20, (0, 0, 255), (255, 255, 255), (width // 2 - 125, height // 2 - 50), 's')
unsave = Button('不保存数据(N)', (150, 50), font20, (0, 0, 255), (255, 255, 255), (width // 2 - 125, height // 2 + 50), 'n')
swin = pygame.Rect(width // 4, height // 4, width // 2, height // 2)
username = Entry((200, 30), font20, (255, 255, 255), (0, 0, 127), (0, 0, 0), (200, 100))
pwd = Entry((200, 30), font20, (255, 255, 255), (0, 0, 127), (0, 0, 0), (200, 180))
t_user = Text('用户名/邮箱', font20b, (0, 0, 0), (90, 100))
t_pwd = Text('密码', font20b, (0, 0, 0), (100, 180))
logining = Text('', font15, (0, 0, 0), (300, 200))
succed = Text('', font15, (0, 0, 0), (width - 150, 10))
data = {
'driver': None,
'username': None,
'password': None
}
state = 0
if isfile('fishc.set'):
with open('fishc.set', 'rb') as f:
data = load(f)
thread = None
clock = pygame.time.Clock()
running = True
while running:
clock.tick(30)
screen.fill((255, 255, 255))
screen.blit(logo, (0, 0))
if state == 1:
pygame.draw.rect(screen, (0, 0, 0), swin, 2)
save1.draw()
unsave.draw()
elif state == 0:
if data['driver'] is None:
chrome.draw()
firefox.draw()
else:
change.draw()
if data['username'] is None or data['password'] is None:
username.draw()
t_user.draw()
pwd.draw()
t_pwd.draw()
login.draw()
elif state == 2:
if thread.result is None:
logining.text = '登录中...'
else:
logining.text = '登录成功!'
logining.draw()
elif state == 3:
succed.text = f'{thread.result}(用户组: {thread.result})'
succed.color = thread.result
succed.rect.topleft = (width - succed.rect.width - 10, 10)
succed.draw()
for event in pygame.event.get():
if event.type == pygame.QUIT:
if state == 1:
running = False
# 虽然只会退出for
break
state = 1
if state == 1:
if save1.chosen(event):
save()
running = False
elif unsave.chosen(event):
running = False
else:
if data['driver'] is None:
temp = False
if chrome.chosen(event):
data['driver'] = (webdriver.Chrome, webdriver.ChromeOptions)
change = c_chrome
temp = True
elif firefox.chosen(event):
data['driver'] = (webdriver.Firefox, webdriver.FirefoxOptions)
change = c_firefox
temp = True
if temp:
option = data['driver']()
option.add_argument('headless')
driver = data['driver'](options=option)
else:
if data['username'] is None or data['password'] is None:
username.listen(event)
pwd.listen(event)
if change.chosen(event):
data['driver'] = None
if login.chosen(event):
data['username'] = username.text.text
data['password'] = pwd.text.text
state = 2
thread = MyThread(func=login_to, args=(username.text.text, pwd.text.text))
thread.start()
pygame.display.flip()
pygame.quit()
driver.close()
就这么一个文件
picture: 从您提供的代码来看,登录成功后,用户名显示在右上角是由以下代码实现的:
succed = Text('', font15, (0, 0, 0), (width - 150, 10))
这行代码创建了一个名为succed的Text对象,将其初始位置设置为屏幕右上角附近。具体来说, width - 150使文本距离屏幕右侧 150 像素, 10则是距离屏幕顶部的像素数。当登录成功时, state变为 3,下面的代码将用户名和用户组信息显示在屏幕上:
elif state == 3:
succed.text = f'{thread.result}(用户组: {thread.result})'
succed.color = thread.result
succed.rect.topleft = (width - succed.rect.width - 10, 10)
succed.draw()
在这段代码中,首先更新succed的文本属性,包括用户名和用户组信息。接着,根据文本的宽度,重新计算并设置文本的位置,使其始终保持在屏幕右上角附近。最后调用succed.draw()方法将文本绘制在屏幕上。 isdkz 发表于 2023-5-1 07:56
从您提供的代码来看,登录成功后,用户名显示在右上角是由以下代码实现的:
似乎并没有回答问题 歌者文明清理员 发表于 2023-5-1 08:00
似乎并没有回答问题
要将用户名显示在屏幕正中间,首先需要在每次更新文本内容时计算正确的位置。可以通过以下方法调整代码来实现:
1. 修改succed对象的初始化位置,使其在屏幕正中间。这里,我们将其位置设置为(width // 2, height // 2) :
succed = Text('', font15, (0, 0, 0), (width // 2, height // 2))
2. 在登录成功时,更新succed对象的位置,使其始终保持在屏幕正中间:
elif state == 3:
succed.text = f'{thread.result}(用户组: {thread.result})'
succed.color = thread.result
succed.rect.center = (width // 2, height // 2)
succed.draw()
这里,我们将succed.rect.topleft替换为succed.rect.center ,并将其位置设置为屏幕中心点(width // 2, height // 2) 。这样,在登录成功后,用户名和用户组信息将显示在屏幕正中间。 isdkz 发表于 2023-5-1 08:03
要将用户名显示在屏幕正中间,首先需要在每次更新文本内容时计算正确的位置。可以通过以下方法调整代码来 ...
也不是正中间啊 歌者文明清理员 发表于 2023-5-1 08:09
也不是正中间啊
抱歉,看起来是文本的渲染方式导致的。为了使文本更精确地居中,可以在绘制文本前计算文本宽度的一半,并将其减去屏幕宽度的一半。这样可以确保文本在屏幕中心位置上。修改代码如下:
1. 在Text类中添加一个方法draw_centered ,用于计算并绘制居中的文本:
class Text:
# 省略其他代码...
def draw_centered(self, surface):
self.surface = self.font.render(self.text, True, self.color)
self.rect = self.surface.get_rect()
self.rect.center = (width // 2, height // 2)
surface.blit(self.surface, self.rect.topleft)
2. 更新state == 3的情况,使用新的draw_centered方法绘制居中的文本:
elif state == 3:
succed.text = f'{thread.result}(用户组: {thread.result})'
succed.color = thread.result
succed.draw_centered(screen)
这样,当登录成功后,用户名和用户组信息将准确显示在屏幕正中间。 isdkz 发表于 2023-5-1 08:14
抱歉,看起来是文本的渲染方式导致的。为了使文本更精确地居中,可以在绘制文本前计算文本宽度的一半,并 ...
看你的代码知道为什么了 isdkz 发表于 2023-5-1 08:14
抱歉,看起来是文本的渲染方式导致的。为了使文本更精确地居中,可以在绘制文本前计算文本宽度的一半,并 ...
是因为text.setter里更新text的时候没更新rect
页:
[1]