pygame - 向下滚动页面

2023-12-25

简而言之,我的程序是一个联系人应用程序,这显然意味着一个人需要能够在应用程序中存储多个联系人,这反过来又意味着联系人最终将“离开”屏幕,所以我需要能够向下滚动页面,以便人们可以看到他们的所有联系人并与特定联系人进行交互。

但是,我有点困惑......我该怎么做?我面临的问题是应用程序的宽度和高度是固定的,因此我无法向下滚动页面却发现背景将变成黑色,因为我的矩形的大小仅与应用程序窗口一样长长度。另一个问题是我只是不知道如何“推”屏幕。我就是不知道。

这是到目前为止该程序的代码:

import pickle
import operator
import pygame
import sys
from pygame.locals import *
from itertools import groupby

#create Contact class
class Contact():
    def __init__(self, firstName, lastName, address, groupType,
                 telephone, mobile, email, photoField):
        self.firstName = firstName
        self.lastName = lastName
        self.address = address
        self.groupType = groupType
        self.telephone = telephone
        self.mobile = mobile
        self.email = email
        self.photoField = photoField

    def showDetails(self):
        print("First Name:\t", self.firstName)
        print("Last Name:\t", self.lastName)
        print("Address:\t", self.address)
        print("Telephone:\t", self.telephone)
        print("Mobile:\t", self.mobile)
        print("Email:\t", self.email)

    @classmethod
    def from_input(cls):
        firstName = input("First Name: ")
        lastName = input("Last Name: ")
        address = input("Address: ")
        telephone = input("Telephone: ")
        mobile = input("Mobile: ")
        email = input("Email: ")
        return cls(firstName, lastName, address, None,

                   telephone, mobile, email, None)

class AddressBook():
    def __init__(self):
        self.contactsList = pickle.load(open("save.p", "rb"))

    def addContact(self, contact = None):
        if contact is None:
            contact = Contact.from_input()
        self.contactsList.append(contact)
        pickle.dump(self.contactsList, open("save.p", "wb"))

    def delContact(self, contact = None):
        if contact is None:
            search = input("Search: ")
            for i in self.contactsList:
                if (i.firstName.lower() == search.lower()) or (i.lastName.lower() == search.lower()):
                    indexed = self.contactsList.index(i)
                    del self.contactsList[indexed]
                    pickle.dump(self.contactsList, open("save.p", "wb"))
                elif (i.firstName.lower() != search.lower()) or (i.lastName.lower() != search.lower()):
                    continue

    def contactInfo(self, contact = None):
        if contact is None:
            search = input("Search: ")
            print()

            #display contact information
            for i in self.contactsList:
                if (i.firstName.lower() == search.lower()) or (i.lastName.lower() == search.lower()):
                    i.showDetails()
                    print()
                elif (i.firstName.lower() != search.lower()) or (i.lastName.lower() != search.lower()):
                    continue
                else:
                    print("No contacts\n")

    def contactSearch(self, contact = None):
        if contact is None:
            search = input("Search: ")
            print()

            for i in self.contactsList:
                if (i.firstName.lower() == search.lower()) or (i.lastName.lower() == search.lower()):
                    print(i.firstName, i.lastName)
                    print()
                elif (i.firstName.lower() != search.lower()) or (i.lastName.lower() != search.lower()):
                    continue
                else:
                    print("No contacts\n")

class Page():
    def __init__(self, screen = pygame.display.set_mode((320, 480)), caption = pygame.display.set_caption("Contacts")):
        self.screen = screen
        self.caption = caption

    def style(self):
        pygame.draw.rect(self.screen, (171,0,0), (0,0,320,63), 0)
        pygame.draw.rect(self.screen, (230,230,230), (0,63,320,417), 0)
        pygame.draw.line(self.screen, (120,0,0), (5,61), (320, 61), 2)

