Python制作一个简单的抽奖软件(二)
认识QT
因为都对 QT和tkinter都没用过,之前简单使用tkinter后发现,界面调整不太好弄。然后度娘了之后,QT是强大GUI库之一,很多人都推荐它。重新选择QT进行尝试。于是,就使用了PYQT5,是QT的python版本。
https://www.riverbankcomputing.com/software/pyqt/download5
使用到的基础控件认识
QApplication
每一个QT程序都需要一个QApplication的对象,所以这个是第一个需要定义的:
app = QApplication(sys.argv)
其中sys.argv是传入的入参,当然我没有用的入参。
QWidget窗体
在QT内,所以可以显示的都是Qwidget的子类,所以需要定义一个对象。
Qwidget:
class MyApp(QWidget):
def __init__(self):
super(MyApp,self).__init__()
setWindowTitle
setWindowTitle 是设置窗口标题的名字:
self.setWindowTitle("2019年年会")
frameGeometry
frameGeometry 是坐标管理,允许我们创建一个无形矩形并根据主窗口的宽高设置自身的宽度与高度。简单理解就是获取这个控件(QWidget)的几何内容(宽高位置等)
我们可以通过这个来对窗口打开时在屏幕的位置进行初始化:
def move_center(self):
m = self.frameGeometry()
w = QDesktopWidget().availableGeometry()
w_center = w.center()
m.moveCenter(w_center)
QPalette()
QPalette 是QT的调色板,可以用个QPalette来进行背景图的设置:
def init_mainwindow(self):
self.main_p = QPalette()
self.main_p.setBrush(self.backgroundRole(),QBrush(QPixmap("beijing2.jpg")))
#self.main_p.setScaledContents(True)
self.setPalette(self.main_p)
也可以通过QPalette来对图片进行处理:这里的处理是对图片进行缩放,然后后面再刷图的时候回使用到
def scale_image(self,filename):
p_pal = QPalette()
img = QImage(filename)
size = QSize(self.prize.person_size[0], self.prize.person_size[1])
p_pal.setBrush(self.backgroundRole(), QBrush(QPixmap.fromImage(img.scaled(size, Qt.IgnoreAspectRatio))))
return p_pal
QLabel
QLabel对象作为一个占位符可以显示不可编辑的文本或者图片,也可以放一个gif动画,还可以作为一个提示标记作为其他控件,这个控件作用还是比较多的。
可以显示一段文本:这里显示了窗口里面的大小标题
字体的样式是可以进行设置的setFont,颜色也可以设置,move是需要放置的位置
def init_text(self):
self.title_show = QLabel(self)
self.title_show.setText(config.title_str)
self.title_show.setFont(QFont("Roman times",30,QFont.Bold))
self.title_show.setStyleSheet("color:red")
self.title_show.setScaledContents(True)
self.title_show.resize(900,40)
place = self.prize.getplace([0.4,0.01])
self.title_show.move(place[0], place[1])
当然如果显示一大段文本信息的话,可以设置换行setWordWrap,以及自适应lable大小setScaledContents:
setWordWrap(True)
setScaledContents(True)
也可以显示图片,这里面setToolTip是显示提示信息,setPalette设置具体的图片,setAlignment在这个控件的位置,setAutoFillBackground,显示图片的时候需要设置
def create_lable_photo(self, file, name, i):
label_ph = QLabel(self)
label_ph.setToolTip(name)
label_ph.setPalette(self.scale_image(file))
label_ph.setAlignment(Qt.AlignCenter)
label_ph.setScaledContents(True)
label_ph.setAutoFillBackground(True)
label_ph.setFont(self.btn_font)
label_ph.resize(self.prize.person_size[0],self.prize.person_size[1])
place = self.prize.show_place[i]
label_ph.move(place[0], place[1])
return label_ph
QPushButton
QPushButton 是按键控件,可以提供一个点击的按钮来触发摸一个事件,按键可以显示文字,也可以显示图片:
def init_button(self):
self.start_btn = QPushButton("PyQt5 Button", self)
self.start_btn.setText("长按开始第" + str(self.now_scroll_number + 1) + "个")
self.start_btn.setAutoRepeatDelay(0.01) // 设置自动长按触发的时间间隔
self.start_btn.setAutoRepeat(True) // 打开长按自动重复
#self.start_btn.clicked.connect(self.btn_start) // 点击触发事件
self.start_btn.pressed.connect(self.btn_start_once) // 按下触发事件
self.start_btn.released.connect(self.btn_hit_once) //释放按键触发事件
self.start_btn.setStyleSheet(self.btn_sty) //按键的相关样式
self.start_btn.setFont(self.btn_font) //文字样式
QHBoxLayout
QBoxLayout可以在水平方向或垂直方向上排列控件,由QHBoxLayout、QVBoxLayout所继承
我这里是有QBoxLayout对三个按键的布局进行了控制:
上下左右设置:AlignLeft 、AlignRight 、AlignCenter ,AlignBottom
def init_widget(self):
self.main_layout = QHBoxLayout()
self.main_layout.addWidget(self.chose_btn, 1, Qt.AlignLeft | Qt.AlignBottom)
self.main_layout.addWidget(self.start_btn, 1, Qt.AlignCenter | Qt.AlignBottom)
self.main_layout.addWidget(self.show_btn, 1, Qt.AlignRight | Qt.AlignBottom)
self.main_layout.setSpacing(1)
self.setGeometry(self.win_size[0], self.win_size[1], self.win_size[2], self.win_size[3])
self.setLayout(self.main_layout)
QMessageBox
QMessageBox是消息弹窗口
其中 提示信息的弹窗:
def show_no_person_msg(self):
QMessageBox.information(self, "!", "所有人都已经抽奖完")
其中 弹出询问选择的窗口:
res = QMessageBox.question(self, "抽奖完毕", "请确认是否认同此次抽奖", QMessageBox.Yes | QMessageBox.No)
if res== QMessageBox.Yes:
至此,QT5在本程序中使用到的相关基本控件就介绍完了。当然,还有音乐播放器和焦点变更没有提及,我也已经加了,因为家里的程序没有加上,所以这里就不介绍了。
抽奖程序中一些关键逻辑
OS
这部分是初始化参与抽奖的人,我这边将以人民命名的照片放到一个文件夹下面,这样初始化时,自动从文件夹下面读取,用的的是OS模块
def find_photo(self, path):
self.photos = {}
for file in os.listdir(path):
print(file)
file_path = os.path.join(path, file)
if os.path.isfile(file_path):
self.photos[self.filter_name(file)] = file_path
中文编码
相信很多人会遇到中文乱码的事情,
我这里是一开始使用的是 GB2312解码, 但是后面发现有一些中文GB2312,也不认识,后面又换成了GB18030
GBK支持简体中文和繁体中文
GB2312只支持简体中文,GBK里面包含了GB2312,用GBK比较多
GB18030是32位的,它支持简体中文、繁体中文 藏文、蒙文、*文等主要的少数民族文字
random
对于抽奖软件,大家肯定都是要关心随机抽取,我这里直接使用的是random模块:
random.shuffle(we_need_list)
这里面使用到的是 经典的洗牌算法 Knuth-Durstenfeld Shuffle,虽然仍然是伪随机,但是已经足够我们的场景了。关于真随机,主要是随机数种子的获取,就不复述了。
重复抽取
有时候会需要对已经抽奖的人进行去除,或者重新加入抽奖:
去除:主要是对参加抽奖的人的list中去掉对应的抽奖人使用的 list.remove
重新加入: 这里我主要是维护了另一个新的表,在初始化的时候,会对list进行深拷贝:
使用到的copy模块:
self.VIP_person = copy.deepcopy(self.join_person)
显示的中奖人图片位置
一开始我并没有使用QT自己的布局控件,是自己利用获取到的屏幕size,然后进行坐标换算,从而实现的自适应调整:
def calc_show_place(self, calc_list, line):
place_all = []
name_all = []
number = len(calc_list)
x_zone_sigle = (config.show_x_zone * self.window_size[0]) / number
new_start = config.show_x_place_start * self.window_size[0]
photo_new = self.person_size[0] / 2
for i in range(number):
center_place = new_start + (x_zone_sigle / 2)
new_place = [(center_place - photo_new), config.show_y_place_start[line] * self.window_size[1]]
place_all.append(new_place)
y_name_zone = config.show_name_place * self.window_size[1]
name_place = [(center_place - (config.name_size[0] /2)) , (y_name_zone + new_place[1] + self.person_size[1])]
name_all.append(name_place)
new_start += x_zone_sigle
return place_all, name_all
最后再贴一次我的最终效果图:
后续有时间,再对这个程序进行优化,完善。
参考
https://blog.****.net/jhj_666/article/details/77940872
https://blog.****.net/liang19890820/article/details/51537246
https://www.cnblogs.com/shokey520/p/3806628.html
其实还有很多,忘记了。。。