使用wxPython和pillow开发拼图小游戏(三)

上篇给大家展示了介绍了单格点击事件和判断拼图是否完成的具体实现,这篇我们继续,跟大家介绍一下导入本地图片来初始化游戏

导入本地图片来初始化游戏,首先我们要实现的是可以在界面上选择导入一张本地图片,因为我们的游戏界面是正方形的,所以准备的图片最好是正方形或接近于正方形,这样体验要过会更好一点。

wyPython提供了一种文件对话框FileDialog,可以使用该对话框选择相应的图片,使用方式如下:

# 第二个参数为对话框的标题,第三个标题为默认进入的目录
# 第四个参数为文件选择器,第四个参数是文件处理方式
dlg = wx.FileDialog(self, "Choose a file", dirname, "", "*.png", wx.FD_OPEN)
if dlg.ShowModal() == wx.ID_OK:  # 判断对话框点击的是否是确定按钮
    self.filename = dlg.GetFilename()  # 获取选择的文件名
    self.dirname = dlg.GetDirectory()  # 获取所选择文件所在的目录

拿到图片名称和目录后,首先我们要将图片加工成正方形,这样才做等分,然后需要对图片进行切割,根据我们选择难度(3*3,4*4,5*5,6*6)确定要切割的图片张数

# 使用pillow将图片转为正方图片
def fill_image(self, image):
    width, height = image.size
    new_image_length = width if width > height else height
    # 生成新图片[白底]
    new_image = Image.new(image.mode, (new_image_length, new_image_length), color='white')
    # 将之前的图粘贴在新图上,居中
    if width > height:  # 原图宽大于高,则填充图片的竖直维度
        # (x,y)二元组表示粘贴上图相对下图的起始位置
        new_image.paste(image, (0, int((new_image_length - height) / 2)))
    else:
        new_image.paste(image, (int((new_image_length - width) / 2), 0))
    return new_image
    
# 使用Pillow且图片
def cut_image(self, image):
    width, height = image.size
    item_width = int(width / self.vac)
    box_list = []
    for i in range(0, self.vac):  # 两重循环,生成self.vac*self.vac张图片基于原图的位置
        for j in range(0, self.vac):
            box = (j * item_width, i * item_width, (j + 1) * item_width, (i + 1) * item_width)
            box_list.append(box)
    image_list = [image.crop(box) for box in box_list]
    self.save_images(image_list)  # 将切割后生成的图片进行保存,切割后的图片按顺序使用编号进行命名

切割好图片之后,需要将切割后的图片加载到按钮上,并随机分布在各个方格中。在”使用wxPtyon和pillow开发拼图小游戏(一)”中显示数字,我们使用了wx.Button,这里加载图片时,我们将使用wx.BitmapButton

index = 0
for i in self.indices:
    btn = wx.BitmapButton(self.panel_1, i, size=(int(540 / self.vac), int(540 / self.vac)),
                          pos=(int(i % self.vac * (540 / self.vac)), int((i // self.vac) * (540 / self.vac))))
    self.bitmap1_onSize(btn, wx.Image('./Pic/' + str(index) + '.png', wx.BITMAP_TYPE_PNG))
    index += 1
    self.Bind(wx.EVT_BUTTON, self.OnClick, btn)  # 添加单击事件

以上介绍了很多,可能有点晕乎,下边我将这块完整的代码放在下边,供大家参考

def load_pic(self, e):
    result = self.select_image()
    if result == 0:  # 判断选择图片是否正常处理
        return
    self.step = 0
    self.step_label.SetLabelText('步数:' + str(self.step))  # 重置步数
    if self.time_thread:  # 停止计时的线程
        self.time_thread.setName('old_thread')
        self.__stopFlag = 'start'
    self.time_label.SetLabelText('耗时:' + str(0) + 's')
    self.random_init()
    self.panel_1.Destroy() # 清除原来的游戏区
    self.panel_1 = wx.Panel(self, 1, size=(540, 540), pos=(0, 0))
    index = 0
    for i in self.indices:  # 游戏区加载各个方格
        btn = wx.BitmapButton(self.panel_1, i, size=(int(540 / self.vac), int(540 / self.vac)),
                              pos=(int(i % self.vac * (540 / self.vac)), int((i // self.vac) * (540 / self.vac))))
        self.bitmap1_onSize(btn, wx.Image('./Pic/' + str(index) + '.png', wx.BITMAP_TYPE_PNG)) # 将完整的图片缩小展示在右边的按钮上
        index += 1
        self.Bind(wx.EVT_BUTTON, self.OnClick, btn) 
    self.load_flag = 1


# 选择图片
def select_image(self):
    dirname = "D:\壁纸"
    dlg = wx.FileDialog(self, "Choose a file", dirname, "", "*.png", wx.FD_OPEN)
    if dlg.ShowModal() == wx.ID_OK:
        self.filename = dlg.GetFilename()
        self.dirname = dlg.GetDirectory()
        image = Image.open(os.path.join(self.dirname, self.filename))
        image = self.fill_image(image)  # 填充图片,将图片转为正方形
        self.cut_image(image) # 切割图片
        self.bitmap1_onSize(self.temp_image_button, wx.Image(os.path.join(self.dirname, self.filename), wx.BITMAP_TYPE_PNG))  # 将完整的图片缩小展示在右边的按钮上
        return 1
    return 0

# 填充图片,将图片转为正方形
def fill_image(self, image):
    width, height = image.size
    # 选取长和宽中较大值作为新图片的边长
    new_image_length = width if width > height else height
    # 生成新图片[白底]
    new_image = Image.new(image.mode, (new_image_length, new_image_length), color='white')
    # 将之前的图粘贴在新图上,居中
    if width > height:  # 原图宽大于高,则填充图片的竖直维度
        # (x,y)二元组表示粘贴上图相对下图的起始位置
        new_image.paste(image, (0, int((new_image_length - height) / 2)))
    else:
        new_image.paste(image, (int((new_image_length - width) / 2), 0))
    return new_image

# 切割图片
def cut_image(self, image):
    width, height = image.size
    item_width = int(width / self.vac)
    box_list = []
    for i in range(0, self.vac):  # 两重循环,基于原图的位置生成self.vac*self.vac张图片
        for j in range(0, self.vac):
            box = (j * item_width, i * item_width, (j + 1) * item_width, (i + 1) * item_width)
            box_list.append(box)
    image_list = [image.crop(box) for box in box_list]
    self.save_images(image_list)

# 保存图片
def save_images(self, img_list):
    index = 0
    files_path = 'Pic'
    # 若文件夹不存在,则创建
    if not os.path.exists(files_path):
        os.makedirs(files_path)
    else:
        shutil.rmtree(files_path)
        os.makedirs(files_path)
    for img in img_list:
        img.save('./Pic/' + str(index) + '.png', 'PNG')
        index += 1

# 将wx.Image,转换为wx.Bitmap,展示在BitmapButton上
def bitmap1_onSize(self, bitmap, image):
    W, H = bitmap.Size
    if W > H:
        NewW = W
        NewH = W * H / W
    else:
        NewH = H
        NewW = H * W / H
    img = image.Scale(int(NewW), int(NewH))
    bitmap.SetBitmap(wx.Bitmap(img))

你可能感兴趣的:(wxPython,Pillow,Python)