class MainPage(Page):
    def __init__(self, screen = pygame.display.set_mode((320, 480)), caption = pygame.display.set_caption("Contacts"), title = "Contacts"):
        Page.__init__(self, screen, caption)
        self.title = title

    def style(self):
        Page.style(self)
        titleFont = pygame.font.SysFont("trebuchet ms", 38)
        textSurface = titleFont.render(self.title, True, (255,255,255))
        self.screen.blit(textSurface, (5, 18))
        AddButton().shape()

    def printContacts(self):
        addressBook = AddressBook()
        addressBook.contactsList
        addressBook.contactsList.sort(key = lambda c: (c.lastName, c.firstName) if c.lastName else (c.firstName, ""))
        contactFont = pygame.font.SysFont("trebuchet ms", 18)
        y = 80

        for (key, g) in groupby(addressBook.contactsList, lambda c: c.lastName[0] if c.lastName else c.firstName[0]):
            groupName = contactFont.render(key, True, (171,0,0))
            self.screen.blit(groupName, (5, y))
            pygame.draw.line(self.screen, (0,0,0), (5,(y+20)), (320, (y+20)), 1)
            y += 30

            for i in g:
                name = i.firstName + " " + i.lastName
                textName = contactFont.render(name, True, (0,0,0))
                pygame.draw.line(self.screen, (210,210,210), (5,(y+20)), (320, (y+20)), 1)
                self.screen.blit(textName, (5, y))
                y += 30

class AddPage(Page):
    def __init__(self, screen = pygame.display.set_mode((320, 480)), caption = pygame.display.set_caption("Contacts"), title = "Add Contact"):
        Page.__init__(self, screen, caption)
        self.title = title

    def style(self):
        Page.style(self)
        titleFont = pygame.font.SysFont("trebuchet ms", 38)
        textSurface = titleFont.render(self.title, True, (255,255,255))
        self.screen.blit(textSurface, (5, 18))
        AddButton().shape()
        CancelButton().shape()

class Button():
    def __init__(self, screen = pygame.display.set_mode((320, 480))):
        self.screen = screen

    def shape(self): 
        pygame.draw.rect(self.screen, (120,0,0), (270,12,40,40), 0)

class AddButton(Button):
    def __init__(self, screen = pygame.display.set_mode((320, 480))):
        Button.__init__(self, screen)

    def shape(self):
        Button.shape(self)
        pygame.draw.line(self.screen, (255,255,255), (289, 15), (289,48), 2)
        pygame.draw.line(self.screen, (255,255,255), (272, 31.5), (307, 31.5), 2)

class CancelButton(Button):
    def __init__(self, screen = pygame.display.set_mode((320, 480))):
        Button.__init__(self, screen)

    def shape(self):
        pygame.draw.rect(self.screen, (120,0,0), (245,20,25,25), 0)
        pygame.draw.aaline(self.screen, (255,255,255), (252,32.5), (263,26))
        pygame.draw.aaline(self.screen, (255,255,255), (252,32.5), (263,39))

pygame.init()
page = MainPage()
page.style()
page.printContacts()

while True:    
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == KEYDOWN and event.key == K_ESCAPE:
            pygame.quit()
            sys.exit()  
        elif event.type == MOUSEBUTTONUP and event.button == 1 and isinstance(page, MainPage):
            if (pygame.mouse.get_pos() >= (270,13)) and (pygame.mouse.get_pos() >= (270,53)) and (pygame.mouse.get_pos() <= (309,13)) and (pygame.mouse.get_pos() <= (309,53)):
                page = AddPage()
                page.style()
        elif event.type == MOUSEBUTTONUP and event.button == 1 and isinstance(page, AddPage):
            if (pygame.mouse.get_pos() >= (270,13)) and (pygame.mouse.get_pos() >= (270,53)) and (pygame.mouse.get_pos() <= (309,13)) and (pygame.mouse.get_pos() <= (309,53)):
                page = MainPage()
                page.style()
                page.printContacts()
            elif (pygame.mouse.get_pos() >= (245,20)) and (pygame.mouse.get_pos() >= (245,45)) and (pygame.mouse.get_pos() <= (370,20)) and (pygame.mouse.get_pos() <= (370,45)):
                page = MainPage()
                page.style()
                page.printContacts()

    pygame.display.update()

    addressBook = AddressBook()
    addressBook.contactsList
    addressBook.contactsList.sort(key = lambda c: (c.lastName, c.firstName) if c.lastName else (c.firstName, ""))

    print("-------------------\nContacts\n")
    for i in addressBook.contactsList:
        print(i.firstName, i.lastName)
    print()

    print("Menu:\n\n1. Add Contact\n2. Show Contact Details\n3. Edit Contact\n4. Delete Contact\n5. Search Contact\n-------------------\n")

    choice = input()
    print()

    if choice == "1":
        #add contacts

        contact = AddressBook().addContact()

    elif choice == "2":
        contact = AddressBook().contactInfo()

    elif choice == "4":
        contact = AddressBook().delContact()

    elif choice == "5":
        contact = AddressBook().contactSearch()

    else:
        continue

