VS Code打開我們的工程文件夾:
新建一個文件:editor.py
首先既然要用到GUI,自然是要import包進來:
import sys
import os
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from ui_savemain import Ui_MainWindow
同時我們也導(dǎo)入自己制作的UI界面。
ui_savemain正是上一節(jié)中我們保存的py文件的名字。
那么怎么調(diào)用出來呢。
class SaveEditor(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
main_window = SaveEditor()
main_window.show()
app.exec()
新建一個類,多重繼承QMainWindow,Ui_MainWindow,然后實例化這個類,直接運行我們就能看到窗體了,同時能看到我們自己放的兩個按鈕。
我這里是后期效果了,前期效果沒有存圖。先放著吧。

首先讓我們來想想如何實現(xiàn)導(dǎo)入字符串的效果,把字符串輸入進去很容易,但是如何把字符串正確處理并且顯示圖片呢?這就是整個程序第一個核心難點。
雖然鼓勵大家獨立思考,但是我這里直接說吧。
首先我們知道樓層信息字符串包含很多$$$$$$,那么我們首先要處理掉$,然后每個數(shù)字對應(yīng)一個圖塊,那么我們只要建立121個(11*11)按鈕,把數(shù)字放進按鈕里面,顯示出來,然后點擊按鈕,可以更改數(shù)字,然后修改完了最后再輸出按鈕上的數(shù)字,然后再把分隔符$填充回去就可以了。
但是按鈕實在是太丑了,我們有別的東西可以利用嗎,可以,就是label,這個控件沒有邊框,可以顯示圖片,讓我們的界面美觀起來,但是label有個重大的缺陷:它本身不能被單擊事件響應(yīng)——或者說當(dāng)初GUI控件的作者就沒設(shè)計這個功能,我們曲線救國,讓label能夠響應(yīng)單擊事件:
這里的代碼不要求大家理解,簡單說一下就是自定義label的信號槽,讓他響應(yīng)單擊事件。
class MyQLabel(QLabel):
button_clicked_signal = Signal()
def __init__(self, parent=None):
super(MyQLabel, self).__init__(parent)
self.button_clicked_signal.connect(self.change_map)#綁定一個指定函數(shù),這個是后面要做的功能,先放進來
def mouseReleaseEvent(self, QMouseEvent):
self.button_clicked_signal.emit()
這樣label也準(zhǔn)備好了,讓我們開始編寫邏輯代碼。
仔細想一下,程序是不是應(yīng)該先把121個label放置到窗口里,然后再繪制地圖呢?
確實應(yīng)該是這樣,那么首先我們要確定label的坐標(biāo),足足有121個,讓我們借助range函數(shù)和for循環(huán)來計算出每個label的坐標(biāo)。
定位到主類,新建一個函數(shù)calculate_xy:
def calculate_xy(self):
xy_offset = 52 # 定義偏移量,因為label的坐標(biāo)并不是從(0,0)開始的
self.xy_list = []#用來存放坐標(biāo)值
for i1 in range(11):#循環(huán)11次
for i2 in range(11):#循環(huán)11次
y = i1 * 32#每次循環(huán)x和y都將*32
x = i2 * 32#因為每個label的大小是32*32,為了不重疊,每次要偏移32個像素
xy = (x + xy_offset, y + xy_offset)#把之前的偏移量加上
self.xy_list.append(xy)#把坐標(biāo)結(jié)果放到list里面
計算好之后,就應(yīng)該創(chuàng)建label了,新建一個函數(shù):
def setup_label(self):
self.label_list = [] # 用于存放label控件方便查找
for index in range(121): # 循環(huán)121次
object_name = "label_" + str(index) # 設(shè)定label的objectName方便我們后期查找
map_label = MyQLabel(self) # 實例化Label類,記得用之前繼承過的類
map_label.setObjectName(object_name) # 設(shè)定objectname
map_label.resize(32, 32) # 設(shè)定label大小
x = self.xy_list[index][0]
y = self.xy_list[index][1]
map_label.move(x, y) # 設(shè)定坐標(biāo)
self.label_list.append(map_label) # 把label放進去
定位到我們的主類,在里面新建一個函數(shù)draw_map
def draw_map(self, floor_str: str): # 傳一個參數(shù)進去,用于接受樓層信息字符串
split_floor = floor_str.split("$") # 處理掉分隔符,取出數(shù)字做成list
split_floor = split_floor[0:121] # 因為會有一個空元素,對list進行切片,去掉最后一個元素,其實直接刪除也可以
for index, text in enumerate(split_floor): # 進行迭代,enumerate函數(shù)會給每個list元素編號
label_widget = self.label_list[index] # 先取到對應(yīng)編號的label
image_path = os.path.join("images", text + ".png") # 提前準(zhǔn)備好了對應(yīng)數(shù)字的圖片文件
if os.path.exists(image_path): # 如果圖片存在
label_widget.setPixmap(QPixmap(image_path)) # 給label填充圖片
else:
label_widget.setPixmap(
QPixmap("images/missing.png")
) # 填充一個miss圖片進去來提醒我們這個數(shù)字圖塊沒有圖片
label_widget.setToolTip(text) # 同時設(shè)置鼠標(biāo)懸浮時候的提示框文本
# 把數(shù)字放到tooltip里面方便后期存取
# text變量是每個圖塊的數(shù)字
這樣我們繪圖部分就處理好了。這樣的話下一章我們來搞定輸入和輸出。