对于 pygame 代码和原始 python 代码的混合,我深表歉意,因为我还没有完全将 shell 代码转换为 pygame 可以使用的代码。因此联系人条目等仍然通过 Shell/控制台完成。我首先想完成主屏幕,然后再继续实际能够通过 pygame 传递输入。


正如 Furas 在评论中已经说过的那样,最好使用 Tkinter 或 PyQt 等 GUI 框架,特别是如果你坚持使用 pygame,文本输入将成为你的主要 PITA。有一些用于 pygame 的小部件库,但恕我直言,与“真正的”GUI 框架相比,它们都很糟糕。

尽管如此,有一种简单的方法可以向您的应用程序添加滚动功能。不要将内容直接绘制到屏幕上,而是将其传输到中间层Surface比屏幕高Surface。如果你想向下滚动,只需blit这个中间部分Surface屏幕“上方”Surface.

这是使用鼠标滚轮滚动的简单示例:

import pygame
import string

pygame.init()

screen = pygame.display.set_mode((300, 300))
intermediate = pygame.surface.Surface((300, 600))
i_a = intermediate.get_rect()
x1 = i_a[0]
x2 = x1 + i_a[2]
a, b = (255, 0, 0), (60, 255, 120)
y1 = i_a[1]
y2 = y1 + i_a[3]
h = y2-y1
rate = (float((b[0]-a[0])/h),
         (float(b[1]-a[1])/h),
         (float(b[2]-a[2])/h)
         )
for line in range(y1,y2):
     color = (min(max(a[0]+(rate[0]*line),0),255),
              min(max(a[1]+(rate[1]*line),0),255),
              min(max(a[2]+(rate[2]*line),0),255)
              )
     pygame.draw.line(intermediate, color, (x1, line),(x2, line))

y = 20
f = pygame.font.SysFont('', 17)
for l in string.ascii_uppercase:
    intermediate.blit(f.render(l, True, (255, 255, 255)), (10, y))
    y += 20

clock = pygame.time.Clock()    
quit = False

scroll_y = 0

while not quit:
    quit = pygame.event.get(pygame.QUIT)
    for e in pygame.event.get():
        if e.type == pygame.MOUSEBUTTONDOWN:
            if e.button == 4: scroll_y = min(scroll_y + 15, 0)
            if e.button == 5: scroll_y = max(scroll_y - 15, -300)

    screen.blit(intermediate, (0, scroll_y))
    pygame.display.flip()
    clock.tick(60)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pygame - 向下滚动页面 的相关文章

  • 类的 IPython 表示

    我正在使用我创建的模块尝试 IPython 但它没有显示类对象的实际表示 相反 它显示类似的内容 TheClass module TheClass name I heavily在这个模块中使用元类 我有真正有意义的类表示 应该向用户显示 是
  • matplotlib 图中点的标签

    所以这是一个关于已发布的解决方案的问题 我试图在我拥有的 matplotlib 散点图中的点上放置一些数据标签 我试图在这里模仿解决方案 是否有与 MATLAB 的 datacursormode 等效的 matplotlib https s
  • pandas DataFrame.join 的运行时间是多少(大“O”顺序)?

    这个问题更具概念性 理论性 与非常大的数据集的运行时间有关 所以我很抱歉没有一个最小的例子来展示 我有一堆来自两个不同传感器的数据帧 我需要最终将它们连接成两个very来自两个不同传感器的大数据帧 df snsr1 and df snsr2
  • NLTK 2.0分类器批量分类器方法

    当我运行此代码时 它会抛出一个错误 我认为这是由于 NLTK 3 0 中不存在batch classify 方法 我很好奇如何解决旧版本中的某些内容在新版本中消失的此类问题 def accuracy classifier gold resu
  • 如何从Python中的函数返回多个值? [复制]

    这个问题在这里已经有答案了 如何从Python中的函数返回多个变量 您可以用逗号分隔要返回的值 def get name you code return first name last name 逗号表示它是一个元组 因此您可以用括号将值括
  • 从Django中具有外键关系的两个表中检索数据? [复制]

    这个问题在这里已经有答案了 This is my models py file from django db import models class Author models Model first name models CharFie
  • 在 Django Admin 中调整字段大小

    在管理上添加或编辑条目时 Django 倾向于填充水平空间 但在某些情况下 当编辑 8 个字符宽的日期字段或 6 或 8 个字符的 CharField 时 这确实是一种空间浪费 字符宽 然后编辑框最多可容纳 15 或 20 个字符 我如何告
  • 从 Powershell 脚本安装 Python

    当以管理员身份从 PowerShell 命令行运行以下命令时 可以在 Windows 11 上成功安装 Python c temp python 3 11 4 amd64 exe quiet InstallAllUsers 0 Instal
  • 当字段是数字时怎么说...在 mongodb 中匹配?

    所以我的结果中有一个名为 城市 的字段 结果已损坏 有时它是一个实际名称 有时它是一个数字 以下代码显示所有记录 db zips aggregate project city substr city 0 1 sort city 1 我需要修
  • Django 视图中的“请求”是什么

    在 Django 第一个应用程序的 Django 教程中 我们有 from django http import HttpResponse def index request return HttpResponse Hello world
  • pandas - 包含时间序列数据的堆积条形图

    我正在尝试使用时间序列数据在 pandas 中创建堆积条形图 DATE TYPE VOL 0 2010 01 01 Heavy 932 612903 1 2010 01 01 Light 370 612903 2 2010 01 01 Me
  • Python - 如何确定解析的 XML 元素的层次结构级别?

    我正在尝试使用 Python 解析 XML 文件中具有特定标记的元素并生成输出 excel 文档 该文档将包含元素并保留其层次结构 我的问题是我无法弄清楚每个元素 解析器在其上迭代 的嵌套深度 XML 示例摘录 3 个元素 它们可以任意嵌套
  • Python GTK+ 画布

    我目前正在通过 PyGobject 学习 GTK 需要画布之类的东西 我已经搜索了文档 发现两个小部件似乎可以完成这项工作 GtkDrawingArea 和 GtkLayout 我需要一些基本函数 如 fillrect 或 drawline
  • 找到一个数字所属的一组范围

    我有一个 200k 行的数字范围列表 例如开始位置 停止位置 该列表包括除了非重叠的重叠之外的所有类型的重叠 列表看起来像这样 3 5 10 30 15 25 5 15 25 35 我需要找到给定数字所属的范围 并对 100k 个数字重复该
  • 带有 LSTM 的 GridSearchCV/RandomizedSearchCV

    我一直在尝试通过 RandomizedSearchCV 调整 LSTM 的超参数 我的代码如下 X train X train reshape X train shape 0 1 X train shape 1 X test X test
  • 每当使用 import cv2 时 OpenCV 都会出错

    我在终端上使用 pip3 install opencv contrib python 安装了 cv2 并且它工作了 但是每当我尝试导入 cv2 或运行导入了 cv2 的 vscode 文件时 在 python IDLE 上它都会说 Trac
  • 如何将 Django 中的权限添加到模型并使用 shell 进行测试

    我在模型中添加了 Meta 类并同步了数据库 然后在 shell 中创建了一个对象 它返回 false 所以我真的无法理解错误在哪里或者缺少什么是否在其他文件中可能存在某种配置 class Employer User Employer in
  • 等待子进程使用 os.system

    我用了很多os system在 for 循环内调用创建后台进程 如何等待所有后台进程结束 os wait告诉我没有子进程 ps 我使用的是Solaris 这是我的代码 usr bin python import subprocess imp
  • 如何使用 PrimaryKeyRelatedField 更新多对多关系上的类别

    Django Rest 框架有一个主键相关字段 http www django rest framework org api guide relations primarykeyrelatedfield其中列出了我的 IDmany to m
  • 如何在 Flask 中的视图函数/会话之间传递复杂对象

    我正在编写一个 Web 应用程序 当 且仅当 用户登录时 该应用程序从第三方服务器接收大量数据 这些数据被解析为自定义对象并存储在list 现在 用户在应用程序中使用这些数据 调用不同的视图 例如发送不同的请求 我不确定什么是最好的模式在视

随机推